ds-harness-remote 0.4.8 → 0.4.10
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 +65 -170
- package/dist/client-runtime.d.ts +5 -0
- package/dist/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +126 -51
- package/dist/client-runtime.js.map +1 -1
- package/dist/client.github.js +166 -121
- package/dist/client.js +166 -121
- 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 +2 -1
- package/dist/codex/virtual-harness.d.ts.map +1 -1
- package/dist/codex/virtual-harness.js +25 -36
- package/dist/codex/virtual-harness.js.map +1 -1
- package/dist/index.js +410 -198
- package/dist/index.js.map +4 -4
- 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/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 +18 -2
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),
|
|
@@ -14395,6 +14466,25 @@ function hasErrorCode(error, code) {
|
|
|
14395
14466
|
return error instanceof Error && "code" in error && error.code === code;
|
|
14396
14467
|
}
|
|
14397
14468
|
|
|
14469
|
+
// src/codex/permissions.ts
|
|
14470
|
+
function codexPermissionPresetFromResponse(value) {
|
|
14471
|
+
const root = record(value);
|
|
14472
|
+
for (const settings of [root, record(root.threadSettings)]) {
|
|
14473
|
+
const sandbox = settings.sandbox ?? settings.sandboxPolicy;
|
|
14474
|
+
const type = record(sandbox).type;
|
|
14475
|
+
if (settings.approvalPolicy === "never" && (sandbox === "danger-full-access" || type === "dangerFullAccess")) {
|
|
14476
|
+
return "danger-full-access";
|
|
14477
|
+
}
|
|
14478
|
+
if (settings.approvalPolicy === "on-request" && (sandbox === "workspace-write" || type === "workspaceWrite")) {
|
|
14479
|
+
return "workspace-write";
|
|
14480
|
+
}
|
|
14481
|
+
}
|
|
14482
|
+
return void 0;
|
|
14483
|
+
}
|
|
14484
|
+
function record(value) {
|
|
14485
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
14486
|
+
}
|
|
14487
|
+
|
|
14398
14488
|
// src/codex/virtual-harness.ts
|
|
14399
14489
|
var CODEX_SESSION_PREFIX = "codex:";
|
|
14400
14490
|
var CODEX_WORKSPACE_PREFIX = "codex-workspace:";
|
|
@@ -14643,10 +14733,11 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14643
14733
|
return this.selectedModels.get(sessionId) ?? directory?.default ?? modelSelection();
|
|
14644
14734
|
}
|
|
14645
14735
|
permissionSelection(sessionId) {
|
|
14646
|
-
return this.selectedPermissions.get(sessionId)
|
|
14736
|
+
return this.selectedPermissions.get(sessionId);
|
|
14647
14737
|
}
|
|
14648
14738
|
setPermissionSelection(sessionId, preset) {
|
|
14649
|
-
this.selectedPermissions.
|
|
14739
|
+
if (preset === void 0) this.selectedPermissions.delete(sessionId);
|
|
14740
|
+
else this.selectedPermissions.set(sessionId, preset);
|
|
14650
14741
|
this.publishProjection(sessionId, "permissions", codexPermissionsProjection(preset), this.nextProjectionSeq());
|
|
14651
14742
|
}
|
|
14652
14743
|
commandList(args) {
|
|
@@ -14670,17 +14761,22 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14670
14761
|
result: { kind: "error", text: "CodeX Remote permission commands do not accept attachments." }
|
|
14671
14762
|
};
|
|
14672
14763
|
const requested = (match[1] ?? "").trim();
|
|
14673
|
-
if (requested === "")
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14764
|
+
if (requested === "") {
|
|
14765
|
+
await this.readHistoryPage(threadId, { maxMessages: 1 }, signal);
|
|
14766
|
+
return {
|
|
14767
|
+
commandId,
|
|
14768
|
+
result: { kind: "success", text: `current preset ${this.permissionSelection(sessionId) ?? "Host settings (not reported)"}` }
|
|
14769
|
+
};
|
|
14770
|
+
}
|
|
14677
14771
|
if (!isCodexPermissionPreset(requested)) return {
|
|
14678
14772
|
commandId,
|
|
14679
14773
|
result: { kind: "error", text: `unknown preset "${requested}" (available: workspace-write, danger-full-access)` }
|
|
14680
14774
|
};
|
|
14681
14775
|
const result = await this.client.request("thread/resume", { threadId, permissionPreset: requested }, signal);
|
|
14682
|
-
const effective = codexPermissionPresetFromResponse(result)
|
|
14776
|
+
const effective = codexPermissionPresetFromResponse(result);
|
|
14777
|
+
if (effective === void 0) throw new Error("The Host did not confirm the CodeX permission preset.");
|
|
14683
14778
|
this.setPermissionSelection(sessionId, effective);
|
|
14779
|
+
if (effective !== requested) throw new Error("The Host did not apply the requested CodeX permission preset.");
|
|
14684
14780
|
return { commandId, result: { kind: "success", text: `preset ${effective}` } };
|
|
14685
14781
|
}
|
|
14686
14782
|
sessionTitle(sessionId) {
|
|
@@ -14812,7 +14908,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14812
14908
|
return queue.iterate(() => this.eventStreams.delete(clientId));
|
|
14813
14909
|
}
|
|
14814
14910
|
async sessionFollow(request, signal) {
|
|
14815
|
-
const sessionId = sessionIdFromAddress(
|
|
14911
|
+
const sessionId = sessionIdFromAddress(record2(request.address));
|
|
14816
14912
|
const threadId = nativeThreadId(sessionId);
|
|
14817
14913
|
const history = await this.readHistoryPage(threadId, {
|
|
14818
14914
|
maxMessages: optionalPositiveInteger(request.maxMessages)
|
|
@@ -14875,7 +14971,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14875
14971
|
});
|
|
14876
14972
|
}
|
|
14877
14973
|
acceptCodexFrame(follow, frame) {
|
|
14878
|
-
const params =
|
|
14974
|
+
const params = record2(frame.params);
|
|
14879
14975
|
if (frame.method === "thread/name/updated") {
|
|
14880
14976
|
const name2 = string(params.threadName);
|
|
14881
14977
|
if (name2 === void 0) return;
|
|
@@ -14887,11 +14983,11 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14887
14983
|
}
|
|
14888
14984
|
if (frame.method === "thread/settings/updated") {
|
|
14889
14985
|
const preset = codexPermissionPresetFromResponse(params);
|
|
14890
|
-
|
|
14986
|
+
this.setPermissionSelection(follow.sessionId, preset);
|
|
14891
14987
|
return;
|
|
14892
14988
|
}
|
|
14893
14989
|
if (frame.method === "turn/started") {
|
|
14894
|
-
const turn =
|
|
14990
|
+
const turn = record2(params.turn);
|
|
14895
14991
|
this.resetLiveTurn(follow);
|
|
14896
14992
|
follow.turn += 1;
|
|
14897
14993
|
follow.activeTurnId = string(turn.id);
|
|
@@ -14900,11 +14996,11 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14900
14996
|
this.pushEvent(follow, "turn/start", { turn: follow.turn });
|
|
14901
14997
|
this.pushEvent(follow, "step/start", { turn: follow.turn, step: 1 });
|
|
14902
14998
|
this.emitRemoteEvent("api-session/status", [follow.sessionId, true]);
|
|
14903
|
-
for (const item of array(turn.items)) this.acceptCompletedItem(follow,
|
|
14999
|
+
for (const item of array(turn.items)) this.acceptCompletedItem(follow, record2(item), false);
|
|
14904
15000
|
return;
|
|
14905
15001
|
}
|
|
14906
15002
|
if (frame.method === "item/started" || frame.method === "item/completed") {
|
|
14907
|
-
const item =
|
|
15003
|
+
const item = record2(params.item);
|
|
14908
15004
|
const itemId = string(item.id);
|
|
14909
15005
|
if (frame.method === "item/started" && itemId !== void 0) {
|
|
14910
15006
|
follow.startedItems.add(itemId);
|
|
@@ -14941,7 +15037,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14941
15037
|
}
|
|
14942
15038
|
if (frame.method === "turn/plan/updated") {
|
|
14943
15039
|
const todos = array(params.plan).flatMap((value) => {
|
|
14944
|
-
const item =
|
|
15040
|
+
const item = record2(value);
|
|
14945
15041
|
const content = string(item.step);
|
|
14946
15042
|
if (content === void 0) return [];
|
|
14947
15043
|
const status2 = item.status === "inProgress" ? "in_progress" : item.status === "completed" ? "completed" : "pending";
|
|
@@ -14975,7 +15071,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
14975
15071
|
return;
|
|
14976
15072
|
}
|
|
14977
15073
|
if (frame.method === "thread/status/changed") {
|
|
14978
|
-
const status2 =
|
|
15074
|
+
const status2 = record2(params.status);
|
|
14979
15075
|
const running = status2.type === "active";
|
|
14980
15076
|
this.emitRemoteEvent("api-session/status", [follow.sessionId, running]);
|
|
14981
15077
|
if (status2.type === "systemError") {
|
|
@@ -15002,8 +15098,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15002
15098
|
return;
|
|
15003
15099
|
}
|
|
15004
15100
|
if (frame.method === "turn/completed") {
|
|
15005
|
-
const turn =
|
|
15006
|
-
for (const item of array(turn.items)) this.acceptCompletedItem(follow,
|
|
15101
|
+
const turn = record2(params.turn);
|
|
15102
|
+
for (const item of array(turn.items)) this.acceptCompletedItem(follow, record2(item), true);
|
|
15007
15103
|
if (follow.stepOpen) {
|
|
15008
15104
|
this.closeAllStreamBlocks(follow);
|
|
15009
15105
|
if (follow.streamActive) this.finishStream(follow);
|
|
@@ -15098,7 +15194,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15098
15194
|
}
|
|
15099
15195
|
cacheImageBlocks(sessionId, value) {
|
|
15100
15196
|
for (const block of collectImageBlocks(value)) {
|
|
15101
|
-
const attachment =
|
|
15197
|
+
const attachment = record2(block.attachment);
|
|
15102
15198
|
const attachmentId = string(attachment.attachmentId);
|
|
15103
15199
|
const data = string(block.data);
|
|
15104
15200
|
if (attachmentId === void 0 || data === void 0 || !attachmentId.startsWith(CODEX_IMAGE_ATTACHMENT_PREFIX)) continue;
|
|
@@ -15239,7 +15335,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15239
15335
|
}
|
|
15240
15336
|
async answerRemoteEvent(args, signal) {
|
|
15241
15337
|
const eventId = string(args.eventId);
|
|
15242
|
-
const outcome =
|
|
15338
|
+
const outcome = record2(args.outcome);
|
|
15243
15339
|
if (eventId === void 0) throw new Error("The CodeX approval result is missing its event id.");
|
|
15244
15340
|
const pending = this.pendingApprovals.get(eventId);
|
|
15245
15341
|
if (pending === void 0) return void 0;
|
|
@@ -15290,7 +15386,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15290
15386
|
if (!containsPath(workspace.path, path)) {
|
|
15291
15387
|
return failure("workspace-not-found", "The selected directory is outside the current CodeX virtual Workspace.");
|
|
15292
15388
|
}
|
|
15293
|
-
const listing =
|
|
15389
|
+
const listing = record2(await this.client.request("dsh/directoryList", { path }, signal));
|
|
15294
15390
|
if (!isCodexDirectoryListing(listing)) {
|
|
15295
15391
|
return failure("internal", "CodeX Remote returned an invalid directory listing.");
|
|
15296
15392
|
}
|
|
@@ -15324,13 +15420,13 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15324
15420
|
const directory = await this.models(signal);
|
|
15325
15421
|
const selection = directory.default;
|
|
15326
15422
|
const requestedPreset = CODEX_DEFAULT_PERMISSION;
|
|
15327
|
-
const result =
|
|
15423
|
+
const result = record2(await this.client.request("thread/start", {
|
|
15328
15424
|
cwd,
|
|
15329
15425
|
model: selection.model,
|
|
15330
15426
|
permissionPreset: requestedPreset
|
|
15331
15427
|
}, signal));
|
|
15332
15428
|
const permissionPreset2 = codexPermissionPresetFromResponse(result) ?? requestedPreset;
|
|
15333
|
-
const thread = { ...
|
|
15429
|
+
const thread = { ...record2(result.thread), cwd, turns: array(record2(result.thread).turns) };
|
|
15334
15430
|
const projected = projectCodexThread(thread);
|
|
15335
15431
|
if (projected === void 0) return failure("internal", "CodeX returned an invalid Thread.");
|
|
15336
15432
|
this.pendingThreads.set(projected.nativeId, thread);
|
|
@@ -15350,16 +15446,14 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15350
15446
|
}
|
|
15351
15447
|
async forkSession(request, signal) {
|
|
15352
15448
|
const sessionId = requiredString(request.sessionId, "sessionId");
|
|
15353
|
-
|
|
15354
|
-
|
|
15355
|
-
threadId: nativeThreadId(sessionId),
|
|
15356
|
-
...permissionPreset2 === void 0 ? {} : { permissionPreset: permissionPreset2 }
|
|
15449
|
+
const result = record2(await this.client.request("thread/fork", {
|
|
15450
|
+
threadId: nativeThreadId(sessionId)
|
|
15357
15451
|
}, signal));
|
|
15358
|
-
permissionPreset2 = codexPermissionPresetFromResponse(result)
|
|
15359
|
-
const projected = projectCodexThread(
|
|
15452
|
+
const permissionPreset2 = codexPermissionPresetFromResponse(result);
|
|
15453
|
+
const projected = projectCodexThread(record2(result.thread));
|
|
15360
15454
|
if (projected === void 0) return failure("internal", "CodeX returned an invalid forked Thread.");
|
|
15361
15455
|
this.selectedModels.set(projected.id, this.modelSelection(sessionId, await this.models(signal)));
|
|
15362
|
-
this.
|
|
15456
|
+
this.setPermissionSelection(projected.id, permissionPreset2);
|
|
15363
15457
|
await this.refreshAndPublishWorkspaces();
|
|
15364
15458
|
const seq = this.nextProjectionSeq();
|
|
15365
15459
|
this.publishProjection(projected.id, "title", displayTitle(projected), seq);
|
|
@@ -15372,7 +15466,6 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15372
15466
|
if (input2 === void 0) return failure("attachment-error", "CodeX virtual Sessions accept text and pasted PNG, JPEG, WebP, or GIF images only.");
|
|
15373
15467
|
const threadId = nativeThreadId(sessionId);
|
|
15374
15468
|
const selection = this.modelSelection(sessionId, await this.models(signal));
|
|
15375
|
-
let permissionPreset2 = this.selectedPermissions.get(sessionId);
|
|
15376
15469
|
const isFreshBlankThread = this.blankThreads.has(threadId) || this.pendingThreads.has(threadId);
|
|
15377
15470
|
await this.ensureRcFollow(sessionId);
|
|
15378
15471
|
if (!isFreshBlankThread) {
|
|
@@ -15381,8 +15474,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15381
15474
|
model: selection.model
|
|
15382
15475
|
}, signal);
|
|
15383
15476
|
const serverPreset = codexPermissionPresetFromResponse(resumeResult);
|
|
15384
|
-
if (
|
|
15385
|
-
permissionPreset2 = serverPreset;
|
|
15477
|
+
if (serverPreset !== void 0) {
|
|
15386
15478
|
this.setPermissionSelection(sessionId, serverPreset);
|
|
15387
15479
|
}
|
|
15388
15480
|
}
|
|
@@ -15396,8 +15488,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15396
15488
|
await this.client.request(mode, {
|
|
15397
15489
|
threadId,
|
|
15398
15490
|
input: input2,
|
|
15399
|
-
...codexModelParams(selection)
|
|
15400
|
-
...permissionPreset2 === void 0 ? {} : { permissionPreset: permissionPreset2 }
|
|
15491
|
+
...codexModelParams(selection)
|
|
15401
15492
|
}, signal);
|
|
15402
15493
|
}
|
|
15403
15494
|
this.blankThreads.delete(threadId);
|
|
@@ -15418,8 +15509,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15418
15509
|
}
|
|
15419
15510
|
async hydrateImageAttachments(sessionId, signal) {
|
|
15420
15511
|
const threadId = nativeThreadId(sessionId);
|
|
15421
|
-
const result =
|
|
15422
|
-
const thread =
|
|
15512
|
+
const result = record2(await this.client.request("thread/read", { threadId, includeTurns: true }, signal));
|
|
15513
|
+
const thread = record2(result.thread);
|
|
15423
15514
|
if (string(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
|
|
15424
15515
|
this.cacheHistoryImages(projectCodexNativeHistory(thread, sessionId));
|
|
15425
15516
|
}
|
|
@@ -15441,7 +15532,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15441
15532
|
return success({ title, seq });
|
|
15442
15533
|
}
|
|
15443
15534
|
async sessionPage(request, signal) {
|
|
15444
|
-
const sessionId = sessionIdFromAddress(
|
|
15535
|
+
const sessionId = sessionIdFromAddress(record2(request.address));
|
|
15445
15536
|
const page = await this.readHistoryPage(nativeThreadId(sessionId), {
|
|
15446
15537
|
beforeSeq: optionalNonNegativeInteger(request.beforeSeq),
|
|
15447
15538
|
throughSeq: optionalInteger(request.throughSeq),
|
|
@@ -15454,15 +15545,15 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15454
15545
|
return void 0;
|
|
15455
15546
|
}
|
|
15456
15547
|
async fetchThread(threadId, signal) {
|
|
15457
|
-
const result =
|
|
15458
|
-
const thread =
|
|
15548
|
+
const result = record2(await this.client.request("thread/read", { threadId, includeTurns: false }, signal));
|
|
15549
|
+
const thread = record2(result.thread);
|
|
15459
15550
|
if (string(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
|
|
15460
15551
|
return thread;
|
|
15461
15552
|
}
|
|
15462
15553
|
async readHistoryPage(threadId, page, signal) {
|
|
15463
15554
|
let value;
|
|
15464
15555
|
try {
|
|
15465
|
-
value =
|
|
15556
|
+
value = record2(await this.client.request("dsh/sessionHistory", {
|
|
15466
15557
|
threadId,
|
|
15467
15558
|
...page.beforeSeq === void 0 ? {} : { beforeSeq: page.beforeSeq },
|
|
15468
15559
|
...page.throughSeq === void 0 ? {} : { throughSeq: page.throughSeq },
|
|
@@ -15470,8 +15561,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15470
15561
|
}, signal));
|
|
15471
15562
|
} catch (error) {
|
|
15472
15563
|
if (!isLegacySessionHistoryUnsupported(error)) throw error;
|
|
15473
|
-
const result =
|
|
15474
|
-
const thread =
|
|
15564
|
+
const result = record2(await this.client.request("thread/read", { threadId, includeTurns: true }, signal));
|
|
15565
|
+
const thread = record2(result.thread);
|
|
15475
15566
|
if (string(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
|
|
15476
15567
|
value = paginateCodexNativeHistory(
|
|
15477
15568
|
projectCodexNativeHistory(thread, `codex:${threadId}`),
|
|
@@ -15485,6 +15576,10 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15485
15576
|
if (!isCodexNativeHistoryPage(value, `codex:${threadId}`)) {
|
|
15486
15577
|
throw new Error("CodeX Remote returned an invalid paginated History.");
|
|
15487
15578
|
}
|
|
15579
|
+
if (Object.hasOwn(value, "permissionPreset")) {
|
|
15580
|
+
const preset = value.permissionPreset;
|
|
15581
|
+
this.setPermissionSelection(`codex:${threadId}`, preset === "workspace-write" || preset === "danger-full-access" ? preset : void 0);
|
|
15582
|
+
}
|
|
15488
15583
|
this.cacheHistoryImages(value);
|
|
15489
15584
|
return value;
|
|
15490
15585
|
}
|
|
@@ -15692,7 +15787,7 @@ async function loadCatalog(client, signal, pendingThreads) {
|
|
|
15692
15787
|
const threads = [];
|
|
15693
15788
|
let cursor2;
|
|
15694
15789
|
for (let page = 0; page < MAX_CODEX_PAGES; page += 1) {
|
|
15695
|
-
const result =
|
|
15790
|
+
const result = record2(await client.request("thread/list", {
|
|
15696
15791
|
limit: CODEX_PAGE_LIMIT,
|
|
15697
15792
|
sortKey: "updated_at",
|
|
15698
15793
|
sortDirection: "desc",
|
|
@@ -15700,7 +15795,7 @@ async function loadCatalog(client, signal, pendingThreads) {
|
|
|
15700
15795
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
15701
15796
|
}, signal));
|
|
15702
15797
|
for (const value of array(result.data)) {
|
|
15703
|
-
const thread =
|
|
15798
|
+
const thread = record2(value);
|
|
15704
15799
|
if (string(thread.id) !== void 0) threads.push(thread);
|
|
15705
15800
|
}
|
|
15706
15801
|
cursor2 = typeof result.nextCursor === "string" && result.nextCursor.length > 0 ? result.nextCursor : void 0;
|
|
@@ -15752,7 +15847,7 @@ async function loadCodexProjects(client, signal) {
|
|
|
15752
15847
|
let cursor2;
|
|
15753
15848
|
try {
|
|
15754
15849
|
for (let page = 0; page < MAX_CODEX_PAGES; page += 1) {
|
|
15755
|
-
const result =
|
|
15850
|
+
const result = record2(await client.request("project/list", {
|
|
15756
15851
|
limit: CODEX_PAGE_LIMIT,
|
|
15757
15852
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
15758
15853
|
}, signal));
|
|
@@ -15774,18 +15869,18 @@ async function loadModelDirectory(client, signal) {
|
|
|
15774
15869
|
let defaultModelId;
|
|
15775
15870
|
let cursor2;
|
|
15776
15871
|
for (let page = 0; page < MAX_CODEX_PAGES; page += 1) {
|
|
15777
|
-
const result =
|
|
15872
|
+
const result = record2(await client.request("model/list", {
|
|
15778
15873
|
limit: CODEX_PAGE_LIMIT,
|
|
15779
15874
|
includeHidden: false,
|
|
15780
15875
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
15781
15876
|
}, signal));
|
|
15782
15877
|
for (const value of array(result.data)) {
|
|
15783
|
-
const source =
|
|
15878
|
+
const source = record2(value);
|
|
15784
15879
|
if (source.hidden === true) continue;
|
|
15785
15880
|
const id2 = string(source.model) ?? string(source.id);
|
|
15786
15881
|
if (id2 === void 0 || models.has(id2)) continue;
|
|
15787
15882
|
const efforts = array(source.supportedReasoningEfforts).map((value2) => {
|
|
15788
|
-
const effort =
|
|
15883
|
+
const effort = record2(value2);
|
|
15789
15884
|
const effortId = string(effort.reasoningEffort);
|
|
15790
15885
|
if (effortId === void 0) return void 0;
|
|
15791
15886
|
const description2 = string(effort.description);
|
|
@@ -15849,8 +15944,8 @@ function projectCodexNativeHistory(thread, sessionId) {
|
|
|
15849
15944
|
return eventSeq;
|
|
15850
15945
|
};
|
|
15851
15946
|
for (const rawTurn of array(thread.turns)) {
|
|
15852
|
-
const turn =
|
|
15853
|
-
const turnItems = array(turn.items).map(
|
|
15947
|
+
const turn = record2(rawTurn);
|
|
15948
|
+
const turnItems = array(turn.items).map(record2);
|
|
15854
15949
|
const toolImages = turnItems.flatMap(toolOutputImageBlocks);
|
|
15855
15950
|
let imageOwner = -1;
|
|
15856
15951
|
for (let index = 0; index < turnItems.length; index += 1) {
|
|
@@ -15999,15 +16094,15 @@ function messageContent(item, attachmentSeed, fallbackType, fallbackText, supple
|
|
|
15999
16094
|
}
|
|
16000
16095
|
function toolOutputImageBlocks(item) {
|
|
16001
16096
|
const candidates = [
|
|
16002
|
-
|
|
16003
|
-
|
|
16097
|
+
record2(item.result).content,
|
|
16098
|
+
record2(item.output).content,
|
|
16004
16099
|
item.contentItems,
|
|
16005
16100
|
Array.isArray(item.output) ? item.output : void 0
|
|
16006
16101
|
];
|
|
16007
16102
|
for (const candidate of candidates) {
|
|
16008
16103
|
if (!Array.isArray(candidate)) continue;
|
|
16009
16104
|
const images = candidate.flatMap((value) => {
|
|
16010
|
-
const block =
|
|
16105
|
+
const block = record2(value);
|
|
16011
16106
|
return isImageContent2(block) && parseImageBlock(block) !== void 0 ? [block] : [];
|
|
16012
16107
|
});
|
|
16013
16108
|
if (images.length > 0) return images;
|
|
@@ -16024,7 +16119,7 @@ function contentBlocks(value, attachmentSeed) {
|
|
|
16024
16119
|
blocks.push({ type: "text", text: raw });
|
|
16025
16120
|
continue;
|
|
16026
16121
|
}
|
|
16027
|
-
const block =
|
|
16122
|
+
const block = record2(raw);
|
|
16028
16123
|
const image = imageContentBlock(block, attachmentSeed, imageIndex);
|
|
16029
16124
|
if (image !== void 0) {
|
|
16030
16125
|
imageIndex += 1;
|
|
@@ -16063,7 +16158,7 @@ function isImageContent2(block) {
|
|
|
16063
16158
|
return block.type === "image" || block.type === "input_image";
|
|
16064
16159
|
}
|
|
16065
16160
|
function parseImageBlock(block) {
|
|
16066
|
-
const url = string(block.url) ?? string(block.image_url) ?? string(
|
|
16161
|
+
const url = string(block.url) ?? string(block.image_url) ?? string(record2(block.image_url).url);
|
|
16067
16162
|
const parsed = url === void 0 ? void 0 : parseDataImageUrl2(url);
|
|
16068
16163
|
if (parsed !== void 0) return parsed;
|
|
16069
16164
|
const data = string(block.data);
|
|
@@ -16220,10 +16315,10 @@ function toolResultEvent(item, turn, step, id2, resultText) {
|
|
|
16220
16315
|
};
|
|
16221
16316
|
}
|
|
16222
16317
|
function toolResultContentReplacement(event) {
|
|
16223
|
-
const data =
|
|
16224
|
-
const message =
|
|
16318
|
+
const data = record2(event.data);
|
|
16319
|
+
const message = record2(data.message);
|
|
16225
16320
|
const content = array(message.content);
|
|
16226
|
-
const result =
|
|
16321
|
+
const result = record2(content[0]);
|
|
16227
16322
|
if (result.isError === void 0) return event;
|
|
16228
16323
|
const { isError: _isError, ...stableResult } = result;
|
|
16229
16324
|
return {
|
|
@@ -16263,9 +16358,9 @@ function toolResultText(item, type, text) {
|
|
|
16263
16358
|
if (type === "exitedReviewMode") return `Exited review mode${string(item.review) ? `: ${string(item.review)}` : "."}`;
|
|
16264
16359
|
if (type === "sleep") return `Waited ${integer(item.durationMs) ?? 0} ms.`;
|
|
16265
16360
|
if (type === "subAgentActivity") {
|
|
16266
|
-
return [string(
|
|
16361
|
+
return [string(record2(item.kind).type) ?? string(item.kind) ?? "Subagent activity", string(item.agentPath)].filter((value) => value !== void 0).join(": ");
|
|
16267
16362
|
}
|
|
16268
|
-
return text ?? itemText2(
|
|
16363
|
+
return text ?? itemText2(record2(item.result)) ?? itemText2(record2(item.output)) ?? string(item.status) ?? type;
|
|
16269
16364
|
}
|
|
16270
16365
|
function isSurfaceEvent(type) {
|
|
16271
16366
|
return type === "user/message" || type === "assistant/message" || type === "tool/result";
|
|
@@ -16337,10 +16432,10 @@ function toolResultView(item, type, resultText) {
|
|
|
16337
16432
|
};
|
|
16338
16433
|
}
|
|
16339
16434
|
function toolDisplayName(item, type) {
|
|
16340
|
-
return string(item.name) ?? string(item.tool) ?? string(
|
|
16435
|
+
return string(item.name) ?? string(item.tool) ?? string(record2(item.tool).name) ?? (type === "mcpToolCall" ? "CodeX MCP tool" : humanizeItemType(type));
|
|
16341
16436
|
}
|
|
16342
16437
|
function fileLocations(item) {
|
|
16343
|
-
return array(item.changes).map((value) => string(
|
|
16438
|
+
return array(item.changes).map((value) => string(record2(value).path)).filter((path) => path !== void 0 && path.length > 0).map((path) => ({ path }));
|
|
16344
16439
|
}
|
|
16345
16440
|
function nativeWorkspace(view) {
|
|
16346
16441
|
const { sessionCount: _sessionCount, ...workspace } = view;
|
|
@@ -16362,10 +16457,10 @@ function projectWorkspace(project) {
|
|
|
16362
16457
|
};
|
|
16363
16458
|
}
|
|
16364
16459
|
function projectCodexProject(value, fallbackPosition) {
|
|
16365
|
-
const source =
|
|
16460
|
+
const source = record2(value);
|
|
16366
16461
|
const id2 = string(source.id);
|
|
16367
16462
|
if (id2 === void 0) return void 0;
|
|
16368
|
-
const roots = array(source.roots).map((root) => string(
|
|
16463
|
+
const roots = array(source.roots).map((root) => string(record2(root).path)).filter((path) => path !== void 0 && path.length > 0).map((path) => ({ path }));
|
|
16369
16464
|
if (roots.length === 0) return void 0;
|
|
16370
16465
|
return {
|
|
16371
16466
|
id: id2,
|
|
@@ -16436,7 +16531,7 @@ function isCanonicalBase642(value) {
|
|
|
16436
16531
|
function modelSelectionProjection(selection) {
|
|
16437
16532
|
return { lastUsed: selection, next: selection };
|
|
16438
16533
|
}
|
|
16439
|
-
function codexPermissionsProjection(
|
|
16534
|
+
function codexPermissionsProjection(preset) {
|
|
16440
16535
|
return {
|
|
16441
16536
|
options: [
|
|
16442
16537
|
{
|
|
@@ -16450,7 +16545,7 @@ function codexPermissionsProjection(currentValue) {
|
|
|
16450
16545
|
description: "Full Host file access without approval prompts for subsequent turns in this virtual Session."
|
|
16451
16546
|
}
|
|
16452
16547
|
],
|
|
16453
|
-
currentValue
|
|
16548
|
+
currentValue: preset ?? "Host settings (not reported)"
|
|
16454
16549
|
};
|
|
16455
16550
|
}
|
|
16456
16551
|
function codexImageLimitsProjection() {
|
|
@@ -16466,22 +16561,6 @@ function codexImageLimitsProjection() {
|
|
|
16466
16561
|
function isCodexPermissionPreset(value) {
|
|
16467
16562
|
return value === "workspace-write" || value === "danger-full-access";
|
|
16468
16563
|
}
|
|
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
16564
|
function modelCatalog(directory) {
|
|
16486
16565
|
return {
|
|
16487
16566
|
default: directory.default,
|
|
@@ -16520,7 +16599,7 @@ function itemText2(value) {
|
|
|
16520
16599
|
if (content !== void 0) {
|
|
16521
16600
|
const text = content.map((part) => {
|
|
16522
16601
|
if (typeof part === "string") return part;
|
|
16523
|
-
const block =
|
|
16602
|
+
const block = record2(part);
|
|
16524
16603
|
return string(block.text) ?? string(block.content) ?? "";
|
|
16525
16604
|
}).filter(Boolean).join("\n");
|
|
16526
16605
|
if (text !== "") return text;
|
|
@@ -16534,8 +16613,8 @@ function toolArguments(item) {
|
|
|
16534
16613
|
if (item.type === "commandExecution") return { command: commandText(item.command) ?? item.command ?? "" };
|
|
16535
16614
|
if (item.type === "fileChange") return {
|
|
16536
16615
|
changes: array(item.changes).map((value) => {
|
|
16537
|
-
const change =
|
|
16538
|
-
const kind = typeof change.kind === "string" ? change.kind : string(
|
|
16616
|
+
const change = record2(value);
|
|
16617
|
+
const kind = typeof change.kind === "string" ? change.kind : string(record2(change.kind).type);
|
|
16539
16618
|
return {
|
|
16540
16619
|
...typeof change.path === "string" ? { path: change.path } : {},
|
|
16541
16620
|
...kind === void 0 ? {} : { kind }
|
|
@@ -16556,7 +16635,7 @@ function toolArguments(item) {
|
|
|
16556
16635
|
if (item.type === "subAgentActivity") return {
|
|
16557
16636
|
agentThreadId: string(item.agentThreadId) ?? "",
|
|
16558
16637
|
agentPath: string(item.agentPath) ?? "",
|
|
16559
|
-
kind: string(
|
|
16638
|
+
kind: string(record2(item.kind).type) ?? string(item.kind) ?? "activity"
|
|
16560
16639
|
};
|
|
16561
16640
|
if (item.type === "sleep") return { durationMs: integer(item.durationMs) ?? 0 };
|
|
16562
16641
|
if (item.type === "enteredReviewMode" || item.type === "exitedReviewMode") return {
|
|
@@ -16567,19 +16646,19 @@ function toolArguments(item) {
|
|
|
16567
16646
|
}
|
|
16568
16647
|
function fileChangeSummary(item) {
|
|
16569
16648
|
const changes = array(item.changes).map((value) => {
|
|
16570
|
-
const change =
|
|
16649
|
+
const change = record2(value);
|
|
16571
16650
|
const path = string(change.path);
|
|
16572
|
-
const kind = typeof change.kind === "string" ? change.kind : string(
|
|
16651
|
+
const kind = typeof change.kind === "string" ? change.kind : string(record2(change.kind).type);
|
|
16573
16652
|
return [kind, path].filter((part) => part !== void 0 && part.length > 0).join(" ");
|
|
16574
16653
|
}).filter(Boolean);
|
|
16575
16654
|
return changes.length === 0 ? "File changes completed." : changes.join("\n");
|
|
16576
16655
|
}
|
|
16577
16656
|
function sanitizedFileChanges(value) {
|
|
16578
16657
|
return array(value).flatMap((raw) => {
|
|
16579
|
-
const change =
|
|
16658
|
+
const change = record2(raw);
|
|
16580
16659
|
const path = string(change.path);
|
|
16581
16660
|
if (path === void 0) return [];
|
|
16582
|
-
const kind = typeof change.kind === "string" ? change.kind : string(
|
|
16661
|
+
const kind = typeof change.kind === "string" ? change.kind : string(record2(change.kind).type);
|
|
16583
16662
|
return [{ path, ...kind === void 0 ? {} : { kind } }];
|
|
16584
16663
|
});
|
|
16585
16664
|
}
|
|
@@ -16609,7 +16688,7 @@ function humanizeItemType(type) {
|
|
|
16609
16688
|
function commandText(value) {
|
|
16610
16689
|
if (typeof value === "string") return value;
|
|
16611
16690
|
if (Array.isArray(value)) return value.filter((item) => typeof item === "string").join(" ");
|
|
16612
|
-
const source =
|
|
16691
|
+
const source = record2(value);
|
|
16613
16692
|
return string(source.command) ?? string(source.text);
|
|
16614
16693
|
}
|
|
16615
16694
|
function sessionIdFromAddress(address) {
|
|
@@ -16625,7 +16704,7 @@ function nativeThreadId(sessionId) {
|
|
|
16625
16704
|
function activeTurnId(value) {
|
|
16626
16705
|
if (!Array.isArray(value)) return void 0;
|
|
16627
16706
|
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
16628
|
-
const turn =
|
|
16707
|
+
const turn = record2(value[index]);
|
|
16629
16708
|
if (isActiveCodexTurn(turn) && typeof turn.id === "string" && turn.id.length > 0) return turn.id;
|
|
16630
16709
|
}
|
|
16631
16710
|
return void 0;
|
|
@@ -16634,10 +16713,10 @@ function isActiveCodexTurn(turn) {
|
|
|
16634
16713
|
return turn.status === "inProgress" || turn.status === "running";
|
|
16635
16714
|
}
|
|
16636
16715
|
function carrierArgs(payload) {
|
|
16637
|
-
return
|
|
16716
|
+
return record2(record2(payload).args);
|
|
16638
16717
|
}
|
|
16639
16718
|
function requestArg(args) {
|
|
16640
|
-
return
|
|
16719
|
+
return record2(args.request ?? args._request ?? args);
|
|
16641
16720
|
}
|
|
16642
16721
|
function rcEndpoint(endpoint) {
|
|
16643
16722
|
if (endpoint === "workspace.list") return "workspace/list";
|
|
@@ -16653,20 +16732,20 @@ function ok(value) {
|
|
|
16653
16732
|
return value === void 0 ? { ok: true } : { ok: true, value };
|
|
16654
16733
|
}
|
|
16655
16734
|
function business(value) {
|
|
16656
|
-
const result =
|
|
16735
|
+
const result = record2(value);
|
|
16657
16736
|
if (result.ok === true) return ok(result.value);
|
|
16658
16737
|
if (result.ok === false) {
|
|
16659
|
-
const error =
|
|
16660
|
-
return fail(string(error.code) ?? "internal", string(error.message) ?? "CodeX virtual Harness rejected the request.",
|
|
16738
|
+
const error = record2(result.error);
|
|
16739
|
+
return fail(string(error.code) ?? "internal", string(error.message) ?? "CodeX virtual Harness rejected the request.", record2(error.details));
|
|
16661
16740
|
}
|
|
16662
16741
|
return ok(value);
|
|
16663
16742
|
}
|
|
16664
16743
|
function isCodexDirectoryListing(value) {
|
|
16665
|
-
const listing =
|
|
16744
|
+
const listing = record2(value);
|
|
16666
16745
|
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
16746
|
}
|
|
16668
16747
|
function isCodexDirectoryEntry(value) {
|
|
16669
|
-
const entry =
|
|
16748
|
+
const entry = record2(value);
|
|
16670
16749
|
return typeof entry.name === "string" && typeof entry.path === "string" && typeof entry.hidden === "boolean";
|
|
16671
16750
|
}
|
|
16672
16751
|
function fail(code, message, details = {}) {
|
|
@@ -16686,7 +16765,7 @@ function errorCode(error) {
|
|
|
16686
16765
|
function errorDetails(error) {
|
|
16687
16766
|
return "details" in error && isRecord3(error.details) ? error.details : {};
|
|
16688
16767
|
}
|
|
16689
|
-
function
|
|
16768
|
+
function record2(value) {
|
|
16690
16769
|
return isRecord3(value) ? value : {};
|
|
16691
16770
|
}
|
|
16692
16771
|
function isRecord3(value) {
|
|
@@ -16721,8 +16800,8 @@ function optionalPositiveInteger(value) {
|
|
|
16721
16800
|
return parsed;
|
|
16722
16801
|
}
|
|
16723
16802
|
function isCodexNativeHistoryPage(value, sessionId) {
|
|
16724
|
-
const page =
|
|
16725
|
-
const header =
|
|
16803
|
+
const page = record2(value);
|
|
16804
|
+
const header = record2(page.header);
|
|
16726
16805
|
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
16806
|
}
|
|
16728
16807
|
function truncateCodePoints(value, maximum) {
|
|
@@ -16903,7 +16982,7 @@ function normalizeServerUrl(value) {
|
|
|
16903
16982
|
}
|
|
16904
16983
|
|
|
16905
16984
|
// src/version.ts
|
|
16906
|
-
var PLUGIN_VERSION = "0.4.
|
|
16985
|
+
var PLUGIN_VERSION = "0.4.10";
|
|
16907
16986
|
|
|
16908
16987
|
// src/server-api.ts
|
|
16909
16988
|
var TERMINAL_CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/u;
|
|
@@ -17218,10 +17297,11 @@ var ServerApiError = class extends Error {
|
|
|
17218
17297
|
}
|
|
17219
17298
|
};
|
|
17220
17299
|
function validateTokens(value) {
|
|
17221
|
-
|
|
17300
|
+
const parsed = deviceTokenPairSchema.safeParse(value);
|
|
17301
|
+
if (!parsed.success) {
|
|
17222
17302
|
throw new ServerApiError("INVALID_MESSAGE", "The Server returned invalid device credentials.", false);
|
|
17223
17303
|
}
|
|
17224
|
-
return
|
|
17304
|
+
return parsed.data;
|
|
17225
17305
|
}
|
|
17226
17306
|
function validateWebLogin(value) {
|
|
17227
17307
|
const item = requireRecord(value, "account login");
|
|
@@ -18516,6 +18596,7 @@ function isPrivate(ip) {
|
|
|
18516
18596
|
var REMOTE_COMMAND_LIST_MIN_VERSION = [0, 3, 16];
|
|
18517
18597
|
var REMOTE_FILE_VIEWER_MIN_VERSION = [0, 3, 17];
|
|
18518
18598
|
var DIRECT_WEBRTC_NEGOTIATE_TIMEOUT_MS = 12e3;
|
|
18599
|
+
var DIRECT_LAN_PROGRESS_DISPLAY_MS = 1400;
|
|
18519
18600
|
var ClientModeRuntime = class {
|
|
18520
18601
|
constructor(config, identities, server, apiProxy, typertGateway, logger, host, rtcFactoryProvider = loadNodeRtcFactory) {
|
|
18521
18602
|
this.config = config;
|
|
@@ -18534,6 +18615,8 @@ var ClientModeRuntime = class {
|
|
|
18534
18615
|
proxySwitch;
|
|
18535
18616
|
gatewaySwitch;
|
|
18536
18617
|
codexStreams = /* @__PURE__ */ new Map();
|
|
18618
|
+
connectionProgress;
|
|
18619
|
+
connectionProgressRun = 0;
|
|
18537
18620
|
closed = false;
|
|
18538
18621
|
async start() {
|
|
18539
18622
|
if (this.closed) throw new Error("client remote-mode runtime is closed");
|
|
@@ -18562,7 +18645,15 @@ var ClientModeRuntime = class {
|
|
|
18562
18645
|
...targetStatus,
|
|
18563
18646
|
connected: this.connected !== void 0,
|
|
18564
18647
|
transport: this.connected?.client.getStats().mode ?? "Disconnected",
|
|
18648
|
+
connectedTargetDeviceId: this.connected?.target.deviceId,
|
|
18565
18649
|
preferredTransports: this.config.forceRelay ? ["relay"] : ["lan", "p2p", "turn", "relay"],
|
|
18650
|
+
...this.connectionProgress === void 0 ? {} : {
|
|
18651
|
+
connectionProgress: {
|
|
18652
|
+
targetDeviceId: this.connectionProgress.targetDeviceId,
|
|
18653
|
+
phase: this.connectionProgress.phase,
|
|
18654
|
+
...this.connectionProgress.activeTransports === void 0 ? {} : { activeTransports: [...this.connectionProgress.activeTransports] }
|
|
18655
|
+
}
|
|
18656
|
+
},
|
|
18566
18657
|
remoteFeatures: this.connected?.features ?? remoteHostFeatures(),
|
|
18567
18658
|
...this.pendingWorkspaceSelection === void 0 ? {} : { workspaceSelection: { ...this.pendingWorkspaceSelection } },
|
|
18568
18659
|
backend: this.codexVirtual === void 0 ? "harness" : "codex",
|
|
@@ -18631,6 +18722,7 @@ var ClientModeRuntime = class {
|
|
|
18631
18722
|
async clearClientAuthorization() {
|
|
18632
18723
|
const previous = this.connected;
|
|
18633
18724
|
this.connected = void 0;
|
|
18725
|
+
this.connectionProgress = void 0;
|
|
18634
18726
|
this.pendingWorkspaceSelection = void 0;
|
|
18635
18727
|
await this.closeCodexVirtual();
|
|
18636
18728
|
this.proxySwitch?.selectLocal();
|
|
@@ -18658,6 +18750,7 @@ var ClientModeRuntime = class {
|
|
|
18658
18750
|
this.gatewaySwitch.selectLocal();
|
|
18659
18751
|
const previous2 = this.connected;
|
|
18660
18752
|
this.connected = void 0;
|
|
18753
|
+
this.connectionProgress = void 0;
|
|
18661
18754
|
this.pendingWorkspaceSelection = void 0;
|
|
18662
18755
|
await this.closeCodexStreams(previous2?.client);
|
|
18663
18756
|
await previous2?.client.close().catch(() => void 0);
|
|
@@ -18671,11 +18764,13 @@ var ClientModeRuntime = class {
|
|
|
18671
18764
|
try {
|
|
18672
18765
|
this.assertRemoteCompatible(next);
|
|
18673
18766
|
} catch (error) {
|
|
18767
|
+
this.clearConnectionProgress(next.progressRunId);
|
|
18674
18768
|
await next.client.close().catch(() => void 0);
|
|
18675
18769
|
throw error;
|
|
18676
18770
|
}
|
|
18677
18771
|
const previous = this.connected;
|
|
18678
18772
|
this.connected = next;
|
|
18773
|
+
this.clearConnectionProgress(next.progressRunId);
|
|
18679
18774
|
this.pendingWorkspaceSelection = void 0;
|
|
18680
18775
|
await this.closeCodexVirtual();
|
|
18681
18776
|
this.selectRemoteTarget(next);
|
|
@@ -18790,12 +18885,12 @@ var ClientModeRuntime = class {
|
|
|
18790
18885
|
throw new ClientModeError("FEATURE_NOT_SUPPORTED", "The selected Host does not provide CodeX workspaces.");
|
|
18791
18886
|
}
|
|
18792
18887
|
this.assertRemoteCompatible(remote);
|
|
18793
|
-
const result =
|
|
18888
|
+
const result = record3(await new CodexRemoteClient(remote.client).request("project/create", {
|
|
18794
18889
|
name: remoteWorkspaceTitle(trimmedPath),
|
|
18795
18890
|
roots: [{ path: trimmedPath }],
|
|
18796
18891
|
idempotencyKey: uuidV7()
|
|
18797
18892
|
}, signal));
|
|
18798
|
-
const project =
|
|
18893
|
+
const project = record3(result.project);
|
|
18799
18894
|
if (typeof project.id !== "string" || project.id.length === 0) {
|
|
18800
18895
|
throw new ClientModeError("INVALID_MESSAGE", "The Host returned an invalid CodeX project.");
|
|
18801
18896
|
}
|
|
@@ -18818,6 +18913,7 @@ var ClientModeRuntime = class {
|
|
|
18818
18913
|
await this.closeCodexStreams(this.connected?.client);
|
|
18819
18914
|
await this.connected?.client.close().catch(() => void 0);
|
|
18820
18915
|
this.connected = void 0;
|
|
18916
|
+
this.connectionProgress = void 0;
|
|
18821
18917
|
this.proxySwitch?.restore();
|
|
18822
18918
|
this.gatewaySwitch.restore();
|
|
18823
18919
|
}
|
|
@@ -18844,7 +18940,7 @@ var ClientModeRuntime = class {
|
|
|
18844
18940
|
}
|
|
18845
18941
|
async openCodexStream(payload, signal) {
|
|
18846
18942
|
const remote = this.activeCodexRemote();
|
|
18847
|
-
const value =
|
|
18943
|
+
const value = record3(payload);
|
|
18848
18944
|
if (typeof value.streamId !== "string" || value.streamId.length === 0 || value.streamId.length > 128 || typeof value.threadId !== "string" || value.threadId.length === 0) {
|
|
18849
18945
|
throw new ClientModeError("INVALID_MESSAGE", "A Codex stream and thread are required.");
|
|
18850
18946
|
}
|
|
@@ -18929,7 +19025,7 @@ var ClientModeRuntime = class {
|
|
|
18929
19025
|
};
|
|
18930
19026
|
}
|
|
18931
19027
|
async nextCodexFrames(payload, signal) {
|
|
18932
|
-
const value =
|
|
19028
|
+
const value = record3(payload);
|
|
18933
19029
|
if (typeof value.streamId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Codex stream is required.");
|
|
18934
19030
|
const stream = this.codexStreams.get(value.streamId);
|
|
18935
19031
|
if (stream === void 0) throw new ClientModeError("STREAM_NOT_FOUND", "The Codex stream is not open.");
|
|
@@ -18943,7 +19039,7 @@ var ClientModeRuntime = class {
|
|
|
18943
19039
|
};
|
|
18944
19040
|
}
|
|
18945
19041
|
async closeCodexStream(payload) {
|
|
18946
|
-
const value =
|
|
19042
|
+
const value = record3(payload);
|
|
18947
19043
|
if (typeof value.streamId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Codex stream is required.");
|
|
18948
19044
|
const stream = this.codexStreams.get(value.streamId);
|
|
18949
19045
|
if (stream === void 0) return { closed: false, streamId: value.streamId };
|
|
@@ -18999,61 +19095,70 @@ var ClientModeRuntime = class {
|
|
|
18999
19095
|
}
|
|
19000
19096
|
async connect(targetDeviceId, signal) {
|
|
19001
19097
|
signal?.throwIfAborted();
|
|
19098
|
+
const progressRunId = this.connectionProgressRun + 1;
|
|
19099
|
+
this.connectionProgressRun = progressRunId;
|
|
19100
|
+
this.connectionProgress = { runId: progressRunId, targetDeviceId, phase: "checking-host" };
|
|
19002
19101
|
const identity = this.requireIdentity();
|
|
19003
|
-
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
|
|
19007
|
-
|
|
19008
|
-
|
|
19009
|
-
|
|
19010
|
-
|
|
19011
|
-
|
|
19012
|
-
|
|
19013
|
-
this.
|
|
19014
|
-
|
|
19015
|
-
|
|
19016
|
-
|
|
19017
|
-
|
|
19018
|
-
|
|
19019
|
-
|
|
19020
|
-
|
|
19021
|
-
|
|
19022
|
-
|
|
19023
|
-
|
|
19024
|
-
|
|
19025
|
-
|
|
19026
|
-
|
|
19027
|
-
|
|
19028
|
-
|
|
19029
|
-
|
|
19030
|
-
|
|
19031
|
-
|
|
19032
|
-
|
|
19033
|
-
|
|
19034
|
-
|
|
19035
|
-
|
|
19036
|
-
});
|
|
19037
|
-
if (diagnostics !== void 0) {
|
|
19038
|
-
this.logger.debug("remote Harness WebRTC fallback diagnostics", {
|
|
19102
|
+
let client;
|
|
19103
|
+
try {
|
|
19104
|
+
const serverDevice = (await this.server.listDevices()).find((device) => device.deviceId === targetDeviceId);
|
|
19105
|
+
if (serverDevice === void 0) {
|
|
19106
|
+
throw new ClientModeError("MEMBERSHIP_REQUIRED", "The selected Host is not authorized for this account.");
|
|
19107
|
+
}
|
|
19108
|
+
this.updateConnectionProgress(progressRunId, "authorizing-peer");
|
|
19109
|
+
const target = await this.authorizeHostPeer(serverDevice);
|
|
19110
|
+
const presence = await this.server.presenceFor(targetDeviceId);
|
|
19111
|
+
if (!presence.online) throw new ClientModeError("HOST_OFFLINE", "The selected Host is offline.", true);
|
|
19112
|
+
const credentials = await this.server.authenticate(identity);
|
|
19113
|
+
const rtcFactory = this.config.forceRelay ? void 0 : await this.rtcFactoryProvider({ routeTargets: [this.server.baseUrl] }).catch(() => void 0);
|
|
19114
|
+
if (!this.config.forceRelay && rtcFactory === void 0) {
|
|
19115
|
+
this.logger.warn("remote Harness WebRTC backend unavailable; using relay", {
|
|
19116
|
+
targetDeviceId: shortId(target.deviceId)
|
|
19117
|
+
});
|
|
19118
|
+
}
|
|
19119
|
+
let webRtcFallback = false;
|
|
19120
|
+
const createTransport = (attempt) => new AdaptiveTransport(
|
|
19121
|
+
websocketUrl(this.server.baseUrl),
|
|
19122
|
+
{
|
|
19123
|
+
role: "client",
|
|
19124
|
+
deviceId: identity.deviceId,
|
|
19125
|
+
accessToken: credentials.accessToken,
|
|
19126
|
+
targetDeviceId,
|
|
19127
|
+
forceRelay: this.config.forceRelay || attempt === "relay",
|
|
19128
|
+
preferredTransports: preferredTransportsForAttempt(attempt),
|
|
19129
|
+
negotiateTimeoutMs: attempt === "direct" ? DIRECT_WEBRTC_NEGOTIATE_TIMEOUT_MS : void 0,
|
|
19130
|
+
...rtcFactory === void 0 || attempt === "relay" ? {} : { rtcFactory },
|
|
19131
|
+
fetchIceServers: async (connectionId) => iceServersForAttempt(attempt, await this.server.turnCredentials(connectionId)),
|
|
19132
|
+
onWebRtcFallback: (error, diagnostics) => {
|
|
19133
|
+
webRtcFallback = true;
|
|
19134
|
+
this.logger.warn(attempt === "direct" ? "remote Harness direct WebRTC failed; trying TURN" : "remote Harness TURN WebRTC failed; using relay", {
|
|
19039
19135
|
targetDeviceId: shortId(target.deviceId),
|
|
19040
19136
|
attempt,
|
|
19041
|
-
|
|
19137
|
+
reason: diagnosticReason(error)
|
|
19042
19138
|
});
|
|
19139
|
+
if (diagnostics !== void 0) {
|
|
19140
|
+
this.logger.debug("remote Harness WebRTC fallback diagnostics", {
|
|
19141
|
+
targetDeviceId: shortId(target.deviceId),
|
|
19142
|
+
attempt,
|
|
19143
|
+
...webrtcDiagnosticsLogFields(diagnostics)
|
|
19144
|
+
});
|
|
19145
|
+
}
|
|
19043
19146
|
}
|
|
19044
19147
|
}
|
|
19045
|
-
|
|
19046
|
-
|
|
19047
|
-
|
|
19048
|
-
let transport;
|
|
19049
|
-
let client;
|
|
19050
|
-
try {
|
|
19148
|
+
);
|
|
19149
|
+
const attempts = this.config.forceRelay || rtcFactory === void 0 ? ["relay"] : ["direct", "turn", "relay"];
|
|
19150
|
+
let transport;
|
|
19051
19151
|
for (const attempt of attempts) {
|
|
19052
19152
|
webRtcFallback = false;
|
|
19053
|
-
|
|
19054
|
-
|
|
19055
|
-
|
|
19056
|
-
|
|
19153
|
+
const stopProgressTimer = this.beginAttemptProgress(progressRunId, attempt);
|
|
19154
|
+
try {
|
|
19155
|
+
transport = createTransport(attempt);
|
|
19156
|
+
client = new RemoteClientCore(new ClientSecureTransport(transport, identity, target), 6e4);
|
|
19157
|
+
await client.connect();
|
|
19158
|
+
signal?.throwIfAborted();
|
|
19159
|
+
} finally {
|
|
19160
|
+
stopProgressTimer();
|
|
19161
|
+
}
|
|
19057
19162
|
if (attempt === "relay" || !webRtcFallback) break;
|
|
19058
19163
|
await client.close();
|
|
19059
19164
|
client = void 0;
|
|
@@ -19069,9 +19174,16 @@ var ClientModeRuntime = class {
|
|
|
19069
19174
|
}
|
|
19070
19175
|
const connectedClient = client;
|
|
19071
19176
|
const connectedTransport = transport;
|
|
19177
|
+
const connectedPreference = transportPreferenceForMode(connectedClient.getStats().mode);
|
|
19178
|
+
this.updateConnectionProgress(
|
|
19179
|
+
progressRunId,
|
|
19180
|
+
"connected",
|
|
19181
|
+
connectedPreference === void 0 ? void 0 : [connectedPreference]
|
|
19182
|
+
);
|
|
19072
19183
|
connectedClient.onClose(() => {
|
|
19073
19184
|
if (this.connected?.client !== connectedClient) return;
|
|
19074
19185
|
this.connected = void 0;
|
|
19186
|
+
this.connectionProgress = void 0;
|
|
19075
19187
|
this.pendingWorkspaceSelection = void 0;
|
|
19076
19188
|
void this.closeCodexVirtual();
|
|
19077
19189
|
this.proxySwitch?.selectLocal();
|
|
@@ -19103,9 +19215,11 @@ var ClientModeRuntime = class {
|
|
|
19103
19215
|
target,
|
|
19104
19216
|
transport: connectedTransport,
|
|
19105
19217
|
features,
|
|
19218
|
+
progressRunId,
|
|
19106
19219
|
...serverDevice.clientVersion === void 0 ? {} : { clientVersion: serverDevice.clientVersion }
|
|
19107
19220
|
};
|
|
19108
19221
|
} catch (error) {
|
|
19222
|
+
this.clearConnectionProgress(progressRunId);
|
|
19109
19223
|
await client?.close().catch(() => void 0);
|
|
19110
19224
|
throw error;
|
|
19111
19225
|
}
|
|
@@ -19115,22 +19229,48 @@ var ClientModeRuntime = class {
|
|
|
19115
19229
|
const next = await this.connect(targetDeviceId, signal);
|
|
19116
19230
|
const previous = this.connected;
|
|
19117
19231
|
this.connected = next;
|
|
19232
|
+
this.clearConnectionProgress(next.progressRunId);
|
|
19118
19233
|
await previous?.client.close().catch(() => void 0);
|
|
19119
19234
|
return next;
|
|
19120
19235
|
}
|
|
19236
|
+
beginAttemptProgress(runId, attempt) {
|
|
19237
|
+
if (attempt !== "direct") {
|
|
19238
|
+
this.updateConnectionProgress(runId, "probing", [attempt]);
|
|
19239
|
+
return () => void 0;
|
|
19240
|
+
}
|
|
19241
|
+
this.updateConnectionProgress(runId, "probing", ["lan"]);
|
|
19242
|
+
const timer = setTimeout(() => {
|
|
19243
|
+
if (this.connectionProgress?.runId === runId && this.connectionProgress.phase === "probing") {
|
|
19244
|
+
this.updateConnectionProgress(runId, "probing", ["p2p"]);
|
|
19245
|
+
}
|
|
19246
|
+
}, DIRECT_LAN_PROGRESS_DISPLAY_MS);
|
|
19247
|
+
return () => clearTimeout(timer);
|
|
19248
|
+
}
|
|
19249
|
+
updateConnectionProgress(runId, phase, activeTransports) {
|
|
19250
|
+
if (this.connectionProgress?.runId !== runId) return;
|
|
19251
|
+
this.connectionProgress = {
|
|
19252
|
+
runId,
|
|
19253
|
+
targetDeviceId: this.connectionProgress.targetDeviceId,
|
|
19254
|
+
phase,
|
|
19255
|
+
...activeTransports === void 0 ? {} : { activeTransports }
|
|
19256
|
+
};
|
|
19257
|
+
}
|
|
19258
|
+
clearConnectionProgress(runId) {
|
|
19259
|
+
if (this.connectionProgress?.runId === runId) this.connectionProgress = void 0;
|
|
19260
|
+
}
|
|
19121
19261
|
async handleControl(endpoint, payload, signal) {
|
|
19122
19262
|
try {
|
|
19123
19263
|
if (endpoint === "status") return ok2(await this.detailedStatus());
|
|
19124
19264
|
if (endpoint === "devices") return ok2(await this.devices());
|
|
19125
19265
|
if (endpoint === "client.account.login") {
|
|
19126
|
-
const value =
|
|
19266
|
+
const value = record3(payload);
|
|
19127
19267
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
19128
19268
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
19129
19269
|
}
|
|
19130
19270
|
return ok2(await this.authorizeClientWithAccount(value.email, value.password));
|
|
19131
19271
|
}
|
|
19132
19272
|
if (endpoint === "client.account.qr.start") {
|
|
19133
|
-
const value =
|
|
19273
|
+
const value = record3(payload);
|
|
19134
19274
|
const provider = value.provider ?? "zhihu";
|
|
19135
19275
|
if (provider !== "zhihu" && provider !== "github") {
|
|
19136
19276
|
throw new ClientModeError("INVALID_MESSAGE", "A supported OAuth provider is required.");
|
|
@@ -19138,14 +19278,14 @@ var ClientModeRuntime = class {
|
|
|
19138
19278
|
return ok2(await this.startClientOAuthQrLogin(provider));
|
|
19139
19279
|
}
|
|
19140
19280
|
if (endpoint === "client.account.qr.poll") {
|
|
19141
|
-
const value =
|
|
19281
|
+
const value = record3(payload);
|
|
19142
19282
|
if (typeof value.qrId !== "string" || value.qrId.length < 20) {
|
|
19143
19283
|
throw new ClientModeError("INVALID_MESSAGE", "A QR login session is required.");
|
|
19144
19284
|
}
|
|
19145
19285
|
return ok2(await this.pollClientOAuthQrLogin(value.qrId));
|
|
19146
19286
|
}
|
|
19147
19287
|
if (endpoint === "directory.list") {
|
|
19148
|
-
const value =
|
|
19288
|
+
const value = record3(payload);
|
|
19149
19289
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
19150
19290
|
return ok2(await this.listRemoteDirectory(
|
|
19151
19291
|
value.targetDeviceId,
|
|
@@ -19154,38 +19294,38 @@ var ClientModeRuntime = class {
|
|
|
19154
19294
|
));
|
|
19155
19295
|
}
|
|
19156
19296
|
if (endpoint === "workspaces.list") {
|
|
19157
|
-
const value =
|
|
19297
|
+
const value = record3(payload);
|
|
19158
19298
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
19159
19299
|
return ok2(await this.listRemoteWorkspaces(value.targetDeviceId, signal));
|
|
19160
19300
|
}
|
|
19161
19301
|
if (endpoint === "codex.workspaces.list") {
|
|
19162
|
-
const value =
|
|
19302
|
+
const value = record3(payload);
|
|
19163
19303
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
19164
19304
|
return ok2(await this.listCodexWorkspaces(value.targetDeviceId, signal));
|
|
19165
19305
|
}
|
|
19166
19306
|
if (endpoint === "workspace.open") {
|
|
19167
|
-
const value =
|
|
19307
|
+
const value = record3(payload);
|
|
19168
19308
|
if (typeof value.targetDeviceId !== "string" || typeof value.path !== "string") {
|
|
19169
19309
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and working directory are required.");
|
|
19170
19310
|
}
|
|
19171
19311
|
return ok2(await this.openRemoteWorkspace(value.targetDeviceId, value.path, signal));
|
|
19172
19312
|
}
|
|
19173
19313
|
if (endpoint === "codex.workspace.open") {
|
|
19174
|
-
const value =
|
|
19314
|
+
const value = record3(payload);
|
|
19175
19315
|
if (typeof value.targetDeviceId !== "string" || typeof value.workspaceId !== "string") {
|
|
19176
19316
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and CodeX Workspace are required.");
|
|
19177
19317
|
}
|
|
19178
19318
|
return ok2(await this.openCodexWorkspace(value.targetDeviceId, value.workspaceId, signal));
|
|
19179
19319
|
}
|
|
19180
19320
|
if (endpoint === "codex.workspace.create") {
|
|
19181
|
-
const value =
|
|
19321
|
+
const value = record3(payload);
|
|
19182
19322
|
if (typeof value.targetDeviceId !== "string" || typeof value.path !== "string") {
|
|
19183
19323
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and CodeX project directory are required.");
|
|
19184
19324
|
}
|
|
19185
19325
|
return ok2(await this.createCodexWorkspace(value.targetDeviceId, value.path, signal));
|
|
19186
19326
|
}
|
|
19187
19327
|
if (endpoint === "workspace.selection.consume") {
|
|
19188
|
-
const value =
|
|
19328
|
+
const value = record3(payload);
|
|
19189
19329
|
if (typeof value.targetDeviceId !== "string" || typeof value.workspaceId !== "string") {
|
|
19190
19330
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and Workspace are required.");
|
|
19191
19331
|
}
|
|
@@ -19201,7 +19341,7 @@ var ClientModeRuntime = class {
|
|
|
19201
19341
|
return ok2(await this.callRemoteFileViewer(method, payload, signal));
|
|
19202
19342
|
}
|
|
19203
19343
|
if (endpoint === "codex.call") {
|
|
19204
|
-
const value =
|
|
19344
|
+
const value = record3(payload);
|
|
19205
19345
|
if (typeof value.method !== "string" || !("params" in value)) {
|
|
19206
19346
|
throw new ClientModeError("INVALID_MESSAGE", "A Codex method and params are required.");
|
|
19207
19347
|
}
|
|
@@ -19225,7 +19365,7 @@ var ClientModeRuntime = class {
|
|
|
19225
19365
|
return ok2({ supported: local || remoteSupported, local, remote: remoteSupported });
|
|
19226
19366
|
}
|
|
19227
19367
|
if (endpoint === "codex.respond") {
|
|
19228
|
-
const value =
|
|
19368
|
+
const value = record3(payload);
|
|
19229
19369
|
const remote = this.activeCodexRemote();
|
|
19230
19370
|
if (remote !== void 0) return ok2(await remote.client.rpc("codex.app.respond", value, signal));
|
|
19231
19371
|
const host = this.requireLocalCodex();
|
|
@@ -19236,14 +19376,14 @@ var ClientModeRuntime = class {
|
|
|
19236
19376
|
if (endpoint === "codex.stream.close") return ok2(await this.closeCodexStream(payload));
|
|
19237
19377
|
if (endpoint === "host.account.login") {
|
|
19238
19378
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19239
|
-
const value =
|
|
19379
|
+
const value = record3(payload);
|
|
19240
19380
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
19241
19381
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
19242
19382
|
}
|
|
19243
19383
|
return ok2(await this.host.authorizeHostWithAccount(value.email, value.password));
|
|
19244
19384
|
}
|
|
19245
19385
|
if (endpoint === "host.authorization.set") {
|
|
19246
|
-
const value =
|
|
19386
|
+
const value = record3(payload);
|
|
19247
19387
|
if (typeof value.enabled !== "boolean") {
|
|
19248
19388
|
throw new ClientModeError("INVALID_MESSAGE", "Host authorization state is required.");
|
|
19249
19389
|
}
|
|
@@ -19251,14 +19391,14 @@ var ClientModeRuntime = class {
|
|
|
19251
19391
|
}
|
|
19252
19392
|
if (endpoint === "host.registration-code.submit") {
|
|
19253
19393
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19254
|
-
const value =
|
|
19394
|
+
const value = record3(payload);
|
|
19255
19395
|
if (typeof value.code !== "string" || value.code.trim() === "") {
|
|
19256
19396
|
throw new ClientModeError("INVALID_MESSAGE", "A Host registration code is required.");
|
|
19257
19397
|
}
|
|
19258
19398
|
return ok2(await this.host.authorizeHostWithCode(value.code));
|
|
19259
19399
|
}
|
|
19260
19400
|
if (endpoint === "mode.set") {
|
|
19261
|
-
const value =
|
|
19401
|
+
const value = record3(payload);
|
|
19262
19402
|
if (value.mode !== "local" && value.mode !== "remote") throw new ClientModeError("INVALID_MESSAGE", "Mode must be local or remote.");
|
|
19263
19403
|
return ok2(await this.setMode(value.mode, typeof value.targetDeviceId === "string" ? value.targetDeviceId : void 0, signal));
|
|
19264
19404
|
}
|
|
@@ -19322,7 +19462,7 @@ function webrtcDiagnosticsLogFields(diagnostics) {
|
|
|
19322
19462
|
...diagnostics.selectedPath === void 0 ? {} : { rtcSelectedPath: diagnostics.selectedPath }
|
|
19323
19463
|
};
|
|
19324
19464
|
}
|
|
19325
|
-
function
|
|
19465
|
+
function record3(value) {
|
|
19326
19466
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
19327
19467
|
throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
|
|
19328
19468
|
}
|
|
@@ -19486,6 +19626,13 @@ function preferredTransportsForAttempt(attempt) {
|
|
|
19486
19626
|
if (attempt === "turn") return ["turn", "relay"];
|
|
19487
19627
|
return ["relay"];
|
|
19488
19628
|
}
|
|
19629
|
+
function transportPreferenceForMode(mode) {
|
|
19630
|
+
if (mode === "LAN") return "lan";
|
|
19631
|
+
if (mode === "P2P") return "p2p";
|
|
19632
|
+
if (mode === "TURN") return "turn";
|
|
19633
|
+
if (mode === "Relay") return "relay";
|
|
19634
|
+
return void 0;
|
|
19635
|
+
}
|
|
19489
19636
|
function iceServersForAttempt(attempt, iceServers) {
|
|
19490
19637
|
return attempt === "direct" ? stunOnlyIceServers(iceServers) : iceServers;
|
|
19491
19638
|
}
|
|
@@ -19540,24 +19687,24 @@ var IdentityStore = class {
|
|
|
19540
19687
|
}
|
|
19541
19688
|
if (!hasDevice) {
|
|
19542
19689
|
const keys = generateKeyPair();
|
|
19543
|
-
const
|
|
19544
|
-
await atomicJsonWrite(devicePath,
|
|
19690
|
+
const record6 = { schemaVersion: 1, deviceId: uuidV7(), name: deviceName, publicKey: keys.publicKey };
|
|
19691
|
+
await atomicJsonWrite(devicePath, record6, 384);
|
|
19545
19692
|
await atomicTextWrite(keyPath, `${keys.privateKey}
|
|
19546
19693
|
`, 384);
|
|
19547
19694
|
}
|
|
19548
19695
|
await assertPrivateMode(keyPath);
|
|
19549
19696
|
try {
|
|
19550
|
-
let
|
|
19697
|
+
let record6 = identitySchema.parse(JSON.parse(await readFile(devicePath, "utf8")));
|
|
19551
19698
|
const privateKey = (await readFile(keyPath, "utf8")).trim();
|
|
19552
19699
|
const regenerated = generateKeyPair(fromBase64Url2(privateKey));
|
|
19553
|
-
if (regenerated.publicKey !==
|
|
19700
|
+
if (regenerated.publicKey !== record6.publicKey) {
|
|
19554
19701
|
throw new IdentityInvalidError("device public and private keys do not match");
|
|
19555
19702
|
}
|
|
19556
|
-
if (
|
|
19557
|
-
|
|
19558
|
-
await atomicJsonWrite(devicePath,
|
|
19703
|
+
if (record6.name !== deviceName) {
|
|
19704
|
+
record6 = { ...record6, name: deviceName };
|
|
19705
|
+
await atomicJsonWrite(devicePath, record6, 384);
|
|
19559
19706
|
}
|
|
19560
|
-
this.identity = { ...
|
|
19707
|
+
this.identity = { ...record6, privateKey, fingerprint: fingerprint(record6.publicKey) };
|
|
19561
19708
|
await this.loadPeers();
|
|
19562
19709
|
return this.identity;
|
|
19563
19710
|
} catch (error) {
|
|
@@ -19699,10 +19846,10 @@ var ServerCredentialStore = class {
|
|
|
19699
19846
|
return parsed.serverUrl === serverUrl && parsed.deviceId === deviceId ? parsed : void 0;
|
|
19700
19847
|
}
|
|
19701
19848
|
async save(credentials) {
|
|
19702
|
-
const
|
|
19703
|
-
await atomicWrite(this.path, `${JSON.stringify(
|
|
19849
|
+
const record6 = credentialSchema.parse({ schemaVersion: 1, ...credentials });
|
|
19850
|
+
await atomicWrite(this.path, `${JSON.stringify(record6, null, 2)}
|
|
19704
19851
|
`);
|
|
19705
|
-
return
|
|
19852
|
+
return record6;
|
|
19706
19853
|
}
|
|
19707
19854
|
async clear() {
|
|
19708
19855
|
await rm2(this.path, { force: true });
|
|
@@ -19769,7 +19916,7 @@ var PluginControlRuntime = class {
|
|
|
19769
19916
|
if (endpoint === "devices") return ok3([]);
|
|
19770
19917
|
if (endpoint === "host.account.login") {
|
|
19771
19918
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19772
|
-
const value =
|
|
19919
|
+
const value = record4(payload);
|
|
19773
19920
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
19774
19921
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
19775
19922
|
}
|
|
@@ -19777,13 +19924,13 @@ var PluginControlRuntime = class {
|
|
|
19777
19924
|
}
|
|
19778
19925
|
if (endpoint === "host.registration-code.submit") {
|
|
19779
19926
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19780
|
-
const value =
|
|
19927
|
+
const value = record4(payload);
|
|
19781
19928
|
if (typeof value.code !== "string" || value.code.trim() === "") {
|
|
19782
19929
|
throw new ClientModeError("INVALID_MESSAGE", "A Host registration code is required.");
|
|
19783
19930
|
}
|
|
19784
19931
|
return ok3(await this.host.authorizeHostWithCode(value.code));
|
|
19785
19932
|
}
|
|
19786
|
-
if (endpoint === "mode.set" &&
|
|
19933
|
+
if (endpoint === "mode.set" && record4(payload).mode === "local") return ok3(this.hostOnlyStatus());
|
|
19787
19934
|
throw new ClientModeError("METHOD_NOT_ALLOWED", "Remote Client mode is disabled by the plugin role.");
|
|
19788
19935
|
} catch (error) {
|
|
19789
19936
|
return fail3(error);
|
|
@@ -19793,7 +19940,7 @@ var PluginControlRuntime = class {
|
|
|
19793
19940
|
if (this.settings === void 0) {
|
|
19794
19941
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19795
19942
|
}
|
|
19796
|
-
const value =
|
|
19943
|
+
const value = record4(payload);
|
|
19797
19944
|
if (value.role !== "host" && value.role !== "client") {
|
|
19798
19945
|
throw new ClientModeError("INVALID_MESSAGE", "Role must be Host or Client.");
|
|
19799
19946
|
}
|
|
@@ -19828,7 +19975,7 @@ var PluginControlRuntime = class {
|
|
|
19828
19975
|
if (this.settings === void 0) {
|
|
19829
19976
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19830
19977
|
}
|
|
19831
|
-
const value =
|
|
19978
|
+
const value = record4(payload);
|
|
19832
19979
|
if (typeof value.serverUrl !== "string") {
|
|
19833
19980
|
throw new ClientModeError("INVALID_MESSAGE", "Server URL is required.");
|
|
19834
19981
|
}
|
|
@@ -19841,7 +19988,7 @@ var PluginControlRuntime = class {
|
|
|
19841
19988
|
if (this.settings === void 0) {
|
|
19842
19989
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19843
19990
|
}
|
|
19844
|
-
const role =
|
|
19991
|
+
const role = record4(payload).role;
|
|
19845
19992
|
if (role !== "host" && role !== "client") {
|
|
19846
19993
|
throw new ClientModeError("INVALID_MESSAGE", "Role must be Host or Client.");
|
|
19847
19994
|
}
|
|
@@ -19857,7 +20004,7 @@ var PluginControlRuntime = class {
|
|
|
19857
20004
|
if (this.settings === void 0) {
|
|
19858
20005
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19859
20006
|
}
|
|
19860
|
-
const enabled =
|
|
20007
|
+
const enabled = record4(payload).enabled;
|
|
19861
20008
|
if (typeof enabled !== "boolean") {
|
|
19862
20009
|
throw new ClientModeError("INVALID_MESSAGE", "Codex Remote enabled must be a boolean.");
|
|
19863
20010
|
}
|
|
@@ -19966,7 +20113,7 @@ function editableConfig(config) {
|
|
|
19966
20113
|
function isRecord6(value) {
|
|
19967
20114
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19968
20115
|
}
|
|
19969
|
-
function
|
|
20116
|
+
function record4(value) {
|
|
19970
20117
|
if (!isRecord6(value)) throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
|
|
19971
20118
|
return value;
|
|
19972
20119
|
}
|
|
@@ -22573,11 +22720,11 @@ function needsDirectoryFallback(result) {
|
|
|
22573
22720
|
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");
|
|
22574
22721
|
}
|
|
22575
22722
|
function requestArgs(payload) {
|
|
22576
|
-
const root =
|
|
22723
|
+
const root = record5(payload);
|
|
22577
22724
|
const args = isRecord7(root.args) ? root.args : root;
|
|
22578
|
-
return
|
|
22725
|
+
return record5(args.request ?? args._request ?? args);
|
|
22579
22726
|
}
|
|
22580
|
-
function
|
|
22727
|
+
function record5(value) {
|
|
22581
22728
|
return isRecord7(value) ? value : {};
|
|
22582
22729
|
}
|
|
22583
22730
|
function isRecord7(value) {
|
|
@@ -23236,6 +23383,7 @@ var CodexRemoteDomain = class {
|
|
|
23236
23383
|
peerDeviceIds = /* @__PURE__ */ new Map();
|
|
23237
23384
|
turnOwners = /* @__PURE__ */ new Map();
|
|
23238
23385
|
approvals = /* @__PURE__ */ new Map();
|
|
23386
|
+
permissionPresets = /* @__PURE__ */ new Map();
|
|
23239
23387
|
approvalExpiryTimer;
|
|
23240
23388
|
restartTimer;
|
|
23241
23389
|
restartAttempt = 0;
|
|
@@ -23314,6 +23462,7 @@ var CodexRemoteDomain = class {
|
|
|
23314
23462
|
if (extractThread(result)?.id === void 0) {
|
|
23315
23463
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid thread.");
|
|
23316
23464
|
}
|
|
23465
|
+
this.rememberPermission(extractThread(result).id, result);
|
|
23317
23466
|
return result;
|
|
23318
23467
|
}
|
|
23319
23468
|
const threadId = threadIdFromParams(call.params);
|
|
@@ -23328,12 +23477,23 @@ var CodexRemoteDomain = class {
|
|
|
23328
23477
|
}
|
|
23329
23478
|
);
|
|
23330
23479
|
const activeTurnId2 = typeof page.activeTurnId === "string" ? page.activeTurnId : this.turnOwners.get(threadId)?.turnId;
|
|
23331
|
-
return
|
|
23480
|
+
return {
|
|
23481
|
+
...page,
|
|
23482
|
+
...activeTurnId2 === void 0 ? {} : { activeTurnId: activeTurnId2 },
|
|
23483
|
+
permissionPreset: this.permissionPresets.get(threadId) ?? null
|
|
23484
|
+
};
|
|
23332
23485
|
}
|
|
23333
23486
|
if (call.method === "dsh/directoryList") {
|
|
23334
23487
|
return this.listCodexDirectory(call.params.path);
|
|
23335
23488
|
}
|
|
23336
23489
|
const allowedThread = threadId === void 0 ? void 0 : await this.readKnownThread(threadId);
|
|
23490
|
+
if (call.method === "thread/resume" && call.params.permissionPreset !== void 0) {
|
|
23491
|
+
const owner = this.turnOwners.get(threadId);
|
|
23492
|
+
if (owner !== void 0 && owner.connectionId !== connectionId) {
|
|
23493
|
+
throw new RpcError("CODEX_THREAD_BUSY", "Another Remote client is writing to this CodeX thread.");
|
|
23494
|
+
}
|
|
23495
|
+
return this.changeThreadPermission(threadId, call.params, allowedThread);
|
|
23496
|
+
}
|
|
23337
23497
|
if (call.method === "thread/read") {
|
|
23338
23498
|
return this.callUpstream(call.method, call.params);
|
|
23339
23499
|
}
|
|
@@ -23383,8 +23543,18 @@ var CodexRemoteDomain = class {
|
|
|
23383
23543
|
if (call.method === "thread/resume" || call.method === "thread/fork" || call.method === "thread/unarchive") {
|
|
23384
23544
|
await this.assertResultThreadAllowed(result);
|
|
23385
23545
|
}
|
|
23546
|
+
if (call.method === "thread/resume" || call.method === "thread/fork") {
|
|
23547
|
+
const resultId = extractThread(result)?.id;
|
|
23548
|
+
if (typeof resultId === "string") {
|
|
23549
|
+
this.rememberPermission(resultId, result);
|
|
23550
|
+
if (call.params.permissionPreset !== void 0) await this.publishPermission(resultId, result);
|
|
23551
|
+
}
|
|
23552
|
+
}
|
|
23386
23553
|
if (call.method === "turn/start" && threadId !== void 0) {
|
|
23387
23554
|
this.rememberTurnId(threadId, connectionId, extractTurnId(result));
|
|
23555
|
+
if (call.params.permissionPreset !== void 0) {
|
|
23556
|
+
await this.publishPermission(threadId, codexTurnPermissionParams(permission, allowedThread?.cwd));
|
|
23557
|
+
}
|
|
23388
23558
|
}
|
|
23389
23559
|
return result;
|
|
23390
23560
|
} catch (error) {
|
|
@@ -23433,6 +23603,7 @@ var CodexRemoteDomain = class {
|
|
|
23433
23603
|
this.peers.clear();
|
|
23434
23604
|
this.peerDeviceIds.clear();
|
|
23435
23605
|
this.turnOwners.clear();
|
|
23606
|
+
this.permissionPresets.clear();
|
|
23436
23607
|
if (this.approvalExpiryTimer !== void 0) clearTimeout(this.approvalExpiryTimer);
|
|
23437
23608
|
this.approvalExpiryTimer = void 0;
|
|
23438
23609
|
this.approvals.clear();
|
|
@@ -23495,6 +23666,7 @@ var CodexRemoteDomain = class {
|
|
|
23495
23666
|
this.state = "restarting";
|
|
23496
23667
|
this.unavailableCode = code;
|
|
23497
23668
|
this.turnOwners.clear();
|
|
23669
|
+
this.permissionPresets.clear();
|
|
23498
23670
|
this.approvals.clear();
|
|
23499
23671
|
if (this.approvalExpiryTimer !== void 0) clearTimeout(this.approvalExpiryTimer);
|
|
23500
23672
|
this.approvalExpiryTimer = void 0;
|
|
@@ -23550,6 +23722,10 @@ var CodexRemoteDomain = class {
|
|
|
23550
23722
|
return;
|
|
23551
23723
|
}
|
|
23552
23724
|
const threadId = extractThreadId(message.params);
|
|
23725
|
+
if (message.method === "thread/settings/updated" && threadId !== void 0) {
|
|
23726
|
+
this.rememberPermission(threadId, message.params);
|
|
23727
|
+
}
|
|
23728
|
+
if (message.method === "thread/closed" && threadId !== void 0) this.permissionPresets.delete(threadId);
|
|
23553
23729
|
if (message.method === "turn/completed" && threadId !== void 0) this.turnOwners.delete(threadId);
|
|
23554
23730
|
if (message.method === "turn/started" && threadId !== void 0) {
|
|
23555
23731
|
const owner = this.turnOwners.get(threadId);
|
|
@@ -23565,6 +23741,42 @@ var CodexRemoteDomain = class {
|
|
|
23565
23741
|
params: message.params
|
|
23566
23742
|
})));
|
|
23567
23743
|
}
|
|
23744
|
+
rememberPermission(threadId, value) {
|
|
23745
|
+
const preset = codexPermissionPresetFromResponse(value);
|
|
23746
|
+
if (preset === void 0) this.permissionPresets.delete(threadId);
|
|
23747
|
+
else this.permissionPresets.set(threadId, preset);
|
|
23748
|
+
}
|
|
23749
|
+
async changeThreadPermission(threadId, params, allowed) {
|
|
23750
|
+
const permission = codexPermission(params);
|
|
23751
|
+
const settings = {
|
|
23752
|
+
...codexTurnPermissionParams(permission, allowed.cwd),
|
|
23753
|
+
...params.model === void 0 ? {} : { model: params.model }
|
|
23754
|
+
};
|
|
23755
|
+
let result;
|
|
23756
|
+
try {
|
|
23757
|
+
await this.callUpstream("thread/settings/update", { threadId, ...settings });
|
|
23758
|
+
result = { thread: allowed.thread, ...settings, sandbox: settings.sandboxPolicy };
|
|
23759
|
+
} catch {
|
|
23760
|
+
result = await this.callUpstream("thread/resume", {
|
|
23761
|
+
...permission.params,
|
|
23762
|
+
...allowed.cwd === void 0 ? {} : { cwd: allowed.cwd },
|
|
23763
|
+
...codexThreadPermissionParams(permission),
|
|
23764
|
+
excludeTurns: true
|
|
23765
|
+
});
|
|
23766
|
+
await this.assertResultThreadAllowed(result);
|
|
23767
|
+
if (codexPermissionPresetFromResponse(result) !== params.permissionPreset) {
|
|
23768
|
+
await this.callUpstream("thread/settings/update", { threadId, ...settings });
|
|
23769
|
+
result = { ...isRecord10(result) ? result : {}, ...settings, sandbox: settings.sandboxPolicy };
|
|
23770
|
+
}
|
|
23771
|
+
}
|
|
23772
|
+
await this.publishPermission(threadId, result);
|
|
23773
|
+
return result;
|
|
23774
|
+
}
|
|
23775
|
+
async publishPermission(threadId, value) {
|
|
23776
|
+
const source = isRecord10(value) ? value : {};
|
|
23777
|
+
const threadSettings = { approvalPolicy: source.approvalPolicy, sandboxPolicy: source.sandboxPolicy ?? source.sandbox };
|
|
23778
|
+
await this.handleInbound({ kind: "notification", method: "thread/settings/updated", params: { threadId, threadSettings } });
|
|
23779
|
+
}
|
|
23568
23780
|
async handleServerRequest(message) {
|
|
23569
23781
|
const appServer = this.requireAppServer();
|
|
23570
23782
|
await this.expireApprovals();
|
|
@@ -24025,7 +24237,7 @@ function filterThreadListByWorkspaceAuthority(result, authority) {
|
|
|
24025
24237
|
}
|
|
24026
24238
|
return {
|
|
24027
24239
|
...result,
|
|
24028
|
-
data: result.data.map((
|
|
24240
|
+
data: result.data.map((record6) => isRecord10(record6) ? record6 : void 0).filter((thread) => thread !== void 0 && isThreadAllowedByWorkspaceAuthority(thread, authority))
|
|
24029
24241
|
};
|
|
24030
24242
|
}
|
|
24031
24243
|
function sanitizeProject(value) {
|