ds-harness-remote 0.4.9 → 0.4.12
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/README.md +9 -4
- package/dist/client-runtime.d.ts +3 -0
- package/dist/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +46 -14
- package/dist/client-runtime.js.map +1 -1
- package/dist/client.github.js +1 -1
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/codex/domain.d.ts +4 -0
- package/dist/codex/domain.d.ts.map +1 -1
- package/dist/codex/domain.js +74 -1
- package/dist/codex/domain.js.map +1 -1
- package/dist/codex/method-policy.d.ts +2 -2
- package/dist/codex/permissions.d.ts +4 -0
- package/dist/codex/permissions.d.ts.map +1 -0
- package/dist/codex/permissions.js +21 -0
- package/dist/codex/permissions.js.map +1 -0
- package/dist/codex/virtual-harness.d.ts +14 -4
- package/dist/codex/virtual-harness.d.ts.map +1 -1
- package/dist/codex/virtual-harness.js +180 -73
- package/dist/codex/virtual-harness.js.map +1 -1
- package/dist/harness-version.d.ts +7 -0
- package/dist/harness-version.d.ts.map +1 -1
- package/dist/harness-version.js +16 -0
- package/dist/harness-version.js.map +1 -1
- package/dist/index.js +648 -319
- package/dist/index.js.map +4 -4
- package/dist/remote-api-proxy.d.ts.map +1 -1
- package/dist/remote-api-proxy.js +34 -1
- package/dist/remote-api-proxy.js.map +1 -1
- package/dist/server-api.d.ts.map +1 -1
- package/dist/server-api.js +4 -5
- package/dist/server-api.js.map +1 -1
- package/dist/service.d.ts +1 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +8 -4
- package/dist/service.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dsh-plugin.json +1 -1
- package/package.json +21 -21
package/dist/index.js
CHANGED
|
@@ -4055,6 +4055,10 @@ var HARNESS_API_TRANSFER_CHUNK_BYTES = 512 * 1024;
|
|
|
4055
4055
|
var CODEX_APP_TRANSFER_CHUNK_BYTES = 512 * 1024;
|
|
4056
4056
|
var MAX_HARNESS_API_TRANSFER_BYTES = 288 * 1024 * 1024;
|
|
4057
4057
|
var MAX_CODEX_APP_TRANSFER_BYTES = 288 * 1024 * 1024;
|
|
4058
|
+
var MAX_DEVICE_NAME_LENGTH = 128;
|
|
4059
|
+
var MAX_DEVICE_PLATFORM_LENGTH = 64;
|
|
4060
|
+
var MAX_DEVICE_VERSION_LENGTH = 64;
|
|
4061
|
+
var MAX_AUTH_TOKEN_LENGTH = 8 * 1024;
|
|
4058
4062
|
var SECURE_FRAGMENT_MAGIC = new Uint8Array([68, 83, 72, 70]);
|
|
4059
4063
|
var SECURE_FRAGMENT_VERSION = 1;
|
|
4060
4064
|
var SECURE_FRAGMENT_HEADER_BYTES = 17;
|
|
@@ -4138,6 +4142,73 @@ var messageTypeSchema = external_exports.enum(messageTypes);
|
|
|
4138
4142
|
var controlFrameTypeSchema = external_exports.enum(controlFrameTypes);
|
|
4139
4143
|
var uniqueStrings = (values) => new Set(values).size === values.length;
|
|
4140
4144
|
var uniqueNumbers = (values) => new Set(values).size === values.length;
|
|
4145
|
+
var utf8Length = (value) => new TextEncoder().encode(value).byteLength;
|
|
4146
|
+
var boundedUtf8Schema = (minimum, maximum) => external_exports.string().refine((value) => utf8Length(value) >= minimum && utf8Length(value) <= maximum);
|
|
4147
|
+
var deviceIdSchema = external_exports.string().refine((value) => /^[0-9A-HJKMNP-TV-Z]{26}$/iu.test(value) || /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(value), "Device ID must be a ULID or UUID.");
|
|
4148
|
+
var deviceNameSchema = boundedUtf8Schema(1, MAX_DEVICE_NAME_LENGTH).refine((value) => value.trim().length > 0, "Device name must contain visible text.");
|
|
4149
|
+
var devicePlatformSchema = external_exports.string().min(1).max(MAX_DEVICE_PLATFORM_LENGTH).regex(/^[a-z0-9][a-z0-9._-]*$/u);
|
|
4150
|
+
var identityKeySchema = external_exports.string().regex(/^[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$/u);
|
|
4151
|
+
var deviceVersionSchema = boundedUtf8Schema(1, MAX_DEVICE_VERSION_LENGTH);
|
|
4152
|
+
var authTokenSchema = boundedUtf8Schema(16, MAX_AUTH_TOKEN_LENGTH);
|
|
4153
|
+
var expiresAtSchema = external_exports.number().int().positive().safe();
|
|
4154
|
+
var hostDeviceDescriptorSchema = external_exports.object({
|
|
4155
|
+
deviceId: deviceIdSchema,
|
|
4156
|
+
name: deviceNameSchema,
|
|
4157
|
+
role: external_exports.literal("host"),
|
|
4158
|
+
platform: devicePlatformSchema,
|
|
4159
|
+
identityKey: identityKeySchema,
|
|
4160
|
+
clientVersion: deviceVersionSchema,
|
|
4161
|
+
harnessVersion: deviceVersionSchema.optional()
|
|
4162
|
+
}).strict();
|
|
4163
|
+
var clientDeviceDescriptorSchema = external_exports.object({
|
|
4164
|
+
deviceId: deviceIdSchema,
|
|
4165
|
+
name: deviceNameSchema,
|
|
4166
|
+
role: external_exports.literal("client"),
|
|
4167
|
+
platform: devicePlatformSchema,
|
|
4168
|
+
identityKey: identityKeySchema,
|
|
4169
|
+
clientVersion: deviceVersionSchema
|
|
4170
|
+
}).strict();
|
|
4171
|
+
var accountDeviceDescriptorSchema = external_exports.union([
|
|
4172
|
+
hostDeviceDescriptorSchema,
|
|
4173
|
+
clientDeviceDescriptorSchema
|
|
4174
|
+
]);
|
|
4175
|
+
var deviceRegistrationRequestSchema = external_exports.object({
|
|
4176
|
+
v: external_exports.literal(PROTOCOL_VERSION),
|
|
4177
|
+
device: accountDeviceDescriptorSchema
|
|
4178
|
+
}).strict();
|
|
4179
|
+
var hostRegistrationCodeRequestSchema = external_exports.object({
|
|
4180
|
+
v: external_exports.literal(PROTOCOL_VERSION),
|
|
4181
|
+
code: external_exports.string().regex(/^[A-Z0-9]{4}-[A-Z0-9]{4}$/u),
|
|
4182
|
+
device: hostDeviceDescriptorSchema
|
|
4183
|
+
}).strict();
|
|
4184
|
+
var deviceRefreshRequestSchema = external_exports.object({
|
|
4185
|
+
deviceId: deviceIdSchema,
|
|
4186
|
+
refreshToken: authTokenSchema
|
|
4187
|
+
}).strict();
|
|
4188
|
+
var deviceTokenPairSchema = external_exports.object({
|
|
4189
|
+
accessToken: authTokenSchema,
|
|
4190
|
+
accessTokenExpiresAt: expiresAtSchema,
|
|
4191
|
+
refreshToken: authTokenSchema,
|
|
4192
|
+
refreshTokenExpiresAt: expiresAtSchema
|
|
4193
|
+
}).strict();
|
|
4194
|
+
var browserAuthorizationExchangeRequestSchema = external_exports.object({
|
|
4195
|
+
v: external_exports.literal(PROTOCOL_VERSION),
|
|
4196
|
+
device: external_exports.object({
|
|
4197
|
+
deviceId: deviceIdSchema,
|
|
4198
|
+
name: deviceNameSchema,
|
|
4199
|
+
role: external_exports.literal("client"),
|
|
4200
|
+
platform: external_exports.literal("browser"),
|
|
4201
|
+
identityKey: identityKeySchema,
|
|
4202
|
+
clientVersion: deviceVersionSchema
|
|
4203
|
+
}).strict()
|
|
4204
|
+
}).strict();
|
|
4205
|
+
var browserAuthorizationExchangeResponseSchema = external_exports.object({
|
|
4206
|
+
accessToken: authTokenSchema,
|
|
4207
|
+
accessTokenExpiresAt: expiresAtSchema,
|
|
4208
|
+
refreshToken: authTokenSchema,
|
|
4209
|
+
refreshTokenExpiresAt: expiresAtSchema,
|
|
4210
|
+
account: boundedUtf8Schema(1, 254).refine((value) => value.trim().length > 0)
|
|
4211
|
+
}).strict();
|
|
4141
4212
|
var remoteMessageSchema = external_exports.object({
|
|
4142
4213
|
v: external_exports.literal(PROTOCOL_VERSION),
|
|
4143
4214
|
id: external_exports.string().min(1),
|
|
@@ -13906,8 +13977,51 @@ function uuidV7(now = Date.now()) {
|
|
|
13906
13977
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
13907
13978
|
}
|
|
13908
13979
|
|
|
13980
|
+
// src/harness-version.ts
|
|
13981
|
+
import { readFile } from "node:fs/promises";
|
|
13982
|
+
import { dirname, isAbsolute, join } from "node:path";
|
|
13983
|
+
var LEGACY_PLACEHOLDER_VERSION = "0.0.1";
|
|
13984
|
+
function normalizeHarnessVersion(value) {
|
|
13985
|
+
if (typeof value !== "string") return void 0;
|
|
13986
|
+
const version = value.trim();
|
|
13987
|
+
if (version.length === 0 || version.length > 64 || /[\u0000-\u001f]/u.test(version)) return void 0;
|
|
13988
|
+
return version;
|
|
13989
|
+
}
|
|
13990
|
+
function selectHarnessVersion(reportedVersion, distributionVersion) {
|
|
13991
|
+
if (reportedVersion !== void 0 && reportedVersion !== LEGACY_PLACEHOLDER_VERSION) return reportedVersion;
|
|
13992
|
+
return distributionVersion;
|
|
13993
|
+
}
|
|
13994
|
+
function harnessSessionGeneration(version) {
|
|
13995
|
+
if (version === void 0) return "legacy";
|
|
13996
|
+
const match = /^(?:dsh-)?v?(\d+)\.(\d+)\.(\d+)(?:-|$)/u.exec(version.trim());
|
|
13997
|
+
if (match === null) return "legacy";
|
|
13998
|
+
const major = Number(match[1]);
|
|
13999
|
+
const minor = Number(match[2]);
|
|
14000
|
+
const patch = Number(match[3]);
|
|
14001
|
+
return major === 0 && minor === 1 && patch >= 5 ? "v3" : "legacy";
|
|
14002
|
+
}
|
|
14003
|
+
async function readHarnessDistributionVersion(entrypoint = process.argv[1]) {
|
|
14004
|
+
if (entrypoint === void 0 || !isAbsolute(entrypoint)) return void 0;
|
|
14005
|
+
let directory = dirname(entrypoint);
|
|
14006
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
14007
|
+
try {
|
|
14008
|
+
const manifest = JSON.parse(await readFile(join(directory, "package.json"), "utf8"));
|
|
14009
|
+
if (manifest.name === "@deepseek-ai/dsh") return normalizeHarnessVersion(manifest.version);
|
|
14010
|
+
} catch {
|
|
14011
|
+
}
|
|
14012
|
+
const parent = dirname(directory);
|
|
14013
|
+
if (parent === directory) break;
|
|
14014
|
+
directory = parent;
|
|
14015
|
+
}
|
|
14016
|
+
return void 0;
|
|
14017
|
+
}
|
|
14018
|
+
|
|
13909
14019
|
// src/remote-api-proxy.ts
|
|
13910
14020
|
var DIRECT_API_CALL_BYTES = 2 * 1024 * 1024;
|
|
14021
|
+
var AGENT_PRESET_SETTINGS_NS = "agent-presets";
|
|
14022
|
+
var LEGACY_AGENT_PRESET_ALIASES = {
|
|
14023
|
+
code: "ptc"
|
|
14024
|
+
};
|
|
13911
14025
|
var RemoteHarnessApiProxy = class {
|
|
13912
14026
|
constructor(client) {
|
|
13913
14027
|
this.client = client;
|
|
@@ -13996,7 +14110,7 @@ var RemoteHarnessApiProxy = class {
|
|
|
13996
14110
|
const params = {
|
|
13997
14111
|
method,
|
|
13998
14112
|
rpcId: String(request.rpcId),
|
|
13999
|
-
payload: request.payload
|
|
14113
|
+
payload: normalizeLegacyRequest(method, request.payload)
|
|
14000
14114
|
};
|
|
14001
14115
|
const encoded = new TextEncoder().encode(JSON.stringify(params));
|
|
14002
14116
|
const response = method === "session.attachment" || encoded.byteLength > DIRECT_API_CALL_BYTES ? await this.callTransferred(encoded, signal) : await this.client.rpc("harness.api.call", params, signal);
|
|
@@ -14108,9 +14222,32 @@ function normalizeLegacyResponse(method, response) {
|
|
|
14108
14222
|
}
|
|
14109
14223
|
};
|
|
14110
14224
|
}
|
|
14225
|
+
function normalizeLegacyRequest(method, payload) {
|
|
14226
|
+
if (!isRecord2(payload)) return payload;
|
|
14227
|
+
if (method === "agentPreset.read") return replaceAgentPreset(payload, "agentPreset");
|
|
14228
|
+
if (method === "agentPreset.select") return replaceAgentPreset(payload, "agentPreset");
|
|
14229
|
+
if (method === "agentPreset.copy") return replaceAgentPreset(payload, "from");
|
|
14230
|
+
if (method === "settings.update" || method === "settings.replace" || method === "settings.mutate") {
|
|
14231
|
+
return replaceAgentPresetSettings(payload);
|
|
14232
|
+
}
|
|
14233
|
+
return payload;
|
|
14234
|
+
}
|
|
14235
|
+
function replaceAgentPreset(payload, key) {
|
|
14236
|
+
const value = payload[key];
|
|
14237
|
+
const replacement = typeof value === "string" ? LEGACY_AGENT_PRESET_ALIASES[value] : void 0;
|
|
14238
|
+
return replacement === void 0 ? payload : { ...payload, [key]: replacement };
|
|
14239
|
+
}
|
|
14240
|
+
function replaceAgentPresetSettings(payload) {
|
|
14241
|
+
if (payload.ns !== AGENT_PRESET_SETTINGS_NS || !isRecord2(payload.patch)) return payload;
|
|
14242
|
+
const patch = replaceAgentPreset(payload.patch, "default");
|
|
14243
|
+
return patch === payload.patch ? payload : { ...payload, patch };
|
|
14244
|
+
}
|
|
14111
14245
|
function isRemoteDisconnect(error) {
|
|
14112
14246
|
return error instanceof RemoteClientError && (error.code === "TRANSPORT_CLOSED" || error.code === "CLIENT_CLOSED");
|
|
14113
14247
|
}
|
|
14248
|
+
function isRecord2(value) {
|
|
14249
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14250
|
+
}
|
|
14114
14251
|
var AsyncFrameQueue = class {
|
|
14115
14252
|
values = [];
|
|
14116
14253
|
waiters = [];
|
|
@@ -14345,16 +14482,16 @@ function routeStreamEvent2(event, streamId, queue) {
|
|
|
14345
14482
|
queue.fail(remoteFailure({
|
|
14346
14483
|
code: typeof failure2?.code === "string" ? failure2.code : "internal",
|
|
14347
14484
|
message: typeof failure2?.message === "string" ? failure2.message : "The remote Harness stream failed.",
|
|
14348
|
-
details:
|
|
14485
|
+
details: isRecord3(failure2?.details) ? failure2.details : {}
|
|
14349
14486
|
}));
|
|
14350
14487
|
} else {
|
|
14351
14488
|
queue.close();
|
|
14352
14489
|
}
|
|
14353
14490
|
}
|
|
14354
14491
|
function parseRpcResult(value) {
|
|
14355
|
-
if (!
|
|
14492
|
+
if (!isRecord3(value)) throw new Error("The remote Host returned an invalid Gateway result.");
|
|
14356
14493
|
if (value.ok === true) return Object.hasOwn(value, "value") ? { ok: true, value: value.value } : { ok: true };
|
|
14357
|
-
if (value.ok !== false || !
|
|
14494
|
+
if (value.ok !== false || !isRecord3(value.error) || typeof value.error.code !== "string" || typeof value.error.message !== "string" || !isRecord3(value.error.details)) {
|
|
14358
14495
|
throw new Error("The remote Host returned an invalid Gateway failure.");
|
|
14359
14496
|
}
|
|
14360
14497
|
return {
|
|
@@ -14388,13 +14525,32 @@ function base64ToBytes3(value) {
|
|
|
14388
14525
|
if (bytesToBase643(bytes) !== value) throw new Error("The remote Host returned non-canonical Harness Remote transfer data.");
|
|
14389
14526
|
return bytes;
|
|
14390
14527
|
}
|
|
14391
|
-
function
|
|
14528
|
+
function isRecord3(value) {
|
|
14392
14529
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14393
14530
|
}
|
|
14394
14531
|
function hasErrorCode(error, code) {
|
|
14395
14532
|
return error instanceof Error && "code" in error && error.code === code;
|
|
14396
14533
|
}
|
|
14397
14534
|
|
|
14535
|
+
// src/codex/permissions.ts
|
|
14536
|
+
function codexPermissionPresetFromResponse(value) {
|
|
14537
|
+
const root = record(value);
|
|
14538
|
+
for (const settings of [root, record(root.threadSettings)]) {
|
|
14539
|
+
const sandbox = settings.sandbox ?? settings.sandboxPolicy;
|
|
14540
|
+
const type = record(sandbox).type;
|
|
14541
|
+
if (settings.approvalPolicy === "never" && (sandbox === "danger-full-access" || type === "dangerFullAccess")) {
|
|
14542
|
+
return "danger-full-access";
|
|
14543
|
+
}
|
|
14544
|
+
if (settings.approvalPolicy === "on-request" && (sandbox === "workspace-write" || type === "workspaceWrite")) {
|
|
14545
|
+
return "workspace-write";
|
|
14546
|
+
}
|
|
14547
|
+
}
|
|
14548
|
+
return void 0;
|
|
14549
|
+
}
|
|
14550
|
+
function record(value) {
|
|
14551
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
14552
|
+
}
|
|
14553
|
+
|
|
14398
14554
|
// src/codex/virtual-harness.ts
|
|
14399
14555
|
var CODEX_SESSION_PREFIX = "codex:";
|
|
14400
14556
|
var CODEX_WORKSPACE_PREFIX = "codex-workspace:";
|
|
@@ -14420,9 +14576,10 @@ async function discoverCodexVirtualWorkspaces(client, signal) {
|
|
|
14420
14576
|
return (await loadCatalog(client, signal)).workspaces;
|
|
14421
14577
|
}
|
|
14422
14578
|
var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
14423
|
-
constructor(client, host) {
|
|
14579
|
+
constructor(client, host, sessionGeneration = "legacy") {
|
|
14424
14580
|
this.client = client;
|
|
14425
14581
|
this.host = host;
|
|
14582
|
+
this.sessionGeneration = sessionGeneration;
|
|
14426
14583
|
this.api = this.createApiProxy();
|
|
14427
14584
|
}
|
|
14428
14585
|
api;
|
|
@@ -14446,8 +14603,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14446
14603
|
commandSeq = 0;
|
|
14447
14604
|
selectedWorkspaceId;
|
|
14448
14605
|
closed = false;
|
|
14449
|
-
static remote(core, host) {
|
|
14450
|
-
return new _CodexVirtualHarness(new CodexRemoteClient(core), host);
|
|
14606
|
+
static remote(core, host, sessionGeneration = "legacy") {
|
|
14607
|
+
return new _CodexVirtualHarness(new CodexRemoteClient(core), host, sessionGeneration);
|
|
14451
14608
|
}
|
|
14452
14609
|
async workspaces(signal) {
|
|
14453
14610
|
return (await this.refreshCatalog(signal)).workspaces;
|
|
@@ -14643,10 +14800,11 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14643
14800
|
return this.selectedModels.get(sessionId) ?? directory?.default ?? modelSelection();
|
|
14644
14801
|
}
|
|
14645
14802
|
permissionSelection(sessionId) {
|
|
14646
|
-
return this.selectedPermissions.get(sessionId)
|
|
14803
|
+
return this.selectedPermissions.get(sessionId);
|
|
14647
14804
|
}
|
|
14648
14805
|
setPermissionSelection(sessionId, preset) {
|
|
14649
|
-
this.selectedPermissions.
|
|
14806
|
+
if (preset === void 0) this.selectedPermissions.delete(sessionId);
|
|
14807
|
+
else this.selectedPermissions.set(sessionId, preset);
|
|
14650
14808
|
this.publishProjection(sessionId, "permissions", codexPermissionsProjection(preset), this.nextProjectionSeq());
|
|
14651
14809
|
}
|
|
14652
14810
|
commandList(args) {
|
|
@@ -14670,17 +14828,22 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14670
14828
|
result: { kind: "error", text: "CodeX Remote permission commands do not accept attachments." }
|
|
14671
14829
|
};
|
|
14672
14830
|
const requested = (match[1] ?? "").trim();
|
|
14673
|
-
if (requested === "")
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14831
|
+
if (requested === "") {
|
|
14832
|
+
await this.readHistoryPage(threadId, { maxMessages: 1 }, signal);
|
|
14833
|
+
return {
|
|
14834
|
+
commandId,
|
|
14835
|
+
result: { kind: "success", text: `current preset ${this.permissionSelection(sessionId) ?? "Host settings (not reported)"}` }
|
|
14836
|
+
};
|
|
14837
|
+
}
|
|
14677
14838
|
if (!isCodexPermissionPreset(requested)) return {
|
|
14678
14839
|
commandId,
|
|
14679
14840
|
result: { kind: "error", text: `unknown preset "${requested}" (available: workspace-write, danger-full-access)` }
|
|
14680
14841
|
};
|
|
14681
14842
|
const result = await this.client.request("thread/resume", { threadId, permissionPreset: requested }, signal);
|
|
14682
|
-
const effective = codexPermissionPresetFromResponse(result)
|
|
14843
|
+
const effective = codexPermissionPresetFromResponse(result);
|
|
14844
|
+
if (effective === void 0) throw new Error("The Host did not confirm the CodeX permission preset.");
|
|
14683
14845
|
this.setPermissionSelection(sessionId, effective);
|
|
14846
|
+
if (effective !== requested) throw new Error("The Host did not apply the requested CodeX permission preset.");
|
|
14684
14847
|
return { commandId, result: { kind: "success", text: `preset ${effective}` } };
|
|
14685
14848
|
}
|
|
14686
14849
|
sessionTitle(sessionId) {
|
|
@@ -14812,7 +14975,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14812
14975
|
return queue.iterate(() => this.eventStreams.delete(clientId));
|
|
14813
14976
|
}
|
|
14814
14977
|
async sessionFollow(request, signal) {
|
|
14815
|
-
const sessionId = sessionIdFromAddress(
|
|
14978
|
+
const sessionId = sessionIdFromAddress(record2(request.address));
|
|
14816
14979
|
const threadId = nativeThreadId(sessionId);
|
|
14817
14980
|
const history = await this.readHistoryPage(threadId, {
|
|
14818
14981
|
maxMessages: optionalPositiveInteger(request.maxMessages)
|
|
@@ -14831,6 +14994,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14831
14994
|
streamedBlocks: /* @__PURE__ */ new Map(),
|
|
14832
14995
|
nextBlockIndex: 0,
|
|
14833
14996
|
streamActive: false,
|
|
14997
|
+
assistantStreamRevision: 0,
|
|
14834
14998
|
liveItems: /* @__PURE__ */ new Map(),
|
|
14835
14999
|
liveToolOutput: /* @__PURE__ */ new Map(),
|
|
14836
15000
|
liveToolResultSeq: /* @__PURE__ */ new Map(),
|
|
@@ -14854,7 +15018,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14854
15018
|
permissions: codexPermissionsProjection(this.permissionSelection(sessionId)),
|
|
14855
15019
|
imageLimits: codexImageLimitsProjection()
|
|
14856
15020
|
}
|
|
14857
|
-
}
|
|
15021
|
+
},
|
|
15022
|
+
...this.sessionGeneration === "v3" ? { assistantStream: { revision: 0 } } : {}
|
|
14858
15023
|
});
|
|
14859
15024
|
try {
|
|
14860
15025
|
const stream = await this.client.subscribe(
|
|
@@ -14875,7 +15040,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14875
15040
|
});
|
|
14876
15041
|
}
|
|
14877
15042
|
acceptCodexFrame(follow, frame) {
|
|
14878
|
-
const params =
|
|
15043
|
+
const params = record2(frame.params);
|
|
14879
15044
|
if (frame.method === "thread/name/updated") {
|
|
14880
15045
|
const name2 = string(params.threadName);
|
|
14881
15046
|
if (name2 === void 0) return;
|
|
@@ -14887,11 +15052,12 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14887
15052
|
}
|
|
14888
15053
|
if (frame.method === "thread/settings/updated") {
|
|
14889
15054
|
const preset = codexPermissionPresetFromResponse(params);
|
|
14890
|
-
|
|
15055
|
+
this.setPermissionSelection(follow.sessionId, preset);
|
|
14891
15056
|
return;
|
|
14892
15057
|
}
|
|
14893
15058
|
if (frame.method === "turn/started") {
|
|
14894
|
-
const turn =
|
|
15059
|
+
const turn = record2(params.turn);
|
|
15060
|
+
this.endAssistantAttempt(follow, { kind: "abandoned" });
|
|
14895
15061
|
this.resetLiveTurn(follow);
|
|
14896
15062
|
follow.turn += 1;
|
|
14897
15063
|
follow.activeTurnId = string(turn.id);
|
|
@@ -14900,11 +15066,11 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14900
15066
|
this.pushEvent(follow, "turn/start", { turn: follow.turn });
|
|
14901
15067
|
this.pushEvent(follow, "step/start", { turn: follow.turn, step: 1 });
|
|
14902
15068
|
this.emitRemoteEvent("api-session/status", [follow.sessionId, true]);
|
|
14903
|
-
for (const item of array(turn.items)) this.acceptCompletedItem(follow,
|
|
15069
|
+
for (const item of array(turn.items)) this.acceptCompletedItem(follow, record2(item), false);
|
|
14904
15070
|
return;
|
|
14905
15071
|
}
|
|
14906
15072
|
if (frame.method === "item/started" || frame.method === "item/completed") {
|
|
14907
|
-
const item =
|
|
15073
|
+
const item = record2(params.item);
|
|
14908
15074
|
const itemId = string(item.id);
|
|
14909
15075
|
if (frame.method === "item/started" && itemId !== void 0) {
|
|
14910
15076
|
follow.startedItems.add(itemId);
|
|
@@ -14941,7 +15107,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14941
15107
|
}
|
|
14942
15108
|
if (frame.method === "turn/plan/updated") {
|
|
14943
15109
|
const todos = array(params.plan).flatMap((value) => {
|
|
14944
|
-
const item =
|
|
15110
|
+
const item = record2(value);
|
|
14945
15111
|
const content = string(item.step);
|
|
14946
15112
|
if (content === void 0) return [];
|
|
14947
15113
|
const status2 = item.status === "inProgress" ? "in_progress" : item.status === "completed" ? "completed" : "pending";
|
|
@@ -14975,7 +15141,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14975
15141
|
return;
|
|
14976
15142
|
}
|
|
14977
15143
|
if (frame.method === "thread/status/changed") {
|
|
14978
|
-
const status2 =
|
|
15144
|
+
const status2 = record2(params.status);
|
|
14979
15145
|
const running = status2.type === "active";
|
|
14980
15146
|
this.emitRemoteEvent("api-session/status", [follow.sessionId, running]);
|
|
14981
15147
|
if (status2.type === "systemError") {
|
|
@@ -15002,11 +15168,12 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15002
15168
|
return;
|
|
15003
15169
|
}
|
|
15004
15170
|
if (frame.method === "turn/completed") {
|
|
15005
|
-
const turn =
|
|
15006
|
-
for (const item of array(turn.items)) this.acceptCompletedItem(follow,
|
|
15171
|
+
const turn = record2(params.turn);
|
|
15172
|
+
for (const item of array(turn.items)) this.acceptCompletedItem(follow, record2(item), true);
|
|
15007
15173
|
if (follow.stepOpen) {
|
|
15008
15174
|
this.closeAllStreamBlocks(follow);
|
|
15009
15175
|
if (follow.streamActive) this.finishStream(follow);
|
|
15176
|
+
this.endAssistantAttempt(follow, { kind: "abandoned" });
|
|
15010
15177
|
this.pushEvent(follow, "step/end", { turn: follow.turn, step: 1 });
|
|
15011
15178
|
follow.stepOpen = false;
|
|
15012
15179
|
}
|
|
@@ -15045,6 +15212,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15045
15212
|
this.closeItemStreamBlocks(follow, itemId, itemText2(item));
|
|
15046
15213
|
if (type === "agentMessage" && follow.streamActive && follow.streamedBlocks.size === 0) this.finishStream(follow);
|
|
15047
15214
|
const supplementalImages = type === "agentMessage" ? follow.pendingToolImages : [];
|
|
15215
|
+
let assistantMessageSeq;
|
|
15048
15216
|
for (const event of itemEvents(
|
|
15049
15217
|
item,
|
|
15050
15218
|
follow.turn,
|
|
@@ -15056,7 +15224,17 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15056
15224
|
)) {
|
|
15057
15225
|
if (event.type === "tool/call" && follow.startedItems.has(itemId)) continue;
|
|
15058
15226
|
if (event.type === "tool/result") this.pushToolResult(follow, itemId, event);
|
|
15059
|
-
else
|
|
15227
|
+
else {
|
|
15228
|
+
const seq = this.pushEvent(follow, event.type, event.data, event.view);
|
|
15229
|
+
if (event.type === "assistant/message") assistantMessageSeq = seq;
|
|
15230
|
+
}
|
|
15231
|
+
}
|
|
15232
|
+
if (type === "agentMessage" && assistantMessageSeq !== void 0) {
|
|
15233
|
+
this.endAssistantAttempt(follow, {
|
|
15234
|
+
kind: "committed",
|
|
15235
|
+
eventType: "assistant/message",
|
|
15236
|
+
seq: assistantMessageSeq
|
|
15237
|
+
});
|
|
15060
15238
|
}
|
|
15061
15239
|
if (type === "agentMessage" && supplementalImages.length > 0) follow.pendingToolImages = [];
|
|
15062
15240
|
else if (type !== void 0 && isToolItemType2(type)) {
|
|
@@ -15073,18 +15251,21 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15073
15251
|
type,
|
|
15074
15252
|
seq,
|
|
15075
15253
|
time: Date.now(),
|
|
15076
|
-
data
|
|
15254
|
+
data: adaptEventData(
|
|
15255
|
+
type,
|
|
15256
|
+
type === "assistant/message" && this.sessionGeneration === "v3" && follow.assistantAttempt !== void 0 ? { ...record2(data), stream: follow.assistantAttempt.stream } : data,
|
|
15257
|
+
this.sessionGeneration
|
|
15258
|
+
),
|
|
15077
15259
|
...isSurfaceEvent(type) ? placement === void 0 ? { surfaceOp: "append" } : {
|
|
15078
|
-
surfaceOp: { op: "replace", start: placement.replaceSeq, end: placement.replaceSeq },
|
|
15260
|
+
surfaceOp: this.sessionGeneration === "v3" ? { op: "replace", startSeq: placement.replaceSeq, endSeq: placement.replaceSeq } : { op: "replace", start: placement.replaceSeq, end: placement.replaceSeq },
|
|
15079
15261
|
sourceEventSeqs: [placement.replaceSeq]
|
|
15080
15262
|
} : {}
|
|
15081
15263
|
};
|
|
15082
15264
|
this.cacheImageBlocks(follow.sessionId, event.data);
|
|
15083
15265
|
if (!follow.rcOnly) {
|
|
15084
|
-
const alphaEvent = typeof event.surfaceOp === "object" ? { ...event, surfaceOp: "replace" } : event;
|
|
15085
15266
|
follow.queue.push({
|
|
15086
15267
|
type: "event",
|
|
15087
|
-
event
|
|
15268
|
+
event,
|
|
15088
15269
|
...view === void 0 ? {} : { view }
|
|
15089
15270
|
});
|
|
15090
15271
|
}
|
|
@@ -15098,7 +15279,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15098
15279
|
}
|
|
15099
15280
|
cacheImageBlocks(sessionId, value) {
|
|
15100
15281
|
for (const block of collectImageBlocks(value)) {
|
|
15101
|
-
const attachment =
|
|
15282
|
+
const attachment = record2(block.attachment);
|
|
15102
15283
|
const attachmentId = string(attachment.attachmentId);
|
|
15103
15284
|
const data = string(block.data);
|
|
15104
15285
|
if (attachmentId === void 0 || data === void 0 || !attachmentId.startsWith(CODEX_IMAGE_ATTACHMENT_PREFIX)) continue;
|
|
@@ -15111,52 +15292,105 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15111
15292
|
const block = { itemId, index: follow.nextBlockIndex++, kind, text: "" };
|
|
15112
15293
|
follow.streamedBlocks.set(key, block);
|
|
15113
15294
|
follow.streamActive = true;
|
|
15114
|
-
this.
|
|
15115
|
-
turn: follow.turn,
|
|
15116
|
-
step: 1,
|
|
15117
|
-
chunk: { type: "block-start", index: block.index, blockType: kind }
|
|
15118
|
-
});
|
|
15295
|
+
this.pushAssistantChunk(follow, { type: "block-start", index: block.index, blockType: kind });
|
|
15119
15296
|
return block;
|
|
15120
15297
|
}
|
|
15121
15298
|
appendStreamDelta(follow, key, itemId, kind, delta) {
|
|
15122
15299
|
const block = this.ensureStreamBlock(follow, key, itemId, kind);
|
|
15123
15300
|
block.text = appendBoundedText(block.text, delta);
|
|
15124
|
-
this.
|
|
15125
|
-
|
|
15126
|
-
|
|
15127
|
-
|
|
15301
|
+
this.pushAssistantChunk(follow, {
|
|
15302
|
+
type: kind === "reasoning" ? "reasoning-delta" : "text-delta",
|
|
15303
|
+
index: block.index,
|
|
15304
|
+
text: delta
|
|
15128
15305
|
});
|
|
15129
15306
|
}
|
|
15130
15307
|
closeItemStreamBlocks(follow, itemId, fallback) {
|
|
15131
15308
|
const matches = [...follow.streamedBlocks].filter(([, block]) => block.itemId === itemId);
|
|
15132
15309
|
for (const [key, block] of matches) {
|
|
15133
15310
|
const text = block.text || fallback || "";
|
|
15134
|
-
this.
|
|
15135
|
-
|
|
15136
|
-
|
|
15137
|
-
|
|
15311
|
+
this.pushAssistantChunk(follow, {
|
|
15312
|
+
type: "block-end",
|
|
15313
|
+
index: block.index,
|
|
15314
|
+
block: { type: block.kind, text }
|
|
15138
15315
|
});
|
|
15139
15316
|
follow.streamedBlocks.delete(key);
|
|
15140
15317
|
}
|
|
15141
15318
|
}
|
|
15142
15319
|
closeAllStreamBlocks(follow) {
|
|
15143
15320
|
for (const block of follow.streamedBlocks.values()) {
|
|
15144
|
-
this.
|
|
15145
|
-
|
|
15146
|
-
|
|
15147
|
-
|
|
15321
|
+
this.pushAssistantChunk(follow, {
|
|
15322
|
+
type: "block-end",
|
|
15323
|
+
index: block.index,
|
|
15324
|
+
block: { type: block.kind, text: block.text }
|
|
15148
15325
|
});
|
|
15149
15326
|
}
|
|
15150
15327
|
follow.streamedBlocks.clear();
|
|
15151
15328
|
}
|
|
15152
15329
|
finishStream(follow) {
|
|
15153
|
-
this.
|
|
15154
|
-
turn: follow.turn,
|
|
15155
|
-
step: 1,
|
|
15156
|
-
chunk: { type: "finish", reason: { kind: "stop" } }
|
|
15157
|
-
});
|
|
15330
|
+
this.pushAssistantChunk(follow, { type: "finish", reason: { kind: "stop" } });
|
|
15158
15331
|
follow.streamActive = false;
|
|
15159
15332
|
}
|
|
15333
|
+
pushAssistantChunk(follow, chunk) {
|
|
15334
|
+
if (this.sessionGeneration !== "v3" || follow.rcOnly === true) {
|
|
15335
|
+
this.pushEvent(follow, "assistant/chunk", { turn: follow.turn, step: 1, chunk });
|
|
15336
|
+
return;
|
|
15337
|
+
}
|
|
15338
|
+
let attempt = follow.assistantAttempt;
|
|
15339
|
+
if (attempt === void 0) {
|
|
15340
|
+
attempt = {
|
|
15341
|
+
attemptId: `codex-attempt:${follow.activeTurnId ?? follow.turn}:${follow.nextSeq}`,
|
|
15342
|
+
startedAfterSeq: follow.nextSeq - 1,
|
|
15343
|
+
nextIndex: 0,
|
|
15344
|
+
stream: []
|
|
15345
|
+
};
|
|
15346
|
+
follow.assistantAttempt = attempt;
|
|
15347
|
+
follow.assistantStreamRevision += 1;
|
|
15348
|
+
follow.queue.push({
|
|
15349
|
+
type: "assistant-stream",
|
|
15350
|
+
frame: {
|
|
15351
|
+
type: "start",
|
|
15352
|
+
attemptId: attempt.attemptId,
|
|
15353
|
+
revision: follow.assistantStreamRevision,
|
|
15354
|
+
startedAfterSeq: attempt.startedAfterSeq,
|
|
15355
|
+
turn: follow.turn,
|
|
15356
|
+
step: 1
|
|
15357
|
+
}
|
|
15358
|
+
});
|
|
15359
|
+
}
|
|
15360
|
+
const time = Date.now();
|
|
15361
|
+
const index = attempt.nextIndex++;
|
|
15362
|
+
attempt.stream.push({ time, chunk });
|
|
15363
|
+
follow.assistantStreamRevision += 1;
|
|
15364
|
+
follow.queue.push({
|
|
15365
|
+
type: "assistant-stream",
|
|
15366
|
+
frame: {
|
|
15367
|
+
type: "chunk",
|
|
15368
|
+
attemptId: attempt.attemptId,
|
|
15369
|
+
revision: follow.assistantStreamRevision,
|
|
15370
|
+
index,
|
|
15371
|
+
time,
|
|
15372
|
+
chunk
|
|
15373
|
+
}
|
|
15374
|
+
});
|
|
15375
|
+
}
|
|
15376
|
+
endAssistantAttempt(follow, outcome) {
|
|
15377
|
+
const attempt = follow.assistantAttempt;
|
|
15378
|
+
if (attempt === void 0) return;
|
|
15379
|
+
follow.assistantAttempt = void 0;
|
|
15380
|
+
follow.assistantStreamRevision += 1;
|
|
15381
|
+
if (this.sessionGeneration === "v3" && follow.rcOnly !== true) {
|
|
15382
|
+
follow.queue.push({
|
|
15383
|
+
type: "assistant-stream",
|
|
15384
|
+
frame: {
|
|
15385
|
+
type: "end",
|
|
15386
|
+
attemptId: attempt.attemptId,
|
|
15387
|
+
revision: follow.assistantStreamRevision,
|
|
15388
|
+
index: attempt.nextIndex,
|
|
15389
|
+
outcome
|
|
15390
|
+
}
|
|
15391
|
+
});
|
|
15392
|
+
}
|
|
15393
|
+
}
|
|
15160
15394
|
ensureToolStarted(follow, item) {
|
|
15161
15395
|
const itemId = string(item.id);
|
|
15162
15396
|
if (itemId === void 0) return;
|
|
@@ -15199,6 +15433,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15199
15433
|
follow.streamedBlocks.clear();
|
|
15200
15434
|
follow.nextBlockIndex = 0;
|
|
15201
15435
|
follow.streamActive = false;
|
|
15436
|
+
follow.assistantAttempt = void 0;
|
|
15202
15437
|
follow.liveItems.clear();
|
|
15203
15438
|
follow.liveToolOutput.clear();
|
|
15204
15439
|
follow.liveToolResultSeq.clear();
|
|
@@ -15211,7 +15446,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15211
15446
|
this.broadcastRcHost({ type: "host/session-status", sessionId, running: args[1] });
|
|
15212
15447
|
} else if (event === "api-session/removed" && sessionId !== void 0) {
|
|
15213
15448
|
this.broadcastRcHost({ type: "host/session-removed", sessionId });
|
|
15214
|
-
} else if (event === "api-session/added" &&
|
|
15449
|
+
} else if (event === "api-session/added" && isRecord4(args[0])) {
|
|
15215
15450
|
const summary = args[0];
|
|
15216
15451
|
this.broadcastRcHost({
|
|
15217
15452
|
type: "host/session-added",
|
|
@@ -15239,7 +15474,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15239
15474
|
}
|
|
15240
15475
|
async answerRemoteEvent(args, signal) {
|
|
15241
15476
|
const eventId = string(args.eventId);
|
|
15242
|
-
const outcome =
|
|
15477
|
+
const outcome = record2(args.outcome);
|
|
15243
15478
|
if (eventId === void 0) throw new Error("The CodeX approval result is missing its event id.");
|
|
15244
15479
|
const pending = this.pendingApprovals.get(eventId);
|
|
15245
15480
|
if (pending === void 0) return void 0;
|
|
@@ -15290,7 +15525,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15290
15525
|
if (!containsPath(workspace.path, path)) {
|
|
15291
15526
|
return failure("workspace-not-found", "The selected directory is outside the current CodeX virtual Workspace.");
|
|
15292
15527
|
}
|
|
15293
|
-
const listing =
|
|
15528
|
+
const listing = record2(await this.client.request("dsh/directoryList", { path }, signal));
|
|
15294
15529
|
if (!isCodexDirectoryListing(listing)) {
|
|
15295
15530
|
return failure("internal", "CodeX Remote returned an invalid directory listing.");
|
|
15296
15531
|
}
|
|
@@ -15324,13 +15559,13 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15324
15559
|
const directory = await this.models(signal);
|
|
15325
15560
|
const selection = directory.default;
|
|
15326
15561
|
const requestedPreset = CODEX_DEFAULT_PERMISSION;
|
|
15327
|
-
const result =
|
|
15562
|
+
const result = record2(await this.client.request("thread/start", {
|
|
15328
15563
|
cwd,
|
|
15329
15564
|
model: selection.model,
|
|
15330
15565
|
permissionPreset: requestedPreset
|
|
15331
15566
|
}, signal));
|
|
15332
15567
|
const permissionPreset2 = codexPermissionPresetFromResponse(result) ?? requestedPreset;
|
|
15333
|
-
const thread = { ...
|
|
15568
|
+
const thread = { ...record2(result.thread), cwd, turns: array(record2(result.thread).turns) };
|
|
15334
15569
|
const projected = projectCodexThread(thread);
|
|
15335
15570
|
if (projected === void 0) return failure("internal", "CodeX returned an invalid Thread.");
|
|
15336
15571
|
this.pendingThreads.set(projected.nativeId, thread);
|
|
@@ -15350,16 +15585,14 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15350
15585
|
}
|
|
15351
15586
|
async forkSession(request, signal) {
|
|
15352
15587
|
const sessionId = requiredString(request.sessionId, "sessionId");
|
|
15353
|
-
|
|
15354
|
-
|
|
15355
|
-
threadId: nativeThreadId(sessionId),
|
|
15356
|
-
...permissionPreset2 === void 0 ? {} : { permissionPreset: permissionPreset2 }
|
|
15588
|
+
const result = record2(await this.client.request("thread/fork", {
|
|
15589
|
+
threadId: nativeThreadId(sessionId)
|
|
15357
15590
|
}, signal));
|
|
15358
|
-
permissionPreset2 = codexPermissionPresetFromResponse(result)
|
|
15359
|
-
const projected = projectCodexThread(
|
|
15591
|
+
const permissionPreset2 = codexPermissionPresetFromResponse(result);
|
|
15592
|
+
const projected = projectCodexThread(record2(result.thread));
|
|
15360
15593
|
if (projected === void 0) return failure("internal", "CodeX returned an invalid forked Thread.");
|
|
15361
15594
|
this.selectedModels.set(projected.id, this.modelSelection(sessionId, await this.models(signal)));
|
|
15362
|
-
this.
|
|
15595
|
+
this.setPermissionSelection(projected.id, permissionPreset2);
|
|
15363
15596
|
await this.refreshAndPublishWorkspaces();
|
|
15364
15597
|
const seq = this.nextProjectionSeq();
|
|
15365
15598
|
this.publishProjection(projected.id, "title", displayTitle(projected), seq);
|
|
@@ -15372,7 +15605,6 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15372
15605
|
if (input2 === void 0) return failure("attachment-error", "CodeX virtual Sessions accept text and pasted PNG, JPEG, WebP, or GIF images only.");
|
|
15373
15606
|
const threadId = nativeThreadId(sessionId);
|
|
15374
15607
|
const selection = this.modelSelection(sessionId, await this.models(signal));
|
|
15375
|
-
let permissionPreset2 = this.selectedPermissions.get(sessionId);
|
|
15376
15608
|
const isFreshBlankThread = this.blankThreads.has(threadId) || this.pendingThreads.has(threadId);
|
|
15377
15609
|
await this.ensureRcFollow(sessionId);
|
|
15378
15610
|
if (!isFreshBlankThread) {
|
|
@@ -15381,8 +15613,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15381
15613
|
model: selection.model
|
|
15382
15614
|
}, signal);
|
|
15383
15615
|
const serverPreset = codexPermissionPresetFromResponse(resumeResult);
|
|
15384
|
-
if (
|
|
15385
|
-
permissionPreset2 = serverPreset;
|
|
15616
|
+
if (serverPreset !== void 0) {
|
|
15386
15617
|
this.setPermissionSelection(sessionId, serverPreset);
|
|
15387
15618
|
}
|
|
15388
15619
|
}
|
|
@@ -15396,8 +15627,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15396
15627
|
await this.client.request(mode, {
|
|
15397
15628
|
threadId,
|
|
15398
15629
|
input: input2,
|
|
15399
|
-
...codexModelParams(selection)
|
|
15400
|
-
...permissionPreset2 === void 0 ? {} : { permissionPreset: permissionPreset2 }
|
|
15630
|
+
...codexModelParams(selection)
|
|
15401
15631
|
}, signal);
|
|
15402
15632
|
}
|
|
15403
15633
|
this.blankThreads.delete(threadId);
|
|
@@ -15418,8 +15648,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15418
15648
|
}
|
|
15419
15649
|
async hydrateImageAttachments(sessionId, signal) {
|
|
15420
15650
|
const threadId = nativeThreadId(sessionId);
|
|
15421
|
-
const result =
|
|
15422
|
-
const thread =
|
|
15651
|
+
const result = record2(await this.client.request("thread/read", { threadId, includeTurns: true }, signal));
|
|
15652
|
+
const thread = record2(result.thread);
|
|
15423
15653
|
if (string(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
|
|
15424
15654
|
this.cacheHistoryImages(projectCodexNativeHistory(thread, sessionId));
|
|
15425
15655
|
}
|
|
@@ -15441,7 +15671,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15441
15671
|
return success({ title, seq });
|
|
15442
15672
|
}
|
|
15443
15673
|
async sessionPage(request, signal) {
|
|
15444
|
-
const sessionId = sessionIdFromAddress(
|
|
15674
|
+
const sessionId = sessionIdFromAddress(record2(request.address));
|
|
15445
15675
|
const page = await this.readHistoryPage(nativeThreadId(sessionId), {
|
|
15446
15676
|
beforeSeq: optionalNonNegativeInteger(request.beforeSeq),
|
|
15447
15677
|
throughSeq: optionalInteger(request.throughSeq),
|
|
@@ -15454,15 +15684,15 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15454
15684
|
return void 0;
|
|
15455
15685
|
}
|
|
15456
15686
|
async fetchThread(threadId, signal) {
|
|
15457
|
-
const result =
|
|
15458
|
-
const thread =
|
|
15687
|
+
const result = record2(await this.client.request("thread/read", { threadId, includeTurns: false }, signal));
|
|
15688
|
+
const thread = record2(result.thread);
|
|
15459
15689
|
if (string(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
|
|
15460
15690
|
return thread;
|
|
15461
15691
|
}
|
|
15462
15692
|
async readHistoryPage(threadId, page, signal) {
|
|
15463
15693
|
let value;
|
|
15464
15694
|
try {
|
|
15465
|
-
value =
|
|
15695
|
+
value = record2(await this.client.request("dsh/sessionHistory", {
|
|
15466
15696
|
threadId,
|
|
15467
15697
|
...page.beforeSeq === void 0 ? {} : { beforeSeq: page.beforeSeq },
|
|
15468
15698
|
...page.throughSeq === void 0 ? {} : { throughSeq: page.throughSeq },
|
|
@@ -15470,11 +15700,11 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15470
15700
|
}, signal));
|
|
15471
15701
|
} catch (error) {
|
|
15472
15702
|
if (!isLegacySessionHistoryUnsupported(error)) throw error;
|
|
15473
|
-
const result =
|
|
15474
|
-
const thread =
|
|
15703
|
+
const result = record2(await this.client.request("thread/read", { threadId, includeTurns: true }, signal));
|
|
15704
|
+
const thread = record2(result.thread);
|
|
15475
15705
|
if (string(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
|
|
15476
15706
|
value = paginateCodexNativeHistory(
|
|
15477
|
-
projectCodexNativeHistory(thread, `codex:${threadId}
|
|
15707
|
+
projectCodexNativeHistory(thread, `codex:${threadId}`, this.sessionGeneration),
|
|
15478
15708
|
{
|
|
15479
15709
|
beforeSeq: page.beforeSeq,
|
|
15480
15710
|
throughSeq: page.throughSeq,
|
|
@@ -15482,9 +15712,14 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15482
15712
|
}
|
|
15483
15713
|
);
|
|
15484
15714
|
}
|
|
15715
|
+
value = adaptCodexHistoryPage(value, this.sessionGeneration);
|
|
15485
15716
|
if (!isCodexNativeHistoryPage(value, `codex:${threadId}`)) {
|
|
15486
15717
|
throw new Error("CodeX Remote returned an invalid paginated History.");
|
|
15487
15718
|
}
|
|
15719
|
+
if (Object.hasOwn(value, "permissionPreset")) {
|
|
15720
|
+
const preset = value.permissionPreset;
|
|
15721
|
+
this.setPermissionSelection(`codex:${threadId}`, preset === "workspace-write" || preset === "danger-full-access" ? preset : void 0);
|
|
15722
|
+
}
|
|
15488
15723
|
this.cacheHistoryImages(value);
|
|
15489
15724
|
return value;
|
|
15490
15725
|
}
|
|
@@ -15545,6 +15780,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15545
15780
|
streamedBlocks: /* @__PURE__ */ new Map(),
|
|
15546
15781
|
nextBlockIndex: 0,
|
|
15547
15782
|
streamActive: false,
|
|
15783
|
+
assistantStreamRevision: 0,
|
|
15548
15784
|
liveItems: /* @__PURE__ */ new Map(),
|
|
15549
15785
|
liveToolOutput: /* @__PURE__ */ new Map(),
|
|
15550
15786
|
liveToolResultSeq: /* @__PURE__ */ new Map(),
|
|
@@ -15595,7 +15831,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15595
15831
|
}
|
|
15596
15832
|
createApiProxy() {
|
|
15597
15833
|
const call = (endpoint) => async (request, signal) => {
|
|
15598
|
-
const payload = endpoint === "session.prompt" &&
|
|
15834
|
+
const payload = endpoint === "session.prompt" && isRecord4(request.payload) ? { ...request.payload, requestId: String(request.rpcId) } : request.payload;
|
|
15599
15835
|
const result = await this.dispatch(rcEndpoint(endpoint), { args: { request: payload } }, signal ?? new AbortController().signal);
|
|
15600
15836
|
return {
|
|
15601
15837
|
rpcId: request.rpcId,
|
|
@@ -15692,7 +15928,7 @@ async function loadCatalog(client, signal, pendingThreads) {
|
|
|
15692
15928
|
const threads = [];
|
|
15693
15929
|
let cursor2;
|
|
15694
15930
|
for (let page = 0; page < MAX_CODEX_PAGES; page += 1) {
|
|
15695
|
-
const result =
|
|
15931
|
+
const result = record2(await client.request("thread/list", {
|
|
15696
15932
|
limit: CODEX_PAGE_LIMIT,
|
|
15697
15933
|
sortKey: "updated_at",
|
|
15698
15934
|
sortDirection: "desc",
|
|
@@ -15700,7 +15936,7 @@ async function loadCatalog(client, signal, pendingThreads) {
|
|
|
15700
15936
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
15701
15937
|
}, signal));
|
|
15702
15938
|
for (const value of array(result.data)) {
|
|
15703
|
-
const thread =
|
|
15939
|
+
const thread = record2(value);
|
|
15704
15940
|
if (string(thread.id) !== void 0) threads.push(thread);
|
|
15705
15941
|
}
|
|
15706
15942
|
cursor2 = typeof result.nextCursor === "string" && result.nextCursor.length > 0 ? result.nextCursor : void 0;
|
|
@@ -15752,7 +15988,7 @@ async function loadCodexProjects(client, signal) {
|
|
|
15752
15988
|
let cursor2;
|
|
15753
15989
|
try {
|
|
15754
15990
|
for (let page = 0; page < MAX_CODEX_PAGES; page += 1) {
|
|
15755
|
-
const result =
|
|
15991
|
+
const result = record2(await client.request("project/list", {
|
|
15756
15992
|
limit: CODEX_PAGE_LIMIT,
|
|
15757
15993
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
15758
15994
|
}, signal));
|
|
@@ -15774,18 +16010,18 @@ async function loadModelDirectory(client, signal) {
|
|
|
15774
16010
|
let defaultModelId;
|
|
15775
16011
|
let cursor2;
|
|
15776
16012
|
for (let page = 0; page < MAX_CODEX_PAGES; page += 1) {
|
|
15777
|
-
const result =
|
|
16013
|
+
const result = record2(await client.request("model/list", {
|
|
15778
16014
|
limit: CODEX_PAGE_LIMIT,
|
|
15779
16015
|
includeHidden: false,
|
|
15780
16016
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
15781
16017
|
}, signal));
|
|
15782
16018
|
for (const value of array(result.data)) {
|
|
15783
|
-
const source =
|
|
16019
|
+
const source = record2(value);
|
|
15784
16020
|
if (source.hidden === true) continue;
|
|
15785
16021
|
const id2 = string(source.model) ?? string(source.id);
|
|
15786
16022
|
if (id2 === void 0 || models.has(id2)) continue;
|
|
15787
16023
|
const efforts = array(source.supportedReasoningEfforts).map((value2) => {
|
|
15788
|
-
const effort =
|
|
16024
|
+
const effort = record2(value2);
|
|
15789
16025
|
const effortId = string(effort.reasoningEffort);
|
|
15790
16026
|
if (effortId === void 0) return void 0;
|
|
15791
16027
|
const description2 = string(effort.description);
|
|
@@ -15827,7 +16063,7 @@ async function loadModelDirectory(client, signal) {
|
|
|
15827
16063
|
models
|
|
15828
16064
|
};
|
|
15829
16065
|
}
|
|
15830
|
-
function projectCodexNativeHistory(thread, sessionId) {
|
|
16066
|
+
function projectCodexNativeHistory(thread, sessionId, sessionGeneration = "legacy") {
|
|
15831
16067
|
const entries = [];
|
|
15832
16068
|
let seq = 0;
|
|
15833
16069
|
let turnNumber = 0;
|
|
@@ -15840,7 +16076,7 @@ function projectCodexNativeHistory(thread, sessionId) {
|
|
|
15840
16076
|
type,
|
|
15841
16077
|
seq: eventSeq,
|
|
15842
16078
|
time,
|
|
15843
|
-
data,
|
|
16079
|
+
data: adaptEventData(type, data, sessionGeneration),
|
|
15844
16080
|
...sourceEventSeqs === void 0 ? {} : { sourceEventSeqs },
|
|
15845
16081
|
...isSurfaceEvent(type) ? { surfaceOp: "append" } : {}
|
|
15846
16082
|
},
|
|
@@ -15849,8 +16085,8 @@ function projectCodexNativeHistory(thread, sessionId) {
|
|
|
15849
16085
|
return eventSeq;
|
|
15850
16086
|
};
|
|
15851
16087
|
for (const rawTurn of array(thread.turns)) {
|
|
15852
|
-
const turn =
|
|
15853
|
-
const turnItems = array(turn.items).map(
|
|
16088
|
+
const turn = record2(rawTurn);
|
|
16089
|
+
const turnItems = array(turn.items).map(record2);
|
|
15854
16090
|
const toolImages = turnItems.flatMap(toolOutputImageBlocks);
|
|
15855
16091
|
let imageOwner = -1;
|
|
15856
16092
|
for (let index = 0; index < turnItems.length; index += 1) {
|
|
@@ -15893,10 +16129,11 @@ function projectCodexNativeHistory(thread, sessionId) {
|
|
|
15893
16129
|
const projected = projectCodexThread(thread);
|
|
15894
16130
|
return {
|
|
15895
16131
|
header: {
|
|
15896
|
-
version: 1,
|
|
16132
|
+
version: sessionGeneration === "v3" ? 3 : 1,
|
|
15897
16133
|
id: sessionId,
|
|
15898
16134
|
createdAt: projected?.createdAt ?? Date.now(),
|
|
15899
|
-
...projected?.cwd === void 0 ? {} : { cwd: projected.cwd }
|
|
16135
|
+
...projected?.cwd === void 0 ? {} : { cwd: projected.cwd },
|
|
16136
|
+
...sessionGeneration === "v3" ? { isSeeded: false } : {}
|
|
15900
16137
|
},
|
|
15901
16138
|
entries,
|
|
15902
16139
|
lastSeq: seq - 1,
|
|
@@ -15929,6 +16166,40 @@ function paginateCodexNativeHistory(history, request) {
|
|
|
15929
16166
|
...history.activeTurnId === void 0 ? {} : { activeTurnId: history.activeTurnId }
|
|
15930
16167
|
};
|
|
15931
16168
|
}
|
|
16169
|
+
function adaptEventData(type, data, sessionGeneration) {
|
|
16170
|
+
if (sessionGeneration !== "v3" || type !== "assistant/message") return data;
|
|
16171
|
+
const value = record2(data);
|
|
16172
|
+
return Array.isArray(value.stream) ? value : { ...value, stream: [] };
|
|
16173
|
+
}
|
|
16174
|
+
function adaptCodexHistoryPage(value, sessionGeneration) {
|
|
16175
|
+
if (sessionGeneration !== "v3") return value;
|
|
16176
|
+
const page = record2(value);
|
|
16177
|
+
const sourceHeader = record2(page.header);
|
|
16178
|
+
const { seedLength: _seedLength, ...header } = sourceHeader;
|
|
16179
|
+
const records = Array.isArray(page.records) ? page.records.map((raw) => {
|
|
16180
|
+
const entry = record2(raw);
|
|
16181
|
+
const sourceEvent = record2(entry.event);
|
|
16182
|
+
const sourceSurfaceOp = record2(sourceEvent.surfaceOp);
|
|
16183
|
+
const surfaceOp = sourceEvent.surfaceOp === "append" ? "append" : sourceSurfaceOp.op === "replace" && integer(sourceSurfaceOp.startSeq) !== void 0 && integer(sourceSurfaceOp.endSeq) !== void 0 ? sourceSurfaceOp : sourceSurfaceOp.op === "replace" && integer(sourceSurfaceOp.start) !== void 0 && integer(sourceSurfaceOp.end) !== void 0 ? {
|
|
16184
|
+
op: "replace",
|
|
16185
|
+
startSeq: sourceSurfaceOp.start,
|
|
16186
|
+
endSeq: sourceSurfaceOp.end
|
|
16187
|
+
} : sourceEvent.surfaceOp;
|
|
16188
|
+
return {
|
|
16189
|
+
...entry,
|
|
16190
|
+
event: {
|
|
16191
|
+
...sourceEvent,
|
|
16192
|
+
data: adaptEventData(string(sourceEvent.type) ?? "", sourceEvent.data, sessionGeneration),
|
|
16193
|
+
...surfaceOp === void 0 ? {} : { surfaceOp }
|
|
16194
|
+
}
|
|
16195
|
+
};
|
|
16196
|
+
}) : page.records;
|
|
16197
|
+
return {
|
|
16198
|
+
...page,
|
|
16199
|
+
header: { ...header, version: 3, isSeeded: sourceHeader.isSeeded === true },
|
|
16200
|
+
records
|
|
16201
|
+
};
|
|
16202
|
+
}
|
|
15932
16203
|
function itemEvents(item, turn, step, requestId, selection = modelSelection(), sessionId = CODEX_SESSION_PREFIX, supplementalImages = []) {
|
|
15933
16204
|
const type = string(item.type);
|
|
15934
16205
|
const id2 = string(item.id) ?? `${turn}:${step}:${hashString(JSON.stringify(item))}`;
|
|
@@ -15999,15 +16270,15 @@ function messageContent(item, attachmentSeed, fallbackType, fallbackText, supple
|
|
|
15999
16270
|
}
|
|
16000
16271
|
function toolOutputImageBlocks(item) {
|
|
16001
16272
|
const candidates = [
|
|
16002
|
-
|
|
16003
|
-
|
|
16273
|
+
record2(item.result).content,
|
|
16274
|
+
record2(item.output).content,
|
|
16004
16275
|
item.contentItems,
|
|
16005
16276
|
Array.isArray(item.output) ? item.output : void 0
|
|
16006
16277
|
];
|
|
16007
16278
|
for (const candidate of candidates) {
|
|
16008
16279
|
if (!Array.isArray(candidate)) continue;
|
|
16009
16280
|
const images = candidate.flatMap((value) => {
|
|
16010
|
-
const block =
|
|
16281
|
+
const block = record2(value);
|
|
16011
16282
|
return isImageContent2(block) && parseImageBlock(block) !== void 0 ? [block] : [];
|
|
16012
16283
|
});
|
|
16013
16284
|
if (images.length > 0) return images;
|
|
@@ -16024,7 +16295,7 @@ function contentBlocks(value, attachmentSeed) {
|
|
|
16024
16295
|
blocks.push({ type: "text", text: raw });
|
|
16025
16296
|
continue;
|
|
16026
16297
|
}
|
|
16027
|
-
const block =
|
|
16298
|
+
const block = record2(raw);
|
|
16028
16299
|
const image = imageContentBlock(block, attachmentSeed, imageIndex);
|
|
16029
16300
|
if (image !== void 0) {
|
|
16030
16301
|
imageIndex += 1;
|
|
@@ -16063,7 +16334,7 @@ function isImageContent2(block) {
|
|
|
16063
16334
|
return block.type === "image" || block.type === "input_image";
|
|
16064
16335
|
}
|
|
16065
16336
|
function parseImageBlock(block) {
|
|
16066
|
-
const url = string(block.url) ?? string(block.image_url) ?? string(
|
|
16337
|
+
const url = string(block.url) ?? string(block.image_url) ?? string(record2(block.image_url).url);
|
|
16067
16338
|
const parsed = url === void 0 ? void 0 : parseDataImageUrl2(url);
|
|
16068
16339
|
if (parsed !== void 0) return parsed;
|
|
16069
16340
|
const data = string(block.data);
|
|
@@ -16085,7 +16356,7 @@ function collectImageBlocks(value, output = []) {
|
|
|
16085
16356
|
for (const item of value) collectImageBlocks(item, output);
|
|
16086
16357
|
return output;
|
|
16087
16358
|
}
|
|
16088
|
-
if (!
|
|
16359
|
+
if (!isRecord4(value)) return output;
|
|
16089
16360
|
if (value.type === "image") output.push(value);
|
|
16090
16361
|
for (const [key, child] of Object.entries(value)) {
|
|
16091
16362
|
if (key === "attachment") continue;
|
|
@@ -16220,10 +16491,10 @@ function toolResultEvent(item, turn, step, id2, resultText) {
|
|
|
16220
16491
|
};
|
|
16221
16492
|
}
|
|
16222
16493
|
function toolResultContentReplacement(event) {
|
|
16223
|
-
const data =
|
|
16224
|
-
const message =
|
|
16494
|
+
const data = record2(event.data);
|
|
16495
|
+
const message = record2(data.message);
|
|
16225
16496
|
const content = array(message.content);
|
|
16226
|
-
const result =
|
|
16497
|
+
const result = record2(content[0]);
|
|
16227
16498
|
if (result.isError === void 0) return event;
|
|
16228
16499
|
const { isError: _isError, ...stableResult } = result;
|
|
16229
16500
|
return {
|
|
@@ -16263,9 +16534,9 @@ function toolResultText(item, type, text) {
|
|
|
16263
16534
|
if (type === "exitedReviewMode") return `Exited review mode${string(item.review) ? `: ${string(item.review)}` : "."}`;
|
|
16264
16535
|
if (type === "sleep") return `Waited ${integer(item.durationMs) ?? 0} ms.`;
|
|
16265
16536
|
if (type === "subAgentActivity") {
|
|
16266
|
-
return [string(
|
|
16537
|
+
return [string(record2(item.kind).type) ?? string(item.kind) ?? "Subagent activity", string(item.agentPath)].filter((value) => value !== void 0).join(": ");
|
|
16267
16538
|
}
|
|
16268
|
-
return text ?? itemText2(
|
|
16539
|
+
return text ?? itemText2(record2(item.result)) ?? itemText2(record2(item.output)) ?? string(item.status) ?? type;
|
|
16269
16540
|
}
|
|
16270
16541
|
function isSurfaceEvent(type) {
|
|
16271
16542
|
return type === "user/message" || type === "assistant/message" || type === "tool/result";
|
|
@@ -16337,10 +16608,10 @@ function toolResultView(item, type, resultText) {
|
|
|
16337
16608
|
};
|
|
16338
16609
|
}
|
|
16339
16610
|
function toolDisplayName(item, type) {
|
|
16340
|
-
return string(item.name) ?? string(item.tool) ?? string(
|
|
16611
|
+
return string(item.name) ?? string(item.tool) ?? string(record2(item.tool).name) ?? (type === "mcpToolCall" ? "CodeX MCP tool" : humanizeItemType(type));
|
|
16341
16612
|
}
|
|
16342
16613
|
function fileLocations(item) {
|
|
16343
|
-
return array(item.changes).map((value) => string(
|
|
16614
|
+
return array(item.changes).map((value) => string(record2(value).path)).filter((path) => path !== void 0 && path.length > 0).map((path) => ({ path }));
|
|
16344
16615
|
}
|
|
16345
16616
|
function nativeWorkspace(view) {
|
|
16346
16617
|
const { sessionCount: _sessionCount, ...workspace } = view;
|
|
@@ -16362,10 +16633,10 @@ function projectWorkspace(project) {
|
|
|
16362
16633
|
};
|
|
16363
16634
|
}
|
|
16364
16635
|
function projectCodexProject(value, fallbackPosition) {
|
|
16365
|
-
const source =
|
|
16636
|
+
const source = record2(value);
|
|
16366
16637
|
const id2 = string(source.id);
|
|
16367
16638
|
if (id2 === void 0) return void 0;
|
|
16368
|
-
const roots = array(source.roots).map((root) => string(
|
|
16639
|
+
const roots = array(source.roots).map((root) => string(record2(root).path)).filter((path) => path !== void 0 && path.length > 0).map((path) => ({ path }));
|
|
16369
16640
|
if (roots.length === 0) return void 0;
|
|
16370
16641
|
return {
|
|
16371
16642
|
id: id2,
|
|
@@ -16415,7 +16686,7 @@ function codexPromptInput(content) {
|
|
|
16415
16686
|
if (content.length === 0 || content.length > MAX_CODEX_PROMPT_PARTS) return void 0;
|
|
16416
16687
|
const input2 = [];
|
|
16417
16688
|
for (const value of content) {
|
|
16418
|
-
if (!
|
|
16689
|
+
if (!isRecord4(value)) return void 0;
|
|
16419
16690
|
if (value.type === "text") {
|
|
16420
16691
|
if (typeof value.text !== "string" || value.text.length === 0 || value.text.length > MAX_CODEX_PROMPT_TEXT) return void 0;
|
|
16421
16692
|
input2.push({ type: "text", text: value.text });
|
|
@@ -16436,7 +16707,7 @@ function isCanonicalBase642(value) {
|
|
|
16436
16707
|
function modelSelectionProjection(selection) {
|
|
16437
16708
|
return { lastUsed: selection, next: selection };
|
|
16438
16709
|
}
|
|
16439
|
-
function codexPermissionsProjection(
|
|
16710
|
+
function codexPermissionsProjection(preset) {
|
|
16440
16711
|
return {
|
|
16441
16712
|
options: [
|
|
16442
16713
|
{
|
|
@@ -16450,7 +16721,7 @@ function codexPermissionsProjection(currentValue) {
|
|
|
16450
16721
|
description: "Full Host file access without approval prompts for subsequent turns in this virtual Session."
|
|
16451
16722
|
}
|
|
16452
16723
|
],
|
|
16453
|
-
currentValue
|
|
16724
|
+
currentValue: preset ?? "Host settings (not reported)"
|
|
16454
16725
|
};
|
|
16455
16726
|
}
|
|
16456
16727
|
function codexImageLimitsProjection() {
|
|
@@ -16466,22 +16737,6 @@ function codexImageLimitsProjection() {
|
|
|
16466
16737
|
function isCodexPermissionPreset(value) {
|
|
16467
16738
|
return value === "workspace-write" || value === "danger-full-access";
|
|
16468
16739
|
}
|
|
16469
|
-
function codexPermissionPresetFromResponse(value) {
|
|
16470
|
-
const root = record(value);
|
|
16471
|
-
return codexPermissionPresetFromPolicyRecord(root) ?? codexPermissionPresetFromPolicyRecord(record(root.threadSettings));
|
|
16472
|
-
}
|
|
16473
|
-
function codexPermissionPresetFromPolicyRecord(value) {
|
|
16474
|
-
const sandbox = value.sandbox ?? value.sandboxPolicy;
|
|
16475
|
-
if (value.approvalPolicy === "never" && isDangerFullAccessSandbox(sandbox)) return "danger-full-access";
|
|
16476
|
-
if (value.approvalPolicy === "on-request" && isWorkspaceWriteSandbox(sandbox)) return "workspace-write";
|
|
16477
|
-
return void 0;
|
|
16478
|
-
}
|
|
16479
|
-
function isDangerFullAccessSandbox(value) {
|
|
16480
|
-
return value === "danger-full-access" || record(value).type === "dangerFullAccess";
|
|
16481
|
-
}
|
|
16482
|
-
function isWorkspaceWriteSandbox(value) {
|
|
16483
|
-
return value === "workspace-write" || record(value).type === "workspaceWrite";
|
|
16484
|
-
}
|
|
16485
16740
|
function modelCatalog(directory) {
|
|
16486
16741
|
return {
|
|
16487
16742
|
default: directory.default,
|
|
@@ -16520,7 +16775,7 @@ function itemText2(value) {
|
|
|
16520
16775
|
if (content !== void 0) {
|
|
16521
16776
|
const text = content.map((part) => {
|
|
16522
16777
|
if (typeof part === "string") return part;
|
|
16523
|
-
const block =
|
|
16778
|
+
const block = record2(part);
|
|
16524
16779
|
return string(block.text) ?? string(block.content) ?? "";
|
|
16525
16780
|
}).filter(Boolean).join("\n");
|
|
16526
16781
|
if (text !== "") return text;
|
|
@@ -16534,8 +16789,8 @@ function toolArguments(item) {
|
|
|
16534
16789
|
if (item.type === "commandExecution") return { command: commandText(item.command) ?? item.command ?? "" };
|
|
16535
16790
|
if (item.type === "fileChange") return {
|
|
16536
16791
|
changes: array(item.changes).map((value) => {
|
|
16537
|
-
const change =
|
|
16538
|
-
const kind = typeof change.kind === "string" ? change.kind : string(
|
|
16792
|
+
const change = record2(value);
|
|
16793
|
+
const kind = typeof change.kind === "string" ? change.kind : string(record2(change.kind).type);
|
|
16539
16794
|
return {
|
|
16540
16795
|
...typeof change.path === "string" ? { path: change.path } : {},
|
|
16541
16796
|
...kind === void 0 ? {} : { kind }
|
|
@@ -16556,7 +16811,7 @@ function toolArguments(item) {
|
|
|
16556
16811
|
if (item.type === "subAgentActivity") return {
|
|
16557
16812
|
agentThreadId: string(item.agentThreadId) ?? "",
|
|
16558
16813
|
agentPath: string(item.agentPath) ?? "",
|
|
16559
|
-
kind: string(
|
|
16814
|
+
kind: string(record2(item.kind).type) ?? string(item.kind) ?? "activity"
|
|
16560
16815
|
};
|
|
16561
16816
|
if (item.type === "sleep") return { durationMs: integer(item.durationMs) ?? 0 };
|
|
16562
16817
|
if (item.type === "enteredReviewMode" || item.type === "exitedReviewMode") return {
|
|
@@ -16567,19 +16822,19 @@ function toolArguments(item) {
|
|
|
16567
16822
|
}
|
|
16568
16823
|
function fileChangeSummary(item) {
|
|
16569
16824
|
const changes = array(item.changes).map((value) => {
|
|
16570
|
-
const change =
|
|
16825
|
+
const change = record2(value);
|
|
16571
16826
|
const path = string(change.path);
|
|
16572
|
-
const kind = typeof change.kind === "string" ? change.kind : string(
|
|
16827
|
+
const kind = typeof change.kind === "string" ? change.kind : string(record2(change.kind).type);
|
|
16573
16828
|
return [kind, path].filter((part) => part !== void 0 && part.length > 0).join(" ");
|
|
16574
16829
|
}).filter(Boolean);
|
|
16575
16830
|
return changes.length === 0 ? "File changes completed." : changes.join("\n");
|
|
16576
16831
|
}
|
|
16577
16832
|
function sanitizedFileChanges(value) {
|
|
16578
16833
|
return array(value).flatMap((raw) => {
|
|
16579
|
-
const change =
|
|
16834
|
+
const change = record2(raw);
|
|
16580
16835
|
const path = string(change.path);
|
|
16581
16836
|
if (path === void 0) return [];
|
|
16582
|
-
const kind = typeof change.kind === "string" ? change.kind : string(
|
|
16837
|
+
const kind = typeof change.kind === "string" ? change.kind : string(record2(change.kind).type);
|
|
16583
16838
|
return [{ path, ...kind === void 0 ? {} : { kind } }];
|
|
16584
16839
|
});
|
|
16585
16840
|
}
|
|
@@ -16609,7 +16864,7 @@ function humanizeItemType(type) {
|
|
|
16609
16864
|
function commandText(value) {
|
|
16610
16865
|
if (typeof value === "string") return value;
|
|
16611
16866
|
if (Array.isArray(value)) return value.filter((item) => typeof item === "string").join(" ");
|
|
16612
|
-
const source =
|
|
16867
|
+
const source = record2(value);
|
|
16613
16868
|
return string(source.command) ?? string(source.text);
|
|
16614
16869
|
}
|
|
16615
16870
|
function sessionIdFromAddress(address) {
|
|
@@ -16625,7 +16880,7 @@ function nativeThreadId(sessionId) {
|
|
|
16625
16880
|
function activeTurnId(value) {
|
|
16626
16881
|
if (!Array.isArray(value)) return void 0;
|
|
16627
16882
|
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
16628
|
-
const turn =
|
|
16883
|
+
const turn = record2(value[index]);
|
|
16629
16884
|
if (isActiveCodexTurn(turn) && typeof turn.id === "string" && turn.id.length > 0) return turn.id;
|
|
16630
16885
|
}
|
|
16631
16886
|
return void 0;
|
|
@@ -16634,10 +16889,10 @@ function isActiveCodexTurn(turn) {
|
|
|
16634
16889
|
return turn.status === "inProgress" || turn.status === "running";
|
|
16635
16890
|
}
|
|
16636
16891
|
function carrierArgs(payload) {
|
|
16637
|
-
return
|
|
16892
|
+
return record2(record2(payload).args);
|
|
16638
16893
|
}
|
|
16639
16894
|
function requestArg(args) {
|
|
16640
|
-
return
|
|
16895
|
+
return record2(args.request ?? args._request ?? args);
|
|
16641
16896
|
}
|
|
16642
16897
|
function rcEndpoint(endpoint) {
|
|
16643
16898
|
if (endpoint === "workspace.list") return "workspace/list";
|
|
@@ -16653,20 +16908,20 @@ function ok(value) {
|
|
|
16653
16908
|
return value === void 0 ? { ok: true } : { ok: true, value };
|
|
16654
16909
|
}
|
|
16655
16910
|
function business(value) {
|
|
16656
|
-
const result =
|
|
16911
|
+
const result = record2(value);
|
|
16657
16912
|
if (result.ok === true) return ok(result.value);
|
|
16658
16913
|
if (result.ok === false) {
|
|
16659
|
-
const error =
|
|
16660
|
-
return fail(string(error.code) ?? "internal", string(error.message) ?? "CodeX virtual Harness rejected the request.",
|
|
16914
|
+
const error = record2(result.error);
|
|
16915
|
+
return fail(string(error.code) ?? "internal", string(error.message) ?? "CodeX virtual Harness rejected the request.", record2(error.details));
|
|
16661
16916
|
}
|
|
16662
16917
|
return ok(value);
|
|
16663
16918
|
}
|
|
16664
16919
|
function isCodexDirectoryListing(value) {
|
|
16665
|
-
const listing =
|
|
16920
|
+
const listing = record2(value);
|
|
16666
16921
|
return typeof listing.path === "string" && typeof listing.home === "string" && Array.isArray(listing.crumbs) && listing.crumbs.every(isCodexDirectoryEntry) && Array.isArray(listing.entries) && listing.entries.every(isCodexDirectoryEntry) && typeof listing.truncated === "boolean";
|
|
16667
16922
|
}
|
|
16668
16923
|
function isCodexDirectoryEntry(value) {
|
|
16669
|
-
const entry =
|
|
16924
|
+
const entry = record2(value);
|
|
16670
16925
|
return typeof entry.name === "string" && typeof entry.path === "string" && typeof entry.hidden === "boolean";
|
|
16671
16926
|
}
|
|
16672
16927
|
function fail(code, message, details = {}) {
|
|
@@ -16684,12 +16939,12 @@ function errorCode(error) {
|
|
|
16684
16939
|
return "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
16685
16940
|
}
|
|
16686
16941
|
function errorDetails(error) {
|
|
16687
|
-
return "details" in error &&
|
|
16942
|
+
return "details" in error && isRecord4(error.details) ? error.details : {};
|
|
16688
16943
|
}
|
|
16689
|
-
function
|
|
16690
|
-
return
|
|
16944
|
+
function record2(value) {
|
|
16945
|
+
return isRecord4(value) ? value : {};
|
|
16691
16946
|
}
|
|
16692
|
-
function
|
|
16947
|
+
function isRecord4(value) {
|
|
16693
16948
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16694
16949
|
}
|
|
16695
16950
|
function array(value) {
|
|
@@ -16721,8 +16976,8 @@ function optionalPositiveInteger(value) {
|
|
|
16721
16976
|
return parsed;
|
|
16722
16977
|
}
|
|
16723
16978
|
function isCodexNativeHistoryPage(value, sessionId) {
|
|
16724
|
-
const page =
|
|
16725
|
-
const header =
|
|
16979
|
+
const page = record2(value);
|
|
16980
|
+
const header = record2(page.header);
|
|
16726
16981
|
return header.id === sessionId && integer(page.cursor) !== void 0 && integer(page.nextTurn) !== void 0 && Array.isArray(page.records) && typeof page.hasMore === "boolean" && (page.activeTurnId === void 0 || typeof page.activeTurnId === "string");
|
|
16727
16982
|
}
|
|
16728
16983
|
function truncateCodePoints(value, maximum) {
|
|
@@ -16903,7 +17158,7 @@ function normalizeServerUrl(value) {
|
|
|
16903
17158
|
}
|
|
16904
17159
|
|
|
16905
17160
|
// src/version.ts
|
|
16906
|
-
var PLUGIN_VERSION = "0.4.
|
|
17161
|
+
var PLUGIN_VERSION = "0.4.12";
|
|
16907
17162
|
|
|
16908
17163
|
// src/server-api.ts
|
|
16909
17164
|
var TERMINAL_CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/u;
|
|
@@ -17218,10 +17473,11 @@ var ServerApiError = class extends Error {
|
|
|
17218
17473
|
}
|
|
17219
17474
|
};
|
|
17220
17475
|
function validateTokens(value) {
|
|
17221
|
-
|
|
17476
|
+
const parsed = deviceTokenPairSchema.safeParse(value);
|
|
17477
|
+
if (!parsed.success) {
|
|
17222
17478
|
throw new ServerApiError("INVALID_MESSAGE", "The Server returned invalid device credentials.", false);
|
|
17223
17479
|
}
|
|
17224
|
-
return
|
|
17480
|
+
return parsed.data;
|
|
17225
17481
|
}
|
|
17226
17482
|
function validateWebLogin(value) {
|
|
17227
17483
|
const item = requireRecord(value, "account login");
|
|
@@ -17421,7 +17677,7 @@ var TypertGatewaySwitch = class {
|
|
|
17421
17677
|
if (normalized !== void 0) return normalized;
|
|
17422
17678
|
const source = error instanceof Error ? error : new Error("The Harness Gateway rejected the request.");
|
|
17423
17679
|
const code = "code" in source && typeof source.code === "string" ? source.code : "internal";
|
|
17424
|
-
const details = "details" in source &&
|
|
17680
|
+
const details = "details" in source && isRecord5(source.details) ? source.details : {};
|
|
17425
17681
|
return { code, message: source.message, details };
|
|
17426
17682
|
}
|
|
17427
17683
|
};
|
|
@@ -17430,7 +17686,7 @@ function requestFromCarrier(endpoint, payload, signal) {
|
|
|
17430
17686
|
if (segments.length !== 2 || segments.some((segment) => segment.length === 0)) {
|
|
17431
17687
|
throw new Error("The Harness Gateway endpoint is invalid.");
|
|
17432
17688
|
}
|
|
17433
|
-
if (!
|
|
17689
|
+
if (!isRecord5(payload) || !isRecord5(payload.args)) {
|
|
17434
17690
|
throw new Error("The Harness Gateway payload is invalid.");
|
|
17435
17691
|
}
|
|
17436
17692
|
return { namespace: segments[0], method: segments[1], args: payload.args, signal };
|
|
@@ -17445,7 +17701,7 @@ function isLocalOnlyEndpoint(endpoint) {
|
|
|
17445
17701
|
function isRemoteCommandMethod(method) {
|
|
17446
17702
|
return REMOTE_COMMAND_METHODS.includes(method);
|
|
17447
17703
|
}
|
|
17448
|
-
function
|
|
17704
|
+
function isRecord5(value) {
|
|
17449
17705
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17450
17706
|
}
|
|
17451
17707
|
|
|
@@ -17456,7 +17712,7 @@ import { networkInterfaces } from "node:os";
|
|
|
17456
17712
|
// src/native-rtc-helper.ts
|
|
17457
17713
|
import { spawn, spawnSync } from "node:child_process";
|
|
17458
17714
|
import { existsSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
17459
|
-
import { delimiter, dirname, join } from "node:path";
|
|
17715
|
+
import { delimiter, dirname as dirname2, join as join2 } from "node:path";
|
|
17460
17716
|
import { fileURLToPath } from "node:url";
|
|
17461
17717
|
var cachedExternalFactory;
|
|
17462
17718
|
var cachedExternalFactoryResolved = false;
|
|
@@ -17507,21 +17763,21 @@ function nodeBinaryCandidates() {
|
|
|
17507
17763
|
add3(process.env.DSH_REMOTE_NODE);
|
|
17508
17764
|
add3(process.env.NODE);
|
|
17509
17765
|
add3(process.execPath);
|
|
17510
|
-
for (const part of (process.env.PATH ?? "").split(delimiter)) add3(
|
|
17766
|
+
for (const part of (process.env.PATH ?? "").split(delimiter)) add3(join2(part, process.platform === "win32" ? "node.exe" : "node"));
|
|
17511
17767
|
add3("/opt/homebrew/bin/node");
|
|
17512
17768
|
add3("/usr/local/bin/node");
|
|
17513
17769
|
add3("/usr/bin/node");
|
|
17514
|
-
add3(
|
|
17515
|
-
add3(
|
|
17516
|
-
add3(
|
|
17770
|
+
add3(join2(process.env.HOME ?? "", ".volta", "bin", process.platform === "win32" ? "node.exe" : "node"));
|
|
17771
|
+
add3(join2(process.env.HOME ?? "", ".asdf", "shims", process.platform === "win32" ? "node.exe" : "node"));
|
|
17772
|
+
add3(join2(process.env.HOME ?? "", ".local", "bin", process.platform === "win32" ? "node.exe" : "node"));
|
|
17517
17773
|
for (const nvmNode of nvmNodeCandidates()) add3(nvmNode);
|
|
17518
17774
|
return candidates;
|
|
17519
17775
|
}
|
|
17520
17776
|
function nvmNodeCandidates() {
|
|
17521
|
-
const root =
|
|
17777
|
+
const root = join2(process.env.HOME ?? "", ".nvm", "versions", "node");
|
|
17522
17778
|
if (root === "" || !existsSync(root)) return [];
|
|
17523
17779
|
try {
|
|
17524
|
-
return readdirSync(root).map((version) =>
|
|
17780
|
+
return readdirSync(root).map((version) => join2(root, version, "bin", process.platform === "win32" ? "node.exe" : "node")).sort((left, right) => right.localeCompare(left, "en", { numeric: true }));
|
|
17525
17781
|
} catch {
|
|
17526
17782
|
return [];
|
|
17527
17783
|
}
|
|
@@ -17543,7 +17799,7 @@ function isUsableExternalNode(candidate, requireFrom) {
|
|
|
17543
17799
|
"console.log(`node:${process.versions.node}`);"
|
|
17544
17800
|
].join("")
|
|
17545
17801
|
], {
|
|
17546
|
-
cwd:
|
|
17802
|
+
cwd: dirname2(requireFrom),
|
|
17547
17803
|
env,
|
|
17548
17804
|
encoding: "utf8",
|
|
17549
17805
|
timeout: 3e3
|
|
@@ -17565,7 +17821,7 @@ var ExternalNativePeerConnection = class {
|
|
|
17565
17821
|
this.nodeBinary = nodeBinary;
|
|
17566
17822
|
this.requireFrom = requireFrom;
|
|
17567
17823
|
this.child = spawn(this.nodeBinary, ["--input-type=module", "--eval", HELPER_SOURCE], {
|
|
17568
|
-
cwd:
|
|
17824
|
+
cwd: dirname2(this.requireFrom),
|
|
17569
17825
|
env: { ...process.env, DSH_REMOTE_RTC_HELPER_REQUIRE_FROM: this.requireFrom },
|
|
17570
17826
|
stdio: ["pipe", "pipe", "pipe"]
|
|
17571
17827
|
});
|
|
@@ -18516,6 +18772,7 @@ function isPrivate(ip) {
|
|
|
18516
18772
|
var REMOTE_COMMAND_LIST_MIN_VERSION = [0, 3, 16];
|
|
18517
18773
|
var REMOTE_FILE_VIEWER_MIN_VERSION = [0, 3, 17];
|
|
18518
18774
|
var DIRECT_WEBRTC_NEGOTIATE_TIMEOUT_MS = 12e3;
|
|
18775
|
+
var DIRECT_LAN_PROGRESS_DISPLAY_MS = 1400;
|
|
18519
18776
|
var ClientModeRuntime = class {
|
|
18520
18777
|
constructor(config, identities, server, apiProxy, typertGateway, logger, host, rtcFactoryProvider = loadNodeRtcFactory) {
|
|
18521
18778
|
this.config = config;
|
|
@@ -18774,7 +19031,7 @@ var ClientModeRuntime = class {
|
|
|
18774
19031
|
const virtual = CodexVirtualHarness.remote(remote.client, {
|
|
18775
19032
|
deviceId: remote.target.deviceId,
|
|
18776
19033
|
name: remote.target.name
|
|
18777
|
-
});
|
|
19034
|
+
}, harnessSessionGeneration(this.host?.localHarnessVersion?.()));
|
|
18778
19035
|
let workspace;
|
|
18779
19036
|
try {
|
|
18780
19037
|
workspace = await virtual.selectWorkspace(workspaceId, signal);
|
|
@@ -18804,12 +19061,12 @@ var ClientModeRuntime = class {
|
|
|
18804
19061
|
throw new ClientModeError("FEATURE_NOT_SUPPORTED", "The selected Host does not provide CodeX workspaces.");
|
|
18805
19062
|
}
|
|
18806
19063
|
this.assertRemoteCompatible(remote);
|
|
18807
|
-
const result =
|
|
19064
|
+
const result = record3(await new CodexRemoteClient(remote.client).request("project/create", {
|
|
18808
19065
|
name: remoteWorkspaceTitle(trimmedPath),
|
|
18809
19066
|
roots: [{ path: trimmedPath }],
|
|
18810
19067
|
idempotencyKey: uuidV7()
|
|
18811
19068
|
}, signal));
|
|
18812
|
-
const project =
|
|
19069
|
+
const project = record3(result.project);
|
|
18813
19070
|
if (typeof project.id !== "string" || project.id.length === 0) {
|
|
18814
19071
|
throw new ClientModeError("INVALID_MESSAGE", "The Host returned an invalid CodeX project.");
|
|
18815
19072
|
}
|
|
@@ -18859,7 +19116,7 @@ var ClientModeRuntime = class {
|
|
|
18859
19116
|
}
|
|
18860
19117
|
async openCodexStream(payload, signal) {
|
|
18861
19118
|
const remote = this.activeCodexRemote();
|
|
18862
|
-
const value =
|
|
19119
|
+
const value = record3(payload);
|
|
18863
19120
|
if (typeof value.streamId !== "string" || value.streamId.length === 0 || value.streamId.length > 128 || typeof value.threadId !== "string" || value.threadId.length === 0) {
|
|
18864
19121
|
throw new ClientModeError("INVALID_MESSAGE", "A Codex stream and thread are required.");
|
|
18865
19122
|
}
|
|
@@ -18891,10 +19148,10 @@ var ClientModeRuntime = class {
|
|
|
18891
19148
|
}
|
|
18892
19149
|
}
|
|
18893
19150
|
stream.unsubscribe = remote.client.onEvent((event) => {
|
|
18894
|
-
if (event.event === "codex.app.frame" &&
|
|
19151
|
+
if (event.event === "codex.app.frame" && isRecord6(event.data) && event.data.streamId === value.streamId) {
|
|
18895
19152
|
this.appendCodexFrame(stream, event.data);
|
|
18896
19153
|
}
|
|
18897
|
-
if (event.event === "codex.app.stream.closed" &&
|
|
19154
|
+
if (event.event === "codex.app.stream.closed" && isRecord6(event.data) && event.data.streamId === value.streamId) {
|
|
18898
19155
|
stream.closed = typeof event.data.reason === "string" ? event.data.reason : "closed";
|
|
18899
19156
|
stream.wake();
|
|
18900
19157
|
}
|
|
@@ -18921,7 +19178,7 @@ var ClientModeRuntime = class {
|
|
|
18921
19178
|
stream.wake();
|
|
18922
19179
|
};
|
|
18923
19180
|
appendCodexFrame(stream, data) {
|
|
18924
|
-
if (!
|
|
19181
|
+
if (!isRecord6(data) || !isRecord6(data.frame) || typeof data.frame.method !== "string") return;
|
|
18925
19182
|
if (stream.frames.length >= 256) {
|
|
18926
19183
|
stream.closed = "overflow";
|
|
18927
19184
|
} else {
|
|
@@ -18944,7 +19201,7 @@ var ClientModeRuntime = class {
|
|
|
18944
19201
|
};
|
|
18945
19202
|
}
|
|
18946
19203
|
async nextCodexFrames(payload, signal) {
|
|
18947
|
-
const value =
|
|
19204
|
+
const value = record3(payload);
|
|
18948
19205
|
if (typeof value.streamId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Codex stream is required.");
|
|
18949
19206
|
const stream = this.codexStreams.get(value.streamId);
|
|
18950
19207
|
if (stream === void 0) throw new ClientModeError("STREAM_NOT_FOUND", "The Codex stream is not open.");
|
|
@@ -18958,7 +19215,7 @@ var ClientModeRuntime = class {
|
|
|
18958
19215
|
};
|
|
18959
19216
|
}
|
|
18960
19217
|
async closeCodexStream(payload) {
|
|
18961
|
-
const value =
|
|
19218
|
+
const value = record3(payload);
|
|
18962
19219
|
if (typeof value.streamId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Codex stream is required.");
|
|
18963
19220
|
const stream = this.codexStreams.get(value.streamId);
|
|
18964
19221
|
if (stream === void 0) return { closed: false, streamId: value.streamId };
|
|
@@ -19006,7 +19263,16 @@ var ClientModeRuntime = class {
|
|
|
19006
19263
|
}
|
|
19007
19264
|
assertRemoteCompatible(remote) {
|
|
19008
19265
|
const localRemoteGateway = this.gatewaySwitch.supportsCarrier();
|
|
19009
|
-
if (localRemoteGateway && remote.features.remoteGateway
|
|
19266
|
+
if (localRemoteGateway && remote.features.remoteGateway) {
|
|
19267
|
+
const localSessionGeneration = harnessSessionGeneration(this.host?.localHarnessVersion?.());
|
|
19268
|
+
const remoteSessionGeneration = remote.features.sessionFormat === 3 ? "v3" : "legacy";
|
|
19269
|
+
if (localSessionGeneration === remoteSessionGeneration) return;
|
|
19270
|
+
throw new ClientModeError(
|
|
19271
|
+
"HARNESS_VERSION_INCOMPATIBLE",
|
|
19272
|
+
`The local and remote Harness Session formats differ (${localSessionGeneration} vs ${remoteSessionGeneration}).`
|
|
19273
|
+
);
|
|
19274
|
+
}
|
|
19275
|
+
if (!localRemoteGateway && this.proxySwitch !== void 0 && remote.features.apiProxy) return;
|
|
19010
19276
|
throw new ClientModeError(
|
|
19011
19277
|
"HARNESS_VERSION_INCOMPATIBLE",
|
|
19012
19278
|
localRemoteGateway ? "The selected Host does not provide the Harness v0.1.2 Typert Remote Gateway transport." : "The selected Host does not provide the legacy Harness ApiProxy transport."
|
|
@@ -19069,11 +19335,15 @@ var ClientModeRuntime = class {
|
|
|
19069
19335
|
let transport;
|
|
19070
19336
|
for (const attempt of attempts) {
|
|
19071
19337
|
webRtcFallback = false;
|
|
19072
|
-
this.
|
|
19073
|
-
|
|
19074
|
-
|
|
19075
|
-
|
|
19076
|
-
|
|
19338
|
+
const stopProgressTimer = this.beginAttemptProgress(progressRunId, attempt);
|
|
19339
|
+
try {
|
|
19340
|
+
transport = createTransport(attempt);
|
|
19341
|
+
client = new RemoteClientCore(new ClientSecureTransport(transport, identity, target), 6e4);
|
|
19342
|
+
await client.connect();
|
|
19343
|
+
signal?.throwIfAborted();
|
|
19344
|
+
} finally {
|
|
19345
|
+
stopProgressTimer();
|
|
19346
|
+
}
|
|
19077
19347
|
if (attempt === "relay" || !webRtcFallback) break;
|
|
19078
19348
|
await client.close();
|
|
19079
19349
|
client = void 0;
|
|
@@ -19131,7 +19401,8 @@ var ClientModeRuntime = class {
|
|
|
19131
19401
|
transport: connectedTransport,
|
|
19132
19402
|
features,
|
|
19133
19403
|
progressRunId,
|
|
19134
|
-
...serverDevice.clientVersion === void 0 ? {} : { clientVersion: serverDevice.clientVersion }
|
|
19404
|
+
...serverDevice.clientVersion === void 0 ? {} : { clientVersion: serverDevice.clientVersion },
|
|
19405
|
+
...serverDevice.harnessVersion === void 0 ? {} : { harnessVersion: serverDevice.harnessVersion }
|
|
19135
19406
|
};
|
|
19136
19407
|
} catch (error) {
|
|
19137
19408
|
this.clearConnectionProgress(progressRunId);
|
|
@@ -19148,6 +19419,19 @@ var ClientModeRuntime = class {
|
|
|
19148
19419
|
await previous?.client.close().catch(() => void 0);
|
|
19149
19420
|
return next;
|
|
19150
19421
|
}
|
|
19422
|
+
beginAttemptProgress(runId, attempt) {
|
|
19423
|
+
if (attempt !== "direct") {
|
|
19424
|
+
this.updateConnectionProgress(runId, "probing", [attempt]);
|
|
19425
|
+
return () => void 0;
|
|
19426
|
+
}
|
|
19427
|
+
this.updateConnectionProgress(runId, "probing", ["lan"]);
|
|
19428
|
+
const timer = setTimeout(() => {
|
|
19429
|
+
if (this.connectionProgress?.runId === runId && this.connectionProgress.phase === "probing") {
|
|
19430
|
+
this.updateConnectionProgress(runId, "probing", ["p2p"]);
|
|
19431
|
+
}
|
|
19432
|
+
}, DIRECT_LAN_PROGRESS_DISPLAY_MS);
|
|
19433
|
+
return () => clearTimeout(timer);
|
|
19434
|
+
}
|
|
19151
19435
|
updateConnectionProgress(runId, phase, activeTransports) {
|
|
19152
19436
|
if (this.connectionProgress?.runId !== runId) return;
|
|
19153
19437
|
this.connectionProgress = {
|
|
@@ -19165,14 +19449,14 @@ var ClientModeRuntime = class {
|
|
|
19165
19449
|
if (endpoint === "status") return ok2(await this.detailedStatus());
|
|
19166
19450
|
if (endpoint === "devices") return ok2(await this.devices());
|
|
19167
19451
|
if (endpoint === "client.account.login") {
|
|
19168
|
-
const value =
|
|
19452
|
+
const value = record3(payload);
|
|
19169
19453
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
19170
19454
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
19171
19455
|
}
|
|
19172
19456
|
return ok2(await this.authorizeClientWithAccount(value.email, value.password));
|
|
19173
19457
|
}
|
|
19174
19458
|
if (endpoint === "client.account.qr.start") {
|
|
19175
|
-
const value =
|
|
19459
|
+
const value = record3(payload);
|
|
19176
19460
|
const provider = value.provider ?? "zhihu";
|
|
19177
19461
|
if (provider !== "zhihu" && provider !== "github") {
|
|
19178
19462
|
throw new ClientModeError("INVALID_MESSAGE", "A supported OAuth provider is required.");
|
|
@@ -19180,14 +19464,14 @@ var ClientModeRuntime = class {
|
|
|
19180
19464
|
return ok2(await this.startClientOAuthQrLogin(provider));
|
|
19181
19465
|
}
|
|
19182
19466
|
if (endpoint === "client.account.qr.poll") {
|
|
19183
|
-
const value =
|
|
19467
|
+
const value = record3(payload);
|
|
19184
19468
|
if (typeof value.qrId !== "string" || value.qrId.length < 20) {
|
|
19185
19469
|
throw new ClientModeError("INVALID_MESSAGE", "A QR login session is required.");
|
|
19186
19470
|
}
|
|
19187
19471
|
return ok2(await this.pollClientOAuthQrLogin(value.qrId));
|
|
19188
19472
|
}
|
|
19189
19473
|
if (endpoint === "directory.list") {
|
|
19190
|
-
const value =
|
|
19474
|
+
const value = record3(payload);
|
|
19191
19475
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
19192
19476
|
return ok2(await this.listRemoteDirectory(
|
|
19193
19477
|
value.targetDeviceId,
|
|
@@ -19196,38 +19480,38 @@ var ClientModeRuntime = class {
|
|
|
19196
19480
|
));
|
|
19197
19481
|
}
|
|
19198
19482
|
if (endpoint === "workspaces.list") {
|
|
19199
|
-
const value =
|
|
19483
|
+
const value = record3(payload);
|
|
19200
19484
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
19201
19485
|
return ok2(await this.listRemoteWorkspaces(value.targetDeviceId, signal));
|
|
19202
19486
|
}
|
|
19203
19487
|
if (endpoint === "codex.workspaces.list") {
|
|
19204
|
-
const value =
|
|
19488
|
+
const value = record3(payload);
|
|
19205
19489
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
19206
19490
|
return ok2(await this.listCodexWorkspaces(value.targetDeviceId, signal));
|
|
19207
19491
|
}
|
|
19208
19492
|
if (endpoint === "workspace.open") {
|
|
19209
|
-
const value =
|
|
19493
|
+
const value = record3(payload);
|
|
19210
19494
|
if (typeof value.targetDeviceId !== "string" || typeof value.path !== "string") {
|
|
19211
19495
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and working directory are required.");
|
|
19212
19496
|
}
|
|
19213
19497
|
return ok2(await this.openRemoteWorkspace(value.targetDeviceId, value.path, signal));
|
|
19214
19498
|
}
|
|
19215
19499
|
if (endpoint === "codex.workspace.open") {
|
|
19216
|
-
const value =
|
|
19500
|
+
const value = record3(payload);
|
|
19217
19501
|
if (typeof value.targetDeviceId !== "string" || typeof value.workspaceId !== "string") {
|
|
19218
19502
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and CodeX Workspace are required.");
|
|
19219
19503
|
}
|
|
19220
19504
|
return ok2(await this.openCodexWorkspace(value.targetDeviceId, value.workspaceId, signal));
|
|
19221
19505
|
}
|
|
19222
19506
|
if (endpoint === "codex.workspace.create") {
|
|
19223
|
-
const value =
|
|
19507
|
+
const value = record3(payload);
|
|
19224
19508
|
if (typeof value.targetDeviceId !== "string" || typeof value.path !== "string") {
|
|
19225
19509
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and CodeX project directory are required.");
|
|
19226
19510
|
}
|
|
19227
19511
|
return ok2(await this.createCodexWorkspace(value.targetDeviceId, value.path, signal));
|
|
19228
19512
|
}
|
|
19229
19513
|
if (endpoint === "workspace.selection.consume") {
|
|
19230
|
-
const value =
|
|
19514
|
+
const value = record3(payload);
|
|
19231
19515
|
if (typeof value.targetDeviceId !== "string" || typeof value.workspaceId !== "string") {
|
|
19232
19516
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and Workspace are required.");
|
|
19233
19517
|
}
|
|
@@ -19243,7 +19527,7 @@ var ClientModeRuntime = class {
|
|
|
19243
19527
|
return ok2(await this.callRemoteFileViewer(method, payload, signal));
|
|
19244
19528
|
}
|
|
19245
19529
|
if (endpoint === "codex.call") {
|
|
19246
|
-
const value =
|
|
19530
|
+
const value = record3(payload);
|
|
19247
19531
|
if (typeof value.method !== "string" || !("params" in value)) {
|
|
19248
19532
|
throw new ClientModeError("INVALID_MESSAGE", "A Codex method and params are required.");
|
|
19249
19533
|
}
|
|
@@ -19267,7 +19551,7 @@ var ClientModeRuntime = class {
|
|
|
19267
19551
|
return ok2({ supported: local || remoteSupported, local, remote: remoteSupported });
|
|
19268
19552
|
}
|
|
19269
19553
|
if (endpoint === "codex.respond") {
|
|
19270
|
-
const value =
|
|
19554
|
+
const value = record3(payload);
|
|
19271
19555
|
const remote = this.activeCodexRemote();
|
|
19272
19556
|
if (remote !== void 0) return ok2(await remote.client.rpc("codex.app.respond", value, signal));
|
|
19273
19557
|
const host = this.requireLocalCodex();
|
|
@@ -19278,14 +19562,14 @@ var ClientModeRuntime = class {
|
|
|
19278
19562
|
if (endpoint === "codex.stream.close") return ok2(await this.closeCodexStream(payload));
|
|
19279
19563
|
if (endpoint === "host.account.login") {
|
|
19280
19564
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19281
|
-
const value =
|
|
19565
|
+
const value = record3(payload);
|
|
19282
19566
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
19283
19567
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
19284
19568
|
}
|
|
19285
19569
|
return ok2(await this.host.authorizeHostWithAccount(value.email, value.password));
|
|
19286
19570
|
}
|
|
19287
19571
|
if (endpoint === "host.authorization.set") {
|
|
19288
|
-
const value =
|
|
19572
|
+
const value = record3(payload);
|
|
19289
19573
|
if (typeof value.enabled !== "boolean") {
|
|
19290
19574
|
throw new ClientModeError("INVALID_MESSAGE", "Host authorization state is required.");
|
|
19291
19575
|
}
|
|
@@ -19293,14 +19577,14 @@ var ClientModeRuntime = class {
|
|
|
19293
19577
|
}
|
|
19294
19578
|
if (endpoint === "host.registration-code.submit") {
|
|
19295
19579
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19296
|
-
const value =
|
|
19580
|
+
const value = record3(payload);
|
|
19297
19581
|
if (typeof value.code !== "string" || value.code.trim() === "") {
|
|
19298
19582
|
throw new ClientModeError("INVALID_MESSAGE", "A Host registration code is required.");
|
|
19299
19583
|
}
|
|
19300
19584
|
return ok2(await this.host.authorizeHostWithCode(value.code));
|
|
19301
19585
|
}
|
|
19302
19586
|
if (endpoint === "mode.set") {
|
|
19303
|
-
const value =
|
|
19587
|
+
const value = record3(payload);
|
|
19304
19588
|
if (value.mode !== "local" && value.mode !== "remote") throw new ClientModeError("INVALID_MESSAGE", "Mode must be local or remote.");
|
|
19305
19589
|
return ok2(await this.setMode(value.mode, typeof value.targetDeviceId === "string" ? value.targetDeviceId : void 0, signal));
|
|
19306
19590
|
}
|
|
@@ -19364,13 +19648,13 @@ function webrtcDiagnosticsLogFields(diagnostics) {
|
|
|
19364
19648
|
...diagnostics.selectedPath === void 0 ? {} : { rtcSelectedPath: diagnostics.selectedPath }
|
|
19365
19649
|
};
|
|
19366
19650
|
}
|
|
19367
|
-
function
|
|
19651
|
+
function record3(value) {
|
|
19368
19652
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
19369
19653
|
throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
|
|
19370
19654
|
}
|
|
19371
19655
|
return value;
|
|
19372
19656
|
}
|
|
19373
|
-
function
|
|
19657
|
+
function isRecord6(value) {
|
|
19374
19658
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19375
19659
|
}
|
|
19376
19660
|
function ok2(value) {
|
|
@@ -19395,11 +19679,11 @@ async function readRemoteWorkspaceBaseline(gateway, signal) {
|
|
|
19395
19679
|
const iterator = source[Symbol.asyncIterator]();
|
|
19396
19680
|
try {
|
|
19397
19681
|
const first = await iterator.next();
|
|
19398
|
-
if (first.done || !
|
|
19682
|
+
if (first.done || !isRecord6(first.value) || first.value.type !== "baseline" || !isRecord6(first.value.value) || !Array.isArray(first.value.value.items)) {
|
|
19399
19683
|
throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned an invalid Workspace baseline.");
|
|
19400
19684
|
}
|
|
19401
19685
|
return first.value.value.items.map((item) => {
|
|
19402
|
-
if (!
|
|
19686
|
+
if (!isRecord6(item) || typeof item.workspaceId !== "string" || typeof item.path !== "string" || typeof item.title !== "string") {
|
|
19403
19687
|
throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned an invalid Workspace row.");
|
|
19404
19688
|
}
|
|
19405
19689
|
return { workspaceId: item.workspaceId, path: item.path, title: item.title };
|
|
@@ -19464,12 +19748,18 @@ async function probeRemoteHostFeatures(client, clientVersion) {
|
|
|
19464
19748
|
if (error instanceof Error && "code" in error && error.code === "METHOD_NOT_FOUND") return fallback;
|
|
19465
19749
|
throw error;
|
|
19466
19750
|
}
|
|
19467
|
-
if (!
|
|
19751
|
+
if (!isRecord6(value) || !Array.isArray(value.capabilities) || value.capabilities.some((capability) => typeof capability !== "string")) {
|
|
19468
19752
|
throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned invalid transport capabilities.");
|
|
19469
19753
|
}
|
|
19470
19754
|
const capabilities = new Set(value.capabilities);
|
|
19471
19755
|
const apiProxy = capabilities.has("harness.api.v1");
|
|
19472
|
-
const
|
|
19756
|
+
const remoteV1 = capabilities.has("harness.remote.v1");
|
|
19757
|
+
const remoteV3 = capabilities.has("harness.remote.v3");
|
|
19758
|
+
if (remoteV1 && remoteV3) {
|
|
19759
|
+
throw new ClientModeError("INVALID_MESSAGE", "The remote Host advertised conflicting Harness Session formats.");
|
|
19760
|
+
}
|
|
19761
|
+
const sessionFormat = remoteV3 ? 3 : void 0;
|
|
19762
|
+
const remoteGateway = remoteV3 || remoteV1;
|
|
19473
19763
|
if (!apiProxy && !remoteGateway) {
|
|
19474
19764
|
throw new ClientModeError("FEATURE_NOT_SUPPORTED", "The remote Host exposes no supported Harness transport.");
|
|
19475
19765
|
}
|
|
@@ -19478,6 +19768,7 @@ async function probeRemoteHostFeatures(client, clientVersion) {
|
|
|
19478
19768
|
fileViewer: capabilities.has("fileviewer.read.v1"),
|
|
19479
19769
|
apiProxy,
|
|
19480
19770
|
remoteGateway,
|
|
19771
|
+
...sessionFormat === void 0 ? {} : { sessionFormat },
|
|
19481
19772
|
codex: capabilities.has("codex.appserver.v1")
|
|
19482
19773
|
};
|
|
19483
19774
|
}
|
|
@@ -19528,10 +19819,6 @@ function preferredTransportsForAttempt(attempt) {
|
|
|
19528
19819
|
if (attempt === "turn") return ["turn", "relay"];
|
|
19529
19820
|
return ["relay"];
|
|
19530
19821
|
}
|
|
19531
|
-
function activeTransportsForAttempt(attempt) {
|
|
19532
|
-
if (attempt === "direct") return ["lan", "p2p"];
|
|
19533
|
-
return [attempt];
|
|
19534
|
-
}
|
|
19535
19822
|
function transportPreferenceForMode(mode) {
|
|
19536
19823
|
if (mode === "LAN") return "lan";
|
|
19537
19824
|
if (mode === "P2P") return "p2p";
|
|
@@ -19548,9 +19835,9 @@ import { hostname as hostname2 } from "node:os";
|
|
|
19548
19835
|
|
|
19549
19836
|
// src/identity-store.ts
|
|
19550
19837
|
import { createHash } from "node:crypto";
|
|
19551
|
-
import { chmod, mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
19838
|
+
import { chmod, mkdir, readFile as readFile2, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
19552
19839
|
import { homedir } from "node:os";
|
|
19553
|
-
import { dirname as
|
|
19840
|
+
import { dirname as dirname3, join as join3 } from "node:path";
|
|
19554
19841
|
var identitySchema = external_exports.object({
|
|
19555
19842
|
schemaVersion: external_exports.literal(1),
|
|
19556
19843
|
deviceId: external_exports.string().uuid(),
|
|
@@ -19579,38 +19866,38 @@ var IdentityStore = class {
|
|
|
19579
19866
|
peers = /* @__PURE__ */ new Map();
|
|
19580
19867
|
constructor(options = {}) {
|
|
19581
19868
|
const env = options.env ?? process.env;
|
|
19582
|
-
const dshHome = env.DSH_HOME ||
|
|
19583
|
-
this.directory = options.directory ??
|
|
19869
|
+
const dshHome = env.DSH_HOME || join3(options.homeDirectory ?? homedir(), ".dsh");
|
|
19870
|
+
this.directory = options.directory ?? join3(dshHome, "remote");
|
|
19584
19871
|
}
|
|
19585
19872
|
async loadOrCreate(deviceName) {
|
|
19586
19873
|
await mkdir(this.directory, { recursive: true, mode: 448 });
|
|
19587
19874
|
await chmod(this.directory, 448);
|
|
19588
|
-
const devicePath =
|
|
19589
|
-
const keyPath =
|
|
19875
|
+
const devicePath = join3(this.directory, "device.json");
|
|
19876
|
+
const keyPath = join3(this.directory, "device.key");
|
|
19590
19877
|
const [hasDevice, hasKey] = await Promise.all([exists(devicePath), exists(keyPath)]);
|
|
19591
19878
|
if (hasDevice !== hasKey) {
|
|
19592
19879
|
throw new IdentityInvalidError("device identity is incomplete; repair it explicitly before reconnecting");
|
|
19593
19880
|
}
|
|
19594
19881
|
if (!hasDevice) {
|
|
19595
19882
|
const keys = generateKeyPair();
|
|
19596
|
-
const
|
|
19597
|
-
await atomicJsonWrite(devicePath,
|
|
19883
|
+
const record6 = { schemaVersion: 1, deviceId: uuidV7(), name: deviceName, publicKey: keys.publicKey };
|
|
19884
|
+
await atomicJsonWrite(devicePath, record6, 384);
|
|
19598
19885
|
await atomicTextWrite(keyPath, `${keys.privateKey}
|
|
19599
19886
|
`, 384);
|
|
19600
19887
|
}
|
|
19601
19888
|
await assertPrivateMode(keyPath);
|
|
19602
19889
|
try {
|
|
19603
|
-
let
|
|
19604
|
-
const privateKey = (await
|
|
19890
|
+
let record6 = identitySchema.parse(JSON.parse(await readFile2(devicePath, "utf8")));
|
|
19891
|
+
const privateKey = (await readFile2(keyPath, "utf8")).trim();
|
|
19605
19892
|
const regenerated = generateKeyPair(fromBase64Url2(privateKey));
|
|
19606
|
-
if (regenerated.publicKey !==
|
|
19893
|
+
if (regenerated.publicKey !== record6.publicKey) {
|
|
19607
19894
|
throw new IdentityInvalidError("device public and private keys do not match");
|
|
19608
19895
|
}
|
|
19609
|
-
if (
|
|
19610
|
-
|
|
19611
|
-
await atomicJsonWrite(devicePath,
|
|
19896
|
+
if (record6.name !== deviceName) {
|
|
19897
|
+
record6 = { ...record6, name: deviceName };
|
|
19898
|
+
await atomicJsonWrite(devicePath, record6, 384);
|
|
19612
19899
|
}
|
|
19613
|
-
this.identity = { ...
|
|
19900
|
+
this.identity = { ...record6, privateKey, fingerprint: fingerprint(record6.publicKey) };
|
|
19614
19901
|
await this.loadPeers();
|
|
19615
19902
|
return this.identity;
|
|
19616
19903
|
} catch (error) {
|
|
@@ -19655,11 +19942,11 @@ var IdentityStore = class {
|
|
|
19655
19942
|
return removed;
|
|
19656
19943
|
}
|
|
19657
19944
|
async loadPeers() {
|
|
19658
|
-
const path =
|
|
19945
|
+
const path = join3(this.directory, "trusted-peers.json");
|
|
19659
19946
|
if (!await exists(path)) {
|
|
19660
19947
|
await atomicJsonWrite(path, { schemaVersion: 1, peers: [] }, 384);
|
|
19661
19948
|
}
|
|
19662
|
-
const parsed = trustedPeersSchema.parse(JSON.parse(await
|
|
19949
|
+
const parsed = trustedPeersSchema.parse(JSON.parse(await readFile2(path, "utf8")));
|
|
19663
19950
|
const peers = /* @__PURE__ */ new Map();
|
|
19664
19951
|
for (const peer of parsed.peers) {
|
|
19665
19952
|
if (peer.fingerprint !== fingerprint(peer.publicKey)) {
|
|
@@ -19671,7 +19958,7 @@ var IdentityStore = class {
|
|
|
19671
19958
|
this.peers = peers;
|
|
19672
19959
|
}
|
|
19673
19960
|
async savePeers() {
|
|
19674
|
-
await atomicJsonWrite(
|
|
19961
|
+
await atomicJsonWrite(join3(this.directory, "trusted-peers.json"), {
|
|
19675
19962
|
schemaVersion: 1,
|
|
19676
19963
|
peers: [...this.peers.values()]
|
|
19677
19964
|
}, 384);
|
|
@@ -19680,7 +19967,7 @@ var IdentityStore = class {
|
|
|
19680
19967
|
function serverStorageDirectory(root, serverUrl, role) {
|
|
19681
19968
|
const origin = new URL(serverUrl).origin;
|
|
19682
19969
|
const scope = createHash("sha256").update(origin).digest("hex").slice(0, 24);
|
|
19683
|
-
return
|
|
19970
|
+
return join3(root, "servers", scope, role);
|
|
19684
19971
|
}
|
|
19685
19972
|
function fingerprint(publicKey) {
|
|
19686
19973
|
const compact = createHash("sha256").update(fromBase64Url2(publicKey)).digest("hex").slice(0, 12).toUpperCase();
|
|
@@ -19698,7 +19985,7 @@ async function atomicJsonWrite(path, value, mode) {
|
|
|
19698
19985
|
`, mode);
|
|
19699
19986
|
}
|
|
19700
19987
|
async function atomicTextWrite(path, value, mode) {
|
|
19701
|
-
await mkdir(
|
|
19988
|
+
await mkdir(dirname3(path), { recursive: true, mode: 448 });
|
|
19702
19989
|
const temporary = `${path}.${process.pid}.${uuidV7()}.tmp`;
|
|
19703
19990
|
await writeFile(temporary, value, { encoding: "utf8", mode, flag: "wx" });
|
|
19704
19991
|
await chmod(temporary, mode);
|
|
@@ -19722,8 +20009,8 @@ function safeErrorMessage(error) {
|
|
|
19722
20009
|
}
|
|
19723
20010
|
|
|
19724
20011
|
// src/server-credentials.ts
|
|
19725
|
-
import { chmod as chmod2, mkdir as mkdir2, readFile as
|
|
19726
|
-
import { dirname as
|
|
20012
|
+
import { chmod as chmod2, mkdir as mkdir2, readFile as readFile3, rename as rename2, rm as rm2, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
|
|
20013
|
+
import { dirname as dirname4, join as join4 } from "node:path";
|
|
19727
20014
|
var credentialSchema = external_exports.object({
|
|
19728
20015
|
schemaVersion: external_exports.literal(1),
|
|
19729
20016
|
serverUrl: external_exports.string().url(),
|
|
@@ -19738,24 +20025,24 @@ var credentialSchema = external_exports.object({
|
|
|
19738
20025
|
var ServerCredentialStore = class {
|
|
19739
20026
|
path;
|
|
19740
20027
|
constructor(directory) {
|
|
19741
|
-
this.path =
|
|
20028
|
+
this.path = join4(directory, "server-credentials.json");
|
|
19742
20029
|
}
|
|
19743
20030
|
async load(serverUrl, deviceId) {
|
|
19744
20031
|
if (!await exists2(this.path)) return void 0;
|
|
19745
20032
|
await assertPrivateMode2(this.path);
|
|
19746
20033
|
let parsed;
|
|
19747
20034
|
try {
|
|
19748
|
-
parsed = credentialSchema.parse(JSON.parse(await
|
|
20035
|
+
parsed = credentialSchema.parse(JSON.parse(await readFile3(this.path, "utf8")));
|
|
19749
20036
|
} catch (error) {
|
|
19750
20037
|
throw new ServerCredentialsInvalidError(`server credentials are invalid: ${safeMessage(error)}`);
|
|
19751
20038
|
}
|
|
19752
20039
|
return parsed.serverUrl === serverUrl && parsed.deviceId === deviceId ? parsed : void 0;
|
|
19753
20040
|
}
|
|
19754
20041
|
async save(credentials) {
|
|
19755
|
-
const
|
|
19756
|
-
await atomicWrite(this.path, `${JSON.stringify(
|
|
20042
|
+
const record6 = credentialSchema.parse({ schemaVersion: 1, ...credentials });
|
|
20043
|
+
await atomicWrite(this.path, `${JSON.stringify(record6, null, 2)}
|
|
19757
20044
|
`);
|
|
19758
|
-
return
|
|
20045
|
+
return record6;
|
|
19759
20046
|
}
|
|
19760
20047
|
async clear() {
|
|
19761
20048
|
await rm2(this.path, { force: true });
|
|
@@ -19765,7 +20052,7 @@ var ServerCredentialsInvalidError = class extends Error {
|
|
|
19765
20052
|
code = "SERVER_CREDENTIALS_INVALID";
|
|
19766
20053
|
};
|
|
19767
20054
|
async function atomicWrite(path, contents) {
|
|
19768
|
-
await mkdir2(
|
|
20055
|
+
await mkdir2(dirname4(path), { recursive: true, mode: 448 });
|
|
19769
20056
|
const temporary = `${path}.${process.pid}.${uuidV7()}.tmp`;
|
|
19770
20057
|
await writeFile2(temporary, contents, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
19771
20058
|
await chmod2(temporary, 384);
|
|
@@ -19822,7 +20109,7 @@ var PluginControlRuntime = class {
|
|
|
19822
20109
|
if (endpoint === "devices") return ok3([]);
|
|
19823
20110
|
if (endpoint === "host.account.login") {
|
|
19824
20111
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19825
|
-
const value =
|
|
20112
|
+
const value = record4(payload);
|
|
19826
20113
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
19827
20114
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
19828
20115
|
}
|
|
@@ -19830,13 +20117,13 @@ var PluginControlRuntime = class {
|
|
|
19830
20117
|
}
|
|
19831
20118
|
if (endpoint === "host.registration-code.submit") {
|
|
19832
20119
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19833
|
-
const value =
|
|
20120
|
+
const value = record4(payload);
|
|
19834
20121
|
if (typeof value.code !== "string" || value.code.trim() === "") {
|
|
19835
20122
|
throw new ClientModeError("INVALID_MESSAGE", "A Host registration code is required.");
|
|
19836
20123
|
}
|
|
19837
20124
|
return ok3(await this.host.authorizeHostWithCode(value.code));
|
|
19838
20125
|
}
|
|
19839
|
-
if (endpoint === "mode.set" &&
|
|
20126
|
+
if (endpoint === "mode.set" && record4(payload).mode === "local") return ok3(this.hostOnlyStatus());
|
|
19840
20127
|
throw new ClientModeError("METHOD_NOT_ALLOWED", "Remote Client mode is disabled by the plugin role.");
|
|
19841
20128
|
} catch (error) {
|
|
19842
20129
|
return fail3(error);
|
|
@@ -19846,7 +20133,7 @@ var PluginControlRuntime = class {
|
|
|
19846
20133
|
if (this.settings === void 0) {
|
|
19847
20134
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19848
20135
|
}
|
|
19849
|
-
const value =
|
|
20136
|
+
const value = record4(payload);
|
|
19850
20137
|
if (value.role !== "host" && value.role !== "client") {
|
|
19851
20138
|
throw new ClientModeError("INVALID_MESSAGE", "Role must be Host or Client.");
|
|
19852
20139
|
}
|
|
@@ -19881,7 +20168,7 @@ var PluginControlRuntime = class {
|
|
|
19881
20168
|
if (this.settings === void 0) {
|
|
19882
20169
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19883
20170
|
}
|
|
19884
|
-
const value =
|
|
20171
|
+
const value = record4(payload);
|
|
19885
20172
|
if (typeof value.serverUrl !== "string") {
|
|
19886
20173
|
throw new ClientModeError("INVALID_MESSAGE", "Server URL is required.");
|
|
19887
20174
|
}
|
|
@@ -19894,7 +20181,7 @@ var PluginControlRuntime = class {
|
|
|
19894
20181
|
if (this.settings === void 0) {
|
|
19895
20182
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19896
20183
|
}
|
|
19897
|
-
const role =
|
|
20184
|
+
const role = record4(payload).role;
|
|
19898
20185
|
if (role !== "host" && role !== "client") {
|
|
19899
20186
|
throw new ClientModeError("INVALID_MESSAGE", "Role must be Host or Client.");
|
|
19900
20187
|
}
|
|
@@ -19910,7 +20197,7 @@ var PluginControlRuntime = class {
|
|
|
19910
20197
|
if (this.settings === void 0) {
|
|
19911
20198
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19912
20199
|
}
|
|
19913
|
-
const enabled =
|
|
20200
|
+
const enabled = record4(payload).enabled;
|
|
19914
20201
|
if (typeof enabled !== "boolean") {
|
|
19915
20202
|
throw new ClientModeError("INVALID_MESSAGE", "Codex Remote enabled must be a boolean.");
|
|
19916
20203
|
}
|
|
@@ -20016,11 +20303,11 @@ function editableConfig(config) {
|
|
|
20016
20303
|
}
|
|
20017
20304
|
};
|
|
20018
20305
|
}
|
|
20019
|
-
function
|
|
20306
|
+
function isRecord7(value) {
|
|
20020
20307
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20021
20308
|
}
|
|
20022
|
-
function
|
|
20023
|
-
if (!
|
|
20309
|
+
function record4(value) {
|
|
20310
|
+
if (!isRecord7(value)) throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
|
|
20024
20311
|
return value;
|
|
20025
20312
|
}
|
|
20026
20313
|
function ok3(value) {
|
|
@@ -20243,36 +20530,6 @@ function shortId2(value) {
|
|
|
20243
20530
|
return value.length <= 12 ? value : `${value.slice(0, 8)}\u2026${value.slice(-4)}`;
|
|
20244
20531
|
}
|
|
20245
20532
|
|
|
20246
|
-
// src/harness-version.ts
|
|
20247
|
-
import { readFile as readFile3 } from "node:fs/promises";
|
|
20248
|
-
import { dirname as dirname4, isAbsolute, join as join4 } from "node:path";
|
|
20249
|
-
var LEGACY_PLACEHOLDER_VERSION = "0.0.1";
|
|
20250
|
-
function normalizeHarnessVersion(value) {
|
|
20251
|
-
if (typeof value !== "string") return void 0;
|
|
20252
|
-
const version = value.trim();
|
|
20253
|
-
if (version.length === 0 || version.length > 64 || /[\u0000-\u001f]/u.test(version)) return void 0;
|
|
20254
|
-
return version;
|
|
20255
|
-
}
|
|
20256
|
-
function selectHarnessVersion(reportedVersion, distributionVersion) {
|
|
20257
|
-
if (reportedVersion !== void 0 && reportedVersion !== LEGACY_PLACEHOLDER_VERSION) return reportedVersion;
|
|
20258
|
-
return distributionVersion;
|
|
20259
|
-
}
|
|
20260
|
-
async function readHarnessDistributionVersion(entrypoint = process.argv[1]) {
|
|
20261
|
-
if (entrypoint === void 0 || !isAbsolute(entrypoint)) return void 0;
|
|
20262
|
-
let directory = dirname4(entrypoint);
|
|
20263
|
-
for (let depth = 0; depth < 8; depth += 1) {
|
|
20264
|
-
try {
|
|
20265
|
-
const manifest = JSON.parse(await readFile3(join4(directory, "package.json"), "utf8"));
|
|
20266
|
-
if (manifest.name === "@deepseek-ai/dsh") return normalizeHarnessVersion(manifest.version);
|
|
20267
|
-
} catch {
|
|
20268
|
-
}
|
|
20269
|
-
const parent = dirname4(directory);
|
|
20270
|
-
if (parent === directory) break;
|
|
20271
|
-
directory = parent;
|
|
20272
|
-
}
|
|
20273
|
-
return void 0;
|
|
20274
|
-
}
|
|
20275
|
-
|
|
20276
20533
|
// src/safe-error.ts
|
|
20277
20534
|
var RpcError = class extends Error {
|
|
20278
20535
|
constructor(code, message, details, retryable = false) {
|
|
@@ -22626,14 +22883,14 @@ function needsDirectoryFallback(result) {
|
|
|
22626
22883
|
return code.includes("capability") || code === "directory-picker/unavailable" || code === "directory-picker-unavailable" || message.includes("browse capability") || message.includes("browser capability") || message.includes("brower capability") || message.includes("directory-picker-unavailable");
|
|
22627
22884
|
}
|
|
22628
22885
|
function requestArgs(payload) {
|
|
22629
|
-
const root =
|
|
22630
|
-
const args =
|
|
22631
|
-
return
|
|
22886
|
+
const root = record5(payload);
|
|
22887
|
+
const args = isRecord8(root.args) ? root.args : root;
|
|
22888
|
+
return record5(args.request ?? args._request ?? args);
|
|
22632
22889
|
}
|
|
22633
|
-
function
|
|
22634
|
-
return
|
|
22890
|
+
function record5(value) {
|
|
22891
|
+
return isRecord8(value) ? value : {};
|
|
22635
22892
|
}
|
|
22636
|
-
function
|
|
22893
|
+
function isRecord8(value) {
|
|
22637
22894
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22638
22895
|
}
|
|
22639
22896
|
|
|
@@ -22827,7 +23084,7 @@ var CodexAppServerClient = class {
|
|
|
22827
23084
|
this.handleProcessFailure("CODEX_INVALID_RESPONSE", new Error("Codex App Server emitted invalid JSON."));
|
|
22828
23085
|
return;
|
|
22829
23086
|
}
|
|
22830
|
-
if (!
|
|
23087
|
+
if (!isRecord9(value)) {
|
|
22831
23088
|
this.handleProcessFailure("CODEX_INVALID_RESPONSE", new Error("Codex App Server emitted an invalid message."));
|
|
22832
23089
|
return;
|
|
22833
23090
|
}
|
|
@@ -22872,12 +23129,12 @@ var CodexAppServerClient = class {
|
|
|
22872
23129
|
}
|
|
22873
23130
|
};
|
|
22874
23131
|
function safeUpstreamError(value) {
|
|
22875
|
-
if (!
|
|
23132
|
+
if (!isRecord9(value) || typeof value.message !== "string") return "Codex App Server rejected the request.";
|
|
22876
23133
|
const message = value.message.toLowerCase();
|
|
22877
23134
|
if (message.includes("active writer")) return "Codex thread already has an active writer.";
|
|
22878
23135
|
return message.includes("not initialized") ? "Codex App Server is not initialized." : "Codex App Server rejected the request.";
|
|
22879
23136
|
}
|
|
22880
|
-
function
|
|
23137
|
+
function isRecord9(value) {
|
|
22881
23138
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22882
23139
|
}
|
|
22883
23140
|
|
|
@@ -23247,15 +23504,15 @@ function decodeCanonicalBase643(value) {
|
|
|
23247
23504
|
}
|
|
23248
23505
|
return decoded;
|
|
23249
23506
|
}
|
|
23250
|
-
function
|
|
23507
|
+
function isRecord10(value) {
|
|
23251
23508
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23252
23509
|
}
|
|
23253
23510
|
function safeErrorCode2(error) {
|
|
23254
|
-
if (
|
|
23511
|
+
if (isRecord10(error) && typeof error.code === "string") return error.code;
|
|
23255
23512
|
return "UNKNOWN";
|
|
23256
23513
|
}
|
|
23257
23514
|
function safeMethod(input2) {
|
|
23258
|
-
return
|
|
23515
|
+
return isRecord10(input2) && typeof input2.method === "string" ? input2.method : "invalid";
|
|
23259
23516
|
}
|
|
23260
23517
|
function concatChunks3(chunks, totalBytes) {
|
|
23261
23518
|
const output = new Uint8Array(totalBytes);
|
|
@@ -23289,6 +23546,7 @@ var CodexRemoteDomain = class {
|
|
|
23289
23546
|
peerDeviceIds = /* @__PURE__ */ new Map();
|
|
23290
23547
|
turnOwners = /* @__PURE__ */ new Map();
|
|
23291
23548
|
approvals = /* @__PURE__ */ new Map();
|
|
23549
|
+
permissionPresets = /* @__PURE__ */ new Map();
|
|
23292
23550
|
approvalExpiryTimer;
|
|
23293
23551
|
restartTimer;
|
|
23294
23552
|
restartAttempt = 0;
|
|
@@ -23367,6 +23625,7 @@ var CodexRemoteDomain = class {
|
|
|
23367
23625
|
if (extractThread(result)?.id === void 0) {
|
|
23368
23626
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid thread.");
|
|
23369
23627
|
}
|
|
23628
|
+
this.rememberPermission(extractThread(result).id, result);
|
|
23370
23629
|
return result;
|
|
23371
23630
|
}
|
|
23372
23631
|
const threadId = threadIdFromParams(call.params);
|
|
@@ -23381,12 +23640,23 @@ var CodexRemoteDomain = class {
|
|
|
23381
23640
|
}
|
|
23382
23641
|
);
|
|
23383
23642
|
const activeTurnId2 = typeof page.activeTurnId === "string" ? page.activeTurnId : this.turnOwners.get(threadId)?.turnId;
|
|
23384
|
-
return
|
|
23643
|
+
return {
|
|
23644
|
+
...page,
|
|
23645
|
+
...activeTurnId2 === void 0 ? {} : { activeTurnId: activeTurnId2 },
|
|
23646
|
+
permissionPreset: this.permissionPresets.get(threadId) ?? null
|
|
23647
|
+
};
|
|
23385
23648
|
}
|
|
23386
23649
|
if (call.method === "dsh/directoryList") {
|
|
23387
23650
|
return this.listCodexDirectory(call.params.path);
|
|
23388
23651
|
}
|
|
23389
23652
|
const allowedThread = threadId === void 0 ? void 0 : await this.readKnownThread(threadId);
|
|
23653
|
+
if (call.method === "thread/resume" && call.params.permissionPreset !== void 0) {
|
|
23654
|
+
const owner = this.turnOwners.get(threadId);
|
|
23655
|
+
if (owner !== void 0 && owner.connectionId !== connectionId) {
|
|
23656
|
+
throw new RpcError("CODEX_THREAD_BUSY", "Another Remote client is writing to this CodeX thread.");
|
|
23657
|
+
}
|
|
23658
|
+
return this.changeThreadPermission(threadId, call.params, allowedThread);
|
|
23659
|
+
}
|
|
23390
23660
|
if (call.method === "thread/read") {
|
|
23391
23661
|
return this.callUpstream(call.method, call.params);
|
|
23392
23662
|
}
|
|
@@ -23436,8 +23706,18 @@ var CodexRemoteDomain = class {
|
|
|
23436
23706
|
if (call.method === "thread/resume" || call.method === "thread/fork" || call.method === "thread/unarchive") {
|
|
23437
23707
|
await this.assertResultThreadAllowed(result);
|
|
23438
23708
|
}
|
|
23709
|
+
if (call.method === "thread/resume" || call.method === "thread/fork") {
|
|
23710
|
+
const resultId = extractThread(result)?.id;
|
|
23711
|
+
if (typeof resultId === "string") {
|
|
23712
|
+
this.rememberPermission(resultId, result);
|
|
23713
|
+
if (call.params.permissionPreset !== void 0) await this.publishPermission(resultId, result);
|
|
23714
|
+
}
|
|
23715
|
+
}
|
|
23439
23716
|
if (call.method === "turn/start" && threadId !== void 0) {
|
|
23440
23717
|
this.rememberTurnId(threadId, connectionId, extractTurnId(result));
|
|
23718
|
+
if (call.params.permissionPreset !== void 0) {
|
|
23719
|
+
await this.publishPermission(threadId, codexTurnPermissionParams(permission, allowedThread?.cwd));
|
|
23720
|
+
}
|
|
23441
23721
|
}
|
|
23442
23722
|
return result;
|
|
23443
23723
|
} catch (error) {
|
|
@@ -23486,6 +23766,7 @@ var CodexRemoteDomain = class {
|
|
|
23486
23766
|
this.peers.clear();
|
|
23487
23767
|
this.peerDeviceIds.clear();
|
|
23488
23768
|
this.turnOwners.clear();
|
|
23769
|
+
this.permissionPresets.clear();
|
|
23489
23770
|
if (this.approvalExpiryTimer !== void 0) clearTimeout(this.approvalExpiryTimer);
|
|
23490
23771
|
this.approvalExpiryTimer = void 0;
|
|
23491
23772
|
this.approvals.clear();
|
|
@@ -23548,6 +23829,7 @@ var CodexRemoteDomain = class {
|
|
|
23548
23829
|
this.state = "restarting";
|
|
23549
23830
|
this.unavailableCode = code;
|
|
23550
23831
|
this.turnOwners.clear();
|
|
23832
|
+
this.permissionPresets.clear();
|
|
23551
23833
|
this.approvals.clear();
|
|
23552
23834
|
if (this.approvalExpiryTimer !== void 0) clearTimeout(this.approvalExpiryTimer);
|
|
23553
23835
|
this.approvalExpiryTimer = void 0;
|
|
@@ -23603,6 +23885,10 @@ var CodexRemoteDomain = class {
|
|
|
23603
23885
|
return;
|
|
23604
23886
|
}
|
|
23605
23887
|
const threadId = extractThreadId(message.params);
|
|
23888
|
+
if (message.method === "thread/settings/updated" && threadId !== void 0) {
|
|
23889
|
+
this.rememberPermission(threadId, message.params);
|
|
23890
|
+
}
|
|
23891
|
+
if (message.method === "thread/closed" && threadId !== void 0) this.permissionPresets.delete(threadId);
|
|
23606
23892
|
if (message.method === "turn/completed" && threadId !== void 0) this.turnOwners.delete(threadId);
|
|
23607
23893
|
if (message.method === "turn/started" && threadId !== void 0) {
|
|
23608
23894
|
const owner = this.turnOwners.get(threadId);
|
|
@@ -23618,6 +23904,42 @@ var CodexRemoteDomain = class {
|
|
|
23618
23904
|
params: message.params
|
|
23619
23905
|
})));
|
|
23620
23906
|
}
|
|
23907
|
+
rememberPermission(threadId, value) {
|
|
23908
|
+
const preset = codexPermissionPresetFromResponse(value);
|
|
23909
|
+
if (preset === void 0) this.permissionPresets.delete(threadId);
|
|
23910
|
+
else this.permissionPresets.set(threadId, preset);
|
|
23911
|
+
}
|
|
23912
|
+
async changeThreadPermission(threadId, params, allowed) {
|
|
23913
|
+
const permission = codexPermission(params);
|
|
23914
|
+
const settings = {
|
|
23915
|
+
...codexTurnPermissionParams(permission, allowed.cwd),
|
|
23916
|
+
...params.model === void 0 ? {} : { model: params.model }
|
|
23917
|
+
};
|
|
23918
|
+
let result;
|
|
23919
|
+
try {
|
|
23920
|
+
await this.callUpstream("thread/settings/update", { threadId, ...settings });
|
|
23921
|
+
result = { thread: allowed.thread, ...settings, sandbox: settings.sandboxPolicy };
|
|
23922
|
+
} catch {
|
|
23923
|
+
result = await this.callUpstream("thread/resume", {
|
|
23924
|
+
...permission.params,
|
|
23925
|
+
...allowed.cwd === void 0 ? {} : { cwd: allowed.cwd },
|
|
23926
|
+
...codexThreadPermissionParams(permission),
|
|
23927
|
+
excludeTurns: true
|
|
23928
|
+
});
|
|
23929
|
+
await this.assertResultThreadAllowed(result);
|
|
23930
|
+
if (codexPermissionPresetFromResponse(result) !== params.permissionPreset) {
|
|
23931
|
+
await this.callUpstream("thread/settings/update", { threadId, ...settings });
|
|
23932
|
+
result = { ...isRecord11(result) ? result : {}, ...settings, sandbox: settings.sandboxPolicy };
|
|
23933
|
+
}
|
|
23934
|
+
}
|
|
23935
|
+
await this.publishPermission(threadId, result);
|
|
23936
|
+
return result;
|
|
23937
|
+
}
|
|
23938
|
+
async publishPermission(threadId, value) {
|
|
23939
|
+
const source = isRecord11(value) ? value : {};
|
|
23940
|
+
const threadSettings = { approvalPolicy: source.approvalPolicy, sandboxPolicy: source.sandboxPolicy ?? source.sandbox };
|
|
23941
|
+
await this.handleInbound({ kind: "notification", method: "thread/settings/updated", params: { threadId, threadSettings } });
|
|
23942
|
+
}
|
|
23621
23943
|
async handleServerRequest(message) {
|
|
23622
23944
|
const appServer = this.requireAppServer();
|
|
23623
23945
|
await this.expireApprovals();
|
|
@@ -23710,9 +24032,9 @@ var CodexRemoteDomain = class {
|
|
|
23710
24032
|
itemsView,
|
|
23711
24033
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
23712
24034
|
});
|
|
23713
|
-
const pageResult =
|
|
24035
|
+
const pageResult = isRecord11(result) ? result : {};
|
|
23714
24036
|
for (const rawTurn of array2(pageResult.data)) {
|
|
23715
|
-
if (!
|
|
24037
|
+
if (!isRecord11(rawTurn)) continue;
|
|
23716
24038
|
const turnId = typeof rawTurn.id === "string" ? rawTurn.id : void 0;
|
|
23717
24039
|
const items = rawTurn.itemsView === "full" || turnId === void 0 ? array2(rawTurn.items) : await this.readThreadItems(connectionId, threadId, turnId, array2(rawTurn.items));
|
|
23718
24040
|
turns.push({ ...rawTurn, items });
|
|
@@ -23734,9 +24056,9 @@ var CodexRemoteDomain = class {
|
|
|
23734
24056
|
sortDirection: "asc",
|
|
23735
24057
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
23736
24058
|
});
|
|
23737
|
-
const pageResult =
|
|
24059
|
+
const pageResult = isRecord11(result) ? result : {};
|
|
23738
24060
|
for (const entry of array2(pageResult.data)) {
|
|
23739
|
-
if (
|
|
24061
|
+
if (isRecord11(entry) && entry.item !== void 0) items.push(entry.item);
|
|
23740
24062
|
}
|
|
23741
24063
|
cursor2 = typeof pageResult.nextCursor === "string" && pageResult.nextCursor.length > 0 ? pageResult.nextCursor : void 0;
|
|
23742
24064
|
if (cursor2 === void 0) break;
|
|
@@ -23800,7 +24122,7 @@ var CodexRemoteDomain = class {
|
|
|
23800
24122
|
return [...this.peers.values()].some((peer) => peer.hasThreadSubscription(threadId));
|
|
23801
24123
|
}
|
|
23802
24124
|
resolveUpstreamApproval(params) {
|
|
23803
|
-
if (!
|
|
24125
|
+
if (!isRecord11(params) || typeof params.requestId !== "string" && typeof params.requestId !== "number") return;
|
|
23804
24126
|
for (const [handle, approval] of this.approvals) {
|
|
23805
24127
|
if (approval.upstreamId === params.requestId) this.approvals.delete(handle);
|
|
23806
24128
|
}
|
|
@@ -24017,24 +24339,24 @@ function codexBinaryCandidates(configured, hostPlatform = process.platform, user
|
|
|
24017
24339
|
])];
|
|
24018
24340
|
}
|
|
24019
24341
|
function parseCallEnvelope(input2) {
|
|
24020
|
-
if (!
|
|
24342
|
+
if (!isRecord11(input2) || typeof input2.method !== "string" || !("params" in input2) || Object.keys(input2).some((key) => key !== "method" && key !== "params")) {
|
|
24021
24343
|
throw new RpcError("INVALID_MESSAGE", "The Codex call envelope is invalid.");
|
|
24022
24344
|
}
|
|
24023
24345
|
return { method: input2.method, params: input2.params };
|
|
24024
24346
|
}
|
|
24025
24347
|
function parseRespond(input2) {
|
|
24026
|
-
if (!
|
|
24348
|
+
if (!isRecord11(input2) || typeof input2.requestHandle !== "string" || !["accept", "decline", "cancel"].includes(String(input2.decision)) || Object.keys(input2).some((key) => key !== "requestHandle" && key !== "decision")) {
|
|
24027
24349
|
throw new RpcError("INVALID_MESSAGE", "The Codex approval response is invalid.");
|
|
24028
24350
|
}
|
|
24029
24351
|
return input2;
|
|
24030
24352
|
}
|
|
24031
24353
|
function accountCanRun(result) {
|
|
24032
|
-
if (!
|
|
24033
|
-
return result.requiresOpenaiAuth === false ||
|
|
24354
|
+
if (!isRecord11(result) || typeof result.requiresOpenaiAuth !== "boolean") return false;
|
|
24355
|
+
return result.requiresOpenaiAuth === false || isRecord11(result.account);
|
|
24034
24356
|
}
|
|
24035
24357
|
function sanitizeAccount(result) {
|
|
24036
|
-
if (!
|
|
24037
|
-
const account =
|
|
24358
|
+
if (!isRecord11(result)) throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned invalid account state.");
|
|
24359
|
+
const account = isRecord11(result.account) ? result.account : void 0;
|
|
24038
24360
|
return {
|
|
24039
24361
|
authenticated: account !== void 0 || result.requiresOpenaiAuth === false,
|
|
24040
24362
|
requiresOpenaiAuth: result.requiresOpenaiAuth === true,
|
|
@@ -24047,11 +24369,11 @@ function sanitizeAccount(result) {
|
|
|
24047
24369
|
};
|
|
24048
24370
|
}
|
|
24049
24371
|
function sanitizeThreadList(result) {
|
|
24050
|
-
if (!
|
|
24372
|
+
if (!isRecord11(result) || !Array.isArray(result.data)) {
|
|
24051
24373
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid thread list.");
|
|
24052
24374
|
}
|
|
24053
24375
|
const data = result.data.flatMap((value) => {
|
|
24054
|
-
if (!
|
|
24376
|
+
if (!isRecord11(value) || typeof value.id !== "string") return [];
|
|
24055
24377
|
return [{
|
|
24056
24378
|
id: value.id,
|
|
24057
24379
|
...typeof value.sessionId === "string" ? { sessionId: value.sessionId } : {},
|
|
@@ -24063,7 +24385,7 @@ function sanitizeThreadList(result) {
|
|
|
24063
24385
|
...typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) ? { updatedAt: value.updatedAt } : {},
|
|
24064
24386
|
...typeof value.archived === "boolean" ? { archived: value.archived } : {},
|
|
24065
24387
|
...typeof value.isPinned === "boolean" ? { isPinned: value.isPinned } : {},
|
|
24066
|
-
...
|
|
24388
|
+
...isRecord11(value.status) ? { status: value.status } : {}
|
|
24067
24389
|
}];
|
|
24068
24390
|
});
|
|
24069
24391
|
return {
|
|
@@ -24073,18 +24395,18 @@ function sanitizeThreadList(result) {
|
|
|
24073
24395
|
};
|
|
24074
24396
|
}
|
|
24075
24397
|
function filterThreadListByWorkspaceAuthority(result, authority) {
|
|
24076
|
-
if (!
|
|
24398
|
+
if (!isRecord11(result) || !Array.isArray(result.data)) {
|
|
24077
24399
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid thread list.");
|
|
24078
24400
|
}
|
|
24079
24401
|
return {
|
|
24080
24402
|
...result,
|
|
24081
|
-
data: result.data.map((
|
|
24403
|
+
data: result.data.map((record6) => isRecord11(record6) ? record6 : void 0).filter((thread) => thread !== void 0 && isThreadAllowedByWorkspaceAuthority(thread, authority))
|
|
24082
24404
|
};
|
|
24083
24405
|
}
|
|
24084
24406
|
function sanitizeProject(value) {
|
|
24085
|
-
if (!
|
|
24407
|
+
if (!isRecord11(value) || typeof value.id !== "string" || typeof value.name !== "string") return void 0;
|
|
24086
24408
|
const roots = Array.isArray(value.roots) ? value.roots.flatMap((root) => {
|
|
24087
|
-
const path =
|
|
24409
|
+
const path = isRecord11(root) && typeof root.path === "string" && root.path.length > 0 ? root.path : void 0;
|
|
24088
24410
|
return path === void 0 || !isAbsolute3(path) ? [] : [{ path }];
|
|
24089
24411
|
}) : [];
|
|
24090
24412
|
if (roots.length === 0) return void 0;
|
|
@@ -24098,7 +24420,7 @@ function sanitizeProject(value) {
|
|
|
24098
24420
|
};
|
|
24099
24421
|
}
|
|
24100
24422
|
function sanitizeProjectList(result) {
|
|
24101
|
-
if (!
|
|
24423
|
+
if (!isRecord11(result) || !Array.isArray(result.data)) {
|
|
24102
24424
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid project list.");
|
|
24103
24425
|
}
|
|
24104
24426
|
const data = result.data.flatMap((value) => sanitizeProject(value) ?? []);
|
|
@@ -24108,7 +24430,7 @@ function sanitizeProjectList(result) {
|
|
|
24108
24430
|
};
|
|
24109
24431
|
}
|
|
24110
24432
|
function sanitizeProjectCreate(result) {
|
|
24111
|
-
const project =
|
|
24433
|
+
const project = isRecord11(result) ? sanitizeProject(result.project) : void 0;
|
|
24112
24434
|
if (project === void 0) {
|
|
24113
24435
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid created project.");
|
|
24114
24436
|
}
|
|
@@ -24140,19 +24462,19 @@ function codexDirectoryCrumbs(root, path) {
|
|
|
24140
24462
|
return crumbs2;
|
|
24141
24463
|
}
|
|
24142
24464
|
function extractThread(result) {
|
|
24143
|
-
return
|
|
24465
|
+
return isRecord11(result) && isRecord11(result.thread) ? result.thread : void 0;
|
|
24144
24466
|
}
|
|
24145
24467
|
function extractTurnId(result) {
|
|
24146
|
-
if (!
|
|
24468
|
+
if (!isRecord11(result)) return void 0;
|
|
24147
24469
|
if (typeof result.turnId === "string" && result.turnId.length > 0) return result.turnId;
|
|
24148
|
-
if (
|
|
24470
|
+
if (isRecord11(result.turn) && typeof result.turn.id === "string" && result.turn.id.length > 0) return result.turn.id;
|
|
24149
24471
|
return void 0;
|
|
24150
24472
|
}
|
|
24151
24473
|
function extractThreadId(params) {
|
|
24152
|
-
if (!
|
|
24474
|
+
if (!isRecord11(params)) return void 0;
|
|
24153
24475
|
if (typeof params.threadId === "string") return params.threadId;
|
|
24154
|
-
if (
|
|
24155
|
-
if (
|
|
24476
|
+
if (isRecord11(params.thread) && typeof params.thread.id === "string") return params.thread.id;
|
|
24477
|
+
if (isRecord11(params.turn) && typeof params.turn.threadId === "string") return params.turn.threadId;
|
|
24156
24478
|
return void 0;
|
|
24157
24479
|
}
|
|
24158
24480
|
function optionalInteger2(value) {
|
|
@@ -24194,13 +24516,13 @@ function mapCodexImageInputs(params) {
|
|
|
24194
24516
|
return {
|
|
24195
24517
|
...params,
|
|
24196
24518
|
input: params.input.map((value) => {
|
|
24197
|
-
if (!
|
|
24519
|
+
if (!isRecord11(value) || value.type !== "image" || typeof value.mediaType !== "string" || typeof value.data !== "string") return value;
|
|
24198
24520
|
return { type: "image", url: `data:${value.mediaType};base64,${value.data}` };
|
|
24199
24521
|
})
|
|
24200
24522
|
};
|
|
24201
24523
|
}
|
|
24202
24524
|
function sanitizeApprovalParams(params, requestHandle) {
|
|
24203
|
-
if (!
|
|
24525
|
+
if (!isRecord11(params)) return { requestHandle };
|
|
24204
24526
|
const safe = { ...params };
|
|
24205
24527
|
delete safe.proposedExecpolicyAmendment;
|
|
24206
24528
|
delete safe.additionalPermissions;
|
|
@@ -24231,7 +24553,7 @@ function isProjectListFallbackError(error) {
|
|
|
24231
24553
|
function canTryNextBinary(error) {
|
|
24232
24554
|
return !(error instanceof RpcError) || !["CODEX_AUTH_REQUIRED", "CODEX_CLOSED"].includes(error.code);
|
|
24233
24555
|
}
|
|
24234
|
-
function
|
|
24556
|
+
function isRecord11(value) {
|
|
24235
24557
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24236
24558
|
}
|
|
24237
24559
|
function array2(value) {
|
|
@@ -24339,6 +24661,9 @@ var HostPluginRuntime = class {
|
|
|
24339
24661
|
accountRequired: error === "ACCOUNT_AUTH_REQUIRED" || error === "AUTH_INVALID" || error === "TOKEN_EXPIRED"
|
|
24340
24662
|
};
|
|
24341
24663
|
}
|
|
24664
|
+
localHarnessVersion() {
|
|
24665
|
+
return this.harnessVersion;
|
|
24666
|
+
}
|
|
24342
24667
|
reconnectHost() {
|
|
24343
24668
|
if (this.closed) throw new Error("remote runtime is closed");
|
|
24344
24669
|
if (this.serverConnection === void 0) {
|
|
@@ -24508,9 +24833,13 @@ var HostPluginRuntime = class {
|
|
|
24508
24833
|
}
|
|
24509
24834
|
hostCapabilities() {
|
|
24510
24835
|
const capabilities = [];
|
|
24511
|
-
if (this.apiProxy !== void 0) capabilities.push("harness.api.v1", "harness.api.transfer.v1");
|
|
24512
24836
|
if (this.localGateway?.supportsCarrier === true) {
|
|
24513
|
-
capabilities.push(
|
|
24837
|
+
capabilities.push(
|
|
24838
|
+
harnessSessionGeneration(this.harnessVersion) === "v3" ? "harness.remote.v3" : "harness.remote.v1",
|
|
24839
|
+
"harness.remote.transfer.v1"
|
|
24840
|
+
);
|
|
24841
|
+
} else if (this.apiProxy !== void 0) {
|
|
24842
|
+
capabilities.push("harness.api.v1", "harness.api.transfer.v1");
|
|
24514
24843
|
}
|
|
24515
24844
|
if (this.fileViewerHost?.() !== void 0) capabilities.push("fileviewer.read.v1");
|
|
24516
24845
|
if (this.codex.isAvailable()) capabilities.push("codex.appserver.v1", "codex.appserver.transfer.v1");
|