ds-harness-remote 0.4.9 → 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 +3 -3
- package/dist/client-runtime.d.ts +1 -0
- package/dist/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +27 -10
- package/dist/client-runtime.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 +319 -160
- 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 +1 -1
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;
|
|
@@ -18804,12 +18885,12 @@ var ClientModeRuntime = class {
|
|
|
18804
18885
|
throw new ClientModeError("FEATURE_NOT_SUPPORTED", "The selected Host does not provide CodeX workspaces.");
|
|
18805
18886
|
}
|
|
18806
18887
|
this.assertRemoteCompatible(remote);
|
|
18807
|
-
const result =
|
|
18888
|
+
const result = record3(await new CodexRemoteClient(remote.client).request("project/create", {
|
|
18808
18889
|
name: remoteWorkspaceTitle(trimmedPath),
|
|
18809
18890
|
roots: [{ path: trimmedPath }],
|
|
18810
18891
|
idempotencyKey: uuidV7()
|
|
18811
18892
|
}, signal));
|
|
18812
|
-
const project =
|
|
18893
|
+
const project = record3(result.project);
|
|
18813
18894
|
if (typeof project.id !== "string" || project.id.length === 0) {
|
|
18814
18895
|
throw new ClientModeError("INVALID_MESSAGE", "The Host returned an invalid CodeX project.");
|
|
18815
18896
|
}
|
|
@@ -18859,7 +18940,7 @@ var ClientModeRuntime = class {
|
|
|
18859
18940
|
}
|
|
18860
18941
|
async openCodexStream(payload, signal) {
|
|
18861
18942
|
const remote = this.activeCodexRemote();
|
|
18862
|
-
const value =
|
|
18943
|
+
const value = record3(payload);
|
|
18863
18944
|
if (typeof value.streamId !== "string" || value.streamId.length === 0 || value.streamId.length > 128 || typeof value.threadId !== "string" || value.threadId.length === 0) {
|
|
18864
18945
|
throw new ClientModeError("INVALID_MESSAGE", "A Codex stream and thread are required.");
|
|
18865
18946
|
}
|
|
@@ -18944,7 +19025,7 @@ var ClientModeRuntime = class {
|
|
|
18944
19025
|
};
|
|
18945
19026
|
}
|
|
18946
19027
|
async nextCodexFrames(payload, signal) {
|
|
18947
|
-
const value =
|
|
19028
|
+
const value = record3(payload);
|
|
18948
19029
|
if (typeof value.streamId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Codex stream is required.");
|
|
18949
19030
|
const stream = this.codexStreams.get(value.streamId);
|
|
18950
19031
|
if (stream === void 0) throw new ClientModeError("STREAM_NOT_FOUND", "The Codex stream is not open.");
|
|
@@ -18958,7 +19039,7 @@ var ClientModeRuntime = class {
|
|
|
18958
19039
|
};
|
|
18959
19040
|
}
|
|
18960
19041
|
async closeCodexStream(payload) {
|
|
18961
|
-
const value =
|
|
19042
|
+
const value = record3(payload);
|
|
18962
19043
|
if (typeof value.streamId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Codex stream is required.");
|
|
18963
19044
|
const stream = this.codexStreams.get(value.streamId);
|
|
18964
19045
|
if (stream === void 0) return { closed: false, streamId: value.streamId };
|
|
@@ -19069,11 +19150,15 @@ var ClientModeRuntime = class {
|
|
|
19069
19150
|
let transport;
|
|
19070
19151
|
for (const attempt of attempts) {
|
|
19071
19152
|
webRtcFallback = false;
|
|
19072
|
-
this.
|
|
19073
|
-
|
|
19074
|
-
|
|
19075
|
-
|
|
19076
|
-
|
|
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
|
+
}
|
|
19077
19162
|
if (attempt === "relay" || !webRtcFallback) break;
|
|
19078
19163
|
await client.close();
|
|
19079
19164
|
client = void 0;
|
|
@@ -19148,6 +19233,19 @@ var ClientModeRuntime = class {
|
|
|
19148
19233
|
await previous?.client.close().catch(() => void 0);
|
|
19149
19234
|
return next;
|
|
19150
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
|
+
}
|
|
19151
19249
|
updateConnectionProgress(runId, phase, activeTransports) {
|
|
19152
19250
|
if (this.connectionProgress?.runId !== runId) return;
|
|
19153
19251
|
this.connectionProgress = {
|
|
@@ -19165,14 +19263,14 @@ var ClientModeRuntime = class {
|
|
|
19165
19263
|
if (endpoint === "status") return ok2(await this.detailedStatus());
|
|
19166
19264
|
if (endpoint === "devices") return ok2(await this.devices());
|
|
19167
19265
|
if (endpoint === "client.account.login") {
|
|
19168
|
-
const value =
|
|
19266
|
+
const value = record3(payload);
|
|
19169
19267
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
19170
19268
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
19171
19269
|
}
|
|
19172
19270
|
return ok2(await this.authorizeClientWithAccount(value.email, value.password));
|
|
19173
19271
|
}
|
|
19174
19272
|
if (endpoint === "client.account.qr.start") {
|
|
19175
|
-
const value =
|
|
19273
|
+
const value = record3(payload);
|
|
19176
19274
|
const provider = value.provider ?? "zhihu";
|
|
19177
19275
|
if (provider !== "zhihu" && provider !== "github") {
|
|
19178
19276
|
throw new ClientModeError("INVALID_MESSAGE", "A supported OAuth provider is required.");
|
|
@@ -19180,14 +19278,14 @@ var ClientModeRuntime = class {
|
|
|
19180
19278
|
return ok2(await this.startClientOAuthQrLogin(provider));
|
|
19181
19279
|
}
|
|
19182
19280
|
if (endpoint === "client.account.qr.poll") {
|
|
19183
|
-
const value =
|
|
19281
|
+
const value = record3(payload);
|
|
19184
19282
|
if (typeof value.qrId !== "string" || value.qrId.length < 20) {
|
|
19185
19283
|
throw new ClientModeError("INVALID_MESSAGE", "A QR login session is required.");
|
|
19186
19284
|
}
|
|
19187
19285
|
return ok2(await this.pollClientOAuthQrLogin(value.qrId));
|
|
19188
19286
|
}
|
|
19189
19287
|
if (endpoint === "directory.list") {
|
|
19190
|
-
const value =
|
|
19288
|
+
const value = record3(payload);
|
|
19191
19289
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
19192
19290
|
return ok2(await this.listRemoteDirectory(
|
|
19193
19291
|
value.targetDeviceId,
|
|
@@ -19196,38 +19294,38 @@ var ClientModeRuntime = class {
|
|
|
19196
19294
|
));
|
|
19197
19295
|
}
|
|
19198
19296
|
if (endpoint === "workspaces.list") {
|
|
19199
|
-
const value =
|
|
19297
|
+
const value = record3(payload);
|
|
19200
19298
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
19201
19299
|
return ok2(await this.listRemoteWorkspaces(value.targetDeviceId, signal));
|
|
19202
19300
|
}
|
|
19203
19301
|
if (endpoint === "codex.workspaces.list") {
|
|
19204
|
-
const value =
|
|
19302
|
+
const value = record3(payload);
|
|
19205
19303
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
19206
19304
|
return ok2(await this.listCodexWorkspaces(value.targetDeviceId, signal));
|
|
19207
19305
|
}
|
|
19208
19306
|
if (endpoint === "workspace.open") {
|
|
19209
|
-
const value =
|
|
19307
|
+
const value = record3(payload);
|
|
19210
19308
|
if (typeof value.targetDeviceId !== "string" || typeof value.path !== "string") {
|
|
19211
19309
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and working directory are required.");
|
|
19212
19310
|
}
|
|
19213
19311
|
return ok2(await this.openRemoteWorkspace(value.targetDeviceId, value.path, signal));
|
|
19214
19312
|
}
|
|
19215
19313
|
if (endpoint === "codex.workspace.open") {
|
|
19216
|
-
const value =
|
|
19314
|
+
const value = record3(payload);
|
|
19217
19315
|
if (typeof value.targetDeviceId !== "string" || typeof value.workspaceId !== "string") {
|
|
19218
19316
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and CodeX Workspace are required.");
|
|
19219
19317
|
}
|
|
19220
19318
|
return ok2(await this.openCodexWorkspace(value.targetDeviceId, value.workspaceId, signal));
|
|
19221
19319
|
}
|
|
19222
19320
|
if (endpoint === "codex.workspace.create") {
|
|
19223
|
-
const value =
|
|
19321
|
+
const value = record3(payload);
|
|
19224
19322
|
if (typeof value.targetDeviceId !== "string" || typeof value.path !== "string") {
|
|
19225
19323
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and CodeX project directory are required.");
|
|
19226
19324
|
}
|
|
19227
19325
|
return ok2(await this.createCodexWorkspace(value.targetDeviceId, value.path, signal));
|
|
19228
19326
|
}
|
|
19229
19327
|
if (endpoint === "workspace.selection.consume") {
|
|
19230
|
-
const value =
|
|
19328
|
+
const value = record3(payload);
|
|
19231
19329
|
if (typeof value.targetDeviceId !== "string" || typeof value.workspaceId !== "string") {
|
|
19232
19330
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and Workspace are required.");
|
|
19233
19331
|
}
|
|
@@ -19243,7 +19341,7 @@ var ClientModeRuntime = class {
|
|
|
19243
19341
|
return ok2(await this.callRemoteFileViewer(method, payload, signal));
|
|
19244
19342
|
}
|
|
19245
19343
|
if (endpoint === "codex.call") {
|
|
19246
|
-
const value =
|
|
19344
|
+
const value = record3(payload);
|
|
19247
19345
|
if (typeof value.method !== "string" || !("params" in value)) {
|
|
19248
19346
|
throw new ClientModeError("INVALID_MESSAGE", "A Codex method and params are required.");
|
|
19249
19347
|
}
|
|
@@ -19267,7 +19365,7 @@ var ClientModeRuntime = class {
|
|
|
19267
19365
|
return ok2({ supported: local || remoteSupported, local, remote: remoteSupported });
|
|
19268
19366
|
}
|
|
19269
19367
|
if (endpoint === "codex.respond") {
|
|
19270
|
-
const value =
|
|
19368
|
+
const value = record3(payload);
|
|
19271
19369
|
const remote = this.activeCodexRemote();
|
|
19272
19370
|
if (remote !== void 0) return ok2(await remote.client.rpc("codex.app.respond", value, signal));
|
|
19273
19371
|
const host = this.requireLocalCodex();
|
|
@@ -19278,14 +19376,14 @@ var ClientModeRuntime = class {
|
|
|
19278
19376
|
if (endpoint === "codex.stream.close") return ok2(await this.closeCodexStream(payload));
|
|
19279
19377
|
if (endpoint === "host.account.login") {
|
|
19280
19378
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19281
|
-
const value =
|
|
19379
|
+
const value = record3(payload);
|
|
19282
19380
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
19283
19381
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
19284
19382
|
}
|
|
19285
19383
|
return ok2(await this.host.authorizeHostWithAccount(value.email, value.password));
|
|
19286
19384
|
}
|
|
19287
19385
|
if (endpoint === "host.authorization.set") {
|
|
19288
|
-
const value =
|
|
19386
|
+
const value = record3(payload);
|
|
19289
19387
|
if (typeof value.enabled !== "boolean") {
|
|
19290
19388
|
throw new ClientModeError("INVALID_MESSAGE", "Host authorization state is required.");
|
|
19291
19389
|
}
|
|
@@ -19293,14 +19391,14 @@ var ClientModeRuntime = class {
|
|
|
19293
19391
|
}
|
|
19294
19392
|
if (endpoint === "host.registration-code.submit") {
|
|
19295
19393
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19296
|
-
const value =
|
|
19394
|
+
const value = record3(payload);
|
|
19297
19395
|
if (typeof value.code !== "string" || value.code.trim() === "") {
|
|
19298
19396
|
throw new ClientModeError("INVALID_MESSAGE", "A Host registration code is required.");
|
|
19299
19397
|
}
|
|
19300
19398
|
return ok2(await this.host.authorizeHostWithCode(value.code));
|
|
19301
19399
|
}
|
|
19302
19400
|
if (endpoint === "mode.set") {
|
|
19303
|
-
const value =
|
|
19401
|
+
const value = record3(payload);
|
|
19304
19402
|
if (value.mode !== "local" && value.mode !== "remote") throw new ClientModeError("INVALID_MESSAGE", "Mode must be local or remote.");
|
|
19305
19403
|
return ok2(await this.setMode(value.mode, typeof value.targetDeviceId === "string" ? value.targetDeviceId : void 0, signal));
|
|
19306
19404
|
}
|
|
@@ -19364,7 +19462,7 @@ function webrtcDiagnosticsLogFields(diagnostics) {
|
|
|
19364
19462
|
...diagnostics.selectedPath === void 0 ? {} : { rtcSelectedPath: diagnostics.selectedPath }
|
|
19365
19463
|
};
|
|
19366
19464
|
}
|
|
19367
|
-
function
|
|
19465
|
+
function record3(value) {
|
|
19368
19466
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
19369
19467
|
throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
|
|
19370
19468
|
}
|
|
@@ -19528,10 +19626,6 @@ function preferredTransportsForAttempt(attempt) {
|
|
|
19528
19626
|
if (attempt === "turn") return ["turn", "relay"];
|
|
19529
19627
|
return ["relay"];
|
|
19530
19628
|
}
|
|
19531
|
-
function activeTransportsForAttempt(attempt) {
|
|
19532
|
-
if (attempt === "direct") return ["lan", "p2p"];
|
|
19533
|
-
return [attempt];
|
|
19534
|
-
}
|
|
19535
19629
|
function transportPreferenceForMode(mode) {
|
|
19536
19630
|
if (mode === "LAN") return "lan";
|
|
19537
19631
|
if (mode === "P2P") return "p2p";
|
|
@@ -19593,24 +19687,24 @@ var IdentityStore = class {
|
|
|
19593
19687
|
}
|
|
19594
19688
|
if (!hasDevice) {
|
|
19595
19689
|
const keys = generateKeyPair();
|
|
19596
|
-
const
|
|
19597
|
-
await atomicJsonWrite(devicePath,
|
|
19690
|
+
const record6 = { schemaVersion: 1, deviceId: uuidV7(), name: deviceName, publicKey: keys.publicKey };
|
|
19691
|
+
await atomicJsonWrite(devicePath, record6, 384);
|
|
19598
19692
|
await atomicTextWrite(keyPath, `${keys.privateKey}
|
|
19599
19693
|
`, 384);
|
|
19600
19694
|
}
|
|
19601
19695
|
await assertPrivateMode(keyPath);
|
|
19602
19696
|
try {
|
|
19603
|
-
let
|
|
19697
|
+
let record6 = identitySchema.parse(JSON.parse(await readFile(devicePath, "utf8")));
|
|
19604
19698
|
const privateKey = (await readFile(keyPath, "utf8")).trim();
|
|
19605
19699
|
const regenerated = generateKeyPair(fromBase64Url2(privateKey));
|
|
19606
|
-
if (regenerated.publicKey !==
|
|
19700
|
+
if (regenerated.publicKey !== record6.publicKey) {
|
|
19607
19701
|
throw new IdentityInvalidError("device public and private keys do not match");
|
|
19608
19702
|
}
|
|
19609
|
-
if (
|
|
19610
|
-
|
|
19611
|
-
await atomicJsonWrite(devicePath,
|
|
19703
|
+
if (record6.name !== deviceName) {
|
|
19704
|
+
record6 = { ...record6, name: deviceName };
|
|
19705
|
+
await atomicJsonWrite(devicePath, record6, 384);
|
|
19612
19706
|
}
|
|
19613
|
-
this.identity = { ...
|
|
19707
|
+
this.identity = { ...record6, privateKey, fingerprint: fingerprint(record6.publicKey) };
|
|
19614
19708
|
await this.loadPeers();
|
|
19615
19709
|
return this.identity;
|
|
19616
19710
|
} catch (error) {
|
|
@@ -19752,10 +19846,10 @@ var ServerCredentialStore = class {
|
|
|
19752
19846
|
return parsed.serverUrl === serverUrl && parsed.deviceId === deviceId ? parsed : void 0;
|
|
19753
19847
|
}
|
|
19754
19848
|
async save(credentials) {
|
|
19755
|
-
const
|
|
19756
|
-
await atomicWrite(this.path, `${JSON.stringify(
|
|
19849
|
+
const record6 = credentialSchema.parse({ schemaVersion: 1, ...credentials });
|
|
19850
|
+
await atomicWrite(this.path, `${JSON.stringify(record6, null, 2)}
|
|
19757
19851
|
`);
|
|
19758
|
-
return
|
|
19852
|
+
return record6;
|
|
19759
19853
|
}
|
|
19760
19854
|
async clear() {
|
|
19761
19855
|
await rm2(this.path, { force: true });
|
|
@@ -19822,7 +19916,7 @@ var PluginControlRuntime = class {
|
|
|
19822
19916
|
if (endpoint === "devices") return ok3([]);
|
|
19823
19917
|
if (endpoint === "host.account.login") {
|
|
19824
19918
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19825
|
-
const value =
|
|
19919
|
+
const value = record4(payload);
|
|
19826
19920
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
19827
19921
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
19828
19922
|
}
|
|
@@ -19830,13 +19924,13 @@ var PluginControlRuntime = class {
|
|
|
19830
19924
|
}
|
|
19831
19925
|
if (endpoint === "host.registration-code.submit") {
|
|
19832
19926
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
19833
|
-
const value =
|
|
19927
|
+
const value = record4(payload);
|
|
19834
19928
|
if (typeof value.code !== "string" || value.code.trim() === "") {
|
|
19835
19929
|
throw new ClientModeError("INVALID_MESSAGE", "A Host registration code is required.");
|
|
19836
19930
|
}
|
|
19837
19931
|
return ok3(await this.host.authorizeHostWithCode(value.code));
|
|
19838
19932
|
}
|
|
19839
|
-
if (endpoint === "mode.set" &&
|
|
19933
|
+
if (endpoint === "mode.set" && record4(payload).mode === "local") return ok3(this.hostOnlyStatus());
|
|
19840
19934
|
throw new ClientModeError("METHOD_NOT_ALLOWED", "Remote Client mode is disabled by the plugin role.");
|
|
19841
19935
|
} catch (error) {
|
|
19842
19936
|
return fail3(error);
|
|
@@ -19846,7 +19940,7 @@ var PluginControlRuntime = class {
|
|
|
19846
19940
|
if (this.settings === void 0) {
|
|
19847
19941
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19848
19942
|
}
|
|
19849
|
-
const value =
|
|
19943
|
+
const value = record4(payload);
|
|
19850
19944
|
if (value.role !== "host" && value.role !== "client") {
|
|
19851
19945
|
throw new ClientModeError("INVALID_MESSAGE", "Role must be Host or Client.");
|
|
19852
19946
|
}
|
|
@@ -19881,7 +19975,7 @@ var PluginControlRuntime = class {
|
|
|
19881
19975
|
if (this.settings === void 0) {
|
|
19882
19976
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19883
19977
|
}
|
|
19884
|
-
const value =
|
|
19978
|
+
const value = record4(payload);
|
|
19885
19979
|
if (typeof value.serverUrl !== "string") {
|
|
19886
19980
|
throw new ClientModeError("INVALID_MESSAGE", "Server URL is required.");
|
|
19887
19981
|
}
|
|
@@ -19894,7 +19988,7 @@ var PluginControlRuntime = class {
|
|
|
19894
19988
|
if (this.settings === void 0) {
|
|
19895
19989
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19896
19990
|
}
|
|
19897
|
-
const role =
|
|
19991
|
+
const role = record4(payload).role;
|
|
19898
19992
|
if (role !== "host" && role !== "client") {
|
|
19899
19993
|
throw new ClientModeError("INVALID_MESSAGE", "Role must be Host or Client.");
|
|
19900
19994
|
}
|
|
@@ -19910,7 +20004,7 @@ var PluginControlRuntime = class {
|
|
|
19910
20004
|
if (this.settings === void 0) {
|
|
19911
20005
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
19912
20006
|
}
|
|
19913
|
-
const enabled =
|
|
20007
|
+
const enabled = record4(payload).enabled;
|
|
19914
20008
|
if (typeof enabled !== "boolean") {
|
|
19915
20009
|
throw new ClientModeError("INVALID_MESSAGE", "Codex Remote enabled must be a boolean.");
|
|
19916
20010
|
}
|
|
@@ -20019,7 +20113,7 @@ function editableConfig(config) {
|
|
|
20019
20113
|
function isRecord6(value) {
|
|
20020
20114
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20021
20115
|
}
|
|
20022
|
-
function
|
|
20116
|
+
function record4(value) {
|
|
20023
20117
|
if (!isRecord6(value)) throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
|
|
20024
20118
|
return value;
|
|
20025
20119
|
}
|
|
@@ -22626,11 +22720,11 @@ function needsDirectoryFallback(result) {
|
|
|
22626
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");
|
|
22627
22721
|
}
|
|
22628
22722
|
function requestArgs(payload) {
|
|
22629
|
-
const root =
|
|
22723
|
+
const root = record5(payload);
|
|
22630
22724
|
const args = isRecord7(root.args) ? root.args : root;
|
|
22631
|
-
return
|
|
22725
|
+
return record5(args.request ?? args._request ?? args);
|
|
22632
22726
|
}
|
|
22633
|
-
function
|
|
22727
|
+
function record5(value) {
|
|
22634
22728
|
return isRecord7(value) ? value : {};
|
|
22635
22729
|
}
|
|
22636
22730
|
function isRecord7(value) {
|
|
@@ -23289,6 +23383,7 @@ var CodexRemoteDomain = class {
|
|
|
23289
23383
|
peerDeviceIds = /* @__PURE__ */ new Map();
|
|
23290
23384
|
turnOwners = /* @__PURE__ */ new Map();
|
|
23291
23385
|
approvals = /* @__PURE__ */ new Map();
|
|
23386
|
+
permissionPresets = /* @__PURE__ */ new Map();
|
|
23292
23387
|
approvalExpiryTimer;
|
|
23293
23388
|
restartTimer;
|
|
23294
23389
|
restartAttempt = 0;
|
|
@@ -23367,6 +23462,7 @@ var CodexRemoteDomain = class {
|
|
|
23367
23462
|
if (extractThread(result)?.id === void 0) {
|
|
23368
23463
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid thread.");
|
|
23369
23464
|
}
|
|
23465
|
+
this.rememberPermission(extractThread(result).id, result);
|
|
23370
23466
|
return result;
|
|
23371
23467
|
}
|
|
23372
23468
|
const threadId = threadIdFromParams(call.params);
|
|
@@ -23381,12 +23477,23 @@ var CodexRemoteDomain = class {
|
|
|
23381
23477
|
}
|
|
23382
23478
|
);
|
|
23383
23479
|
const activeTurnId2 = typeof page.activeTurnId === "string" ? page.activeTurnId : this.turnOwners.get(threadId)?.turnId;
|
|
23384
|
-
return
|
|
23480
|
+
return {
|
|
23481
|
+
...page,
|
|
23482
|
+
...activeTurnId2 === void 0 ? {} : { activeTurnId: activeTurnId2 },
|
|
23483
|
+
permissionPreset: this.permissionPresets.get(threadId) ?? null
|
|
23484
|
+
};
|
|
23385
23485
|
}
|
|
23386
23486
|
if (call.method === "dsh/directoryList") {
|
|
23387
23487
|
return this.listCodexDirectory(call.params.path);
|
|
23388
23488
|
}
|
|
23389
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
|
+
}
|
|
23390
23497
|
if (call.method === "thread/read") {
|
|
23391
23498
|
return this.callUpstream(call.method, call.params);
|
|
23392
23499
|
}
|
|
@@ -23436,8 +23543,18 @@ var CodexRemoteDomain = class {
|
|
|
23436
23543
|
if (call.method === "thread/resume" || call.method === "thread/fork" || call.method === "thread/unarchive") {
|
|
23437
23544
|
await this.assertResultThreadAllowed(result);
|
|
23438
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
|
+
}
|
|
23439
23553
|
if (call.method === "turn/start" && threadId !== void 0) {
|
|
23440
23554
|
this.rememberTurnId(threadId, connectionId, extractTurnId(result));
|
|
23555
|
+
if (call.params.permissionPreset !== void 0) {
|
|
23556
|
+
await this.publishPermission(threadId, codexTurnPermissionParams(permission, allowedThread?.cwd));
|
|
23557
|
+
}
|
|
23441
23558
|
}
|
|
23442
23559
|
return result;
|
|
23443
23560
|
} catch (error) {
|
|
@@ -23486,6 +23603,7 @@ var CodexRemoteDomain = class {
|
|
|
23486
23603
|
this.peers.clear();
|
|
23487
23604
|
this.peerDeviceIds.clear();
|
|
23488
23605
|
this.turnOwners.clear();
|
|
23606
|
+
this.permissionPresets.clear();
|
|
23489
23607
|
if (this.approvalExpiryTimer !== void 0) clearTimeout(this.approvalExpiryTimer);
|
|
23490
23608
|
this.approvalExpiryTimer = void 0;
|
|
23491
23609
|
this.approvals.clear();
|
|
@@ -23548,6 +23666,7 @@ var CodexRemoteDomain = class {
|
|
|
23548
23666
|
this.state = "restarting";
|
|
23549
23667
|
this.unavailableCode = code;
|
|
23550
23668
|
this.turnOwners.clear();
|
|
23669
|
+
this.permissionPresets.clear();
|
|
23551
23670
|
this.approvals.clear();
|
|
23552
23671
|
if (this.approvalExpiryTimer !== void 0) clearTimeout(this.approvalExpiryTimer);
|
|
23553
23672
|
this.approvalExpiryTimer = void 0;
|
|
@@ -23603,6 +23722,10 @@ var CodexRemoteDomain = class {
|
|
|
23603
23722
|
return;
|
|
23604
23723
|
}
|
|
23605
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);
|
|
23606
23729
|
if (message.method === "turn/completed" && threadId !== void 0) this.turnOwners.delete(threadId);
|
|
23607
23730
|
if (message.method === "turn/started" && threadId !== void 0) {
|
|
23608
23731
|
const owner = this.turnOwners.get(threadId);
|
|
@@ -23618,6 +23741,42 @@ var CodexRemoteDomain = class {
|
|
|
23618
23741
|
params: message.params
|
|
23619
23742
|
})));
|
|
23620
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
|
+
}
|
|
23621
23780
|
async handleServerRequest(message) {
|
|
23622
23781
|
const appServer = this.requireAppServer();
|
|
23623
23782
|
await this.expireApprovals();
|
|
@@ -24078,7 +24237,7 @@ function filterThreadListByWorkspaceAuthority(result, authority) {
|
|
|
24078
24237
|
}
|
|
24079
24238
|
return {
|
|
24080
24239
|
...result,
|
|
24081
|
-
data: result.data.map((
|
|
24240
|
+
data: result.data.map((record6) => isRecord10(record6) ? record6 : void 0).filter((thread) => thread !== void 0 && isThreadAllowedByWorkspaceAuthority(thread, authority))
|
|
24082
24241
|
};
|
|
24083
24242
|
}
|
|
24084
24243
|
function sanitizeProject(value) {
|