@codexhost/cli-darwin-arm64 0.3.0-test.1 → 0.3.0-test.3

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 CHANGED
@@ -7,7 +7,7 @@ Run Pi and Claude Code as first-class external harnesses inside Codex Desktop.
7
7
  ## Install
8
8
 
9
9
  ```bash
10
- npm install -g @codexhost/cli@0.3.0-test.1
10
+ npm install -g @codexhost/cli@0.3.0-test.3
11
11
  ```
12
12
 
13
13
  Do not install this package directly. npm selects it through the optional dependencies of `@codexhost/cli`.
@@ -1 +1 @@
1
- {"schemaVersion":1,"version":"0.3.0-test.1","distribution":"npm","target":"macos-arm64"}
1
+ {"schemaVersion":1,"version":"0.3.0-test.3","distribution":"npm","target":"macos-arm64"}
@@ -560,55 +560,35 @@ async function readMainProcessTitlePolicyCounters(inspector) {
560
560
  // packages/desktop-control/src/renderer-draft-prewarm-runtime.ts
561
561
  function installDraftPrewarmPolicyBridge(bridge, hostId, target, prewarmedThreadManager) {
562
562
  const existing = target.__codexhostDraftPrewarmPolicyV1;
563
- if (existing?.owns?.(bridge, hostId) === true) {
563
+ if (existing?.owns?.length === 3 && existing.owns(bridge, hostId, prewarmedThreadManager) === true) {
564
564
  return { state: "ready", reason: "owned-request-bridge" };
565
565
  }
566
566
  existing?.dispose?.();
567
567
  const originalSend = bridge.sendRequest;
568
568
  const originalPrewarm = bridge.prewarmThreadStart;
569
569
  let selectedModel = null;
570
- let clearInFlight = null;
571
570
  const isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
572
- const routeCollaborationMode = (method, parameters) => {
573
- if (selectedModel === null || !isRecord5(parameters)) return parameters;
574
- const collaborationMode = parameters.collaborationMode;
575
- const settings = isRecord5(collaborationMode) ? collaborationMode.settings : null;
576
- if (!isRecord5(collaborationMode) || !isRecord5(settings)) {
577
- throw new Error(`Codex ${method} omitted collaborationMode.settings`);
571
+ const routeThreadStart = (parameters) => {
572
+ if (selectedModel === null || !isRecord5(parameters) || parameters.ephemeral === true) {
573
+ return parameters;
578
574
  }
579
- return {
580
- ...parameters,
581
- collaborationMode: {
582
- ...collaborationMode,
583
- settings: { ...settings, model: selectedModel }
584
- }
585
- };
586
- };
587
- const routeThreadStart = (method, parameters) => {
588
- if (selectedModel === null || !isRecord5(parameters)) return parameters;
589
- const direct = method === "thread/start";
590
- const wrapped = method === "prewarm-thread-start-for-host" || method === "send-cli-request-for-host";
591
- if (!direct && !wrapped) return parameters;
592
- const threadParams = direct ? parameters : parameters.params;
593
- if (!isRecord5(threadParams) || threadParams.ephemeral === true) return parameters;
594
- if (direct) return { ...threadParams, model: selectedModel };
595
- return { ...parameters, params: { ...threadParams, model: selectedModel } };
575
+ return { ...parameters, model: selectedModel };
596
576
  };
597
577
  const routedSend = (method, parameters, options) => {
598
- const routedParameters = method === "start-conversation" || method === "prewarm-conversation-for-host" ? routeCollaborationMode(method, parameters) : routeThreadStart(method, parameters);
578
+ const routedParameters = method === "thread/start" ? routeThreadStart(parameters) : parameters;
599
579
  return options === void 0 ? originalSend.call(bridge, method, routedParameters) : originalSend.call(bridge, method, routedParameters, options);
600
580
  };
601
581
  const routedPrewarm = (parameters, options) => {
602
- const routedParameters = routeThreadStart("thread/start", parameters);
603
- return options === void 0 ? originalPrewarm?.call(bridge, routedParameters) : originalPrewarm?.call(bridge, routedParameters, options);
582
+ const routedParameters = routeThreadStart(parameters);
583
+ return options === void 0 ? originalPrewarm.call(bridge, routedParameters) : originalPrewarm.call(bridge, routedParameters, options);
604
584
  };
605
585
  bridge.sendRequest = routedSend;
606
- if (originalPrewarm) bridge.prewarmThreadStart = routedPrewarm;
586
+ bridge.prewarmThreadStart = routedPrewarm;
607
587
  const policy = Object.freeze({
608
588
  state: "ready",
609
589
  hostId,
610
- owns(candidate, candidateHostId) {
611
- return candidate === bridge && candidateHostId === hostId;
590
+ owns(candidate, candidateHostId, candidatePrewarmedThreadManager) {
591
+ return candidate === bridge && candidateHostId === hostId && candidatePrewarmedThreadManager === prewarmedThreadManager;
612
592
  },
613
593
  select(model) {
614
594
  if (model !== null && (typeof model !== "string" || !model.startsWith("codexhost/"))) {
@@ -619,24 +599,13 @@ function installDraftPrewarmPolicyBridge(bridge, hostId, target, prewarmedThread
619
599
  return true;
620
600
  },
621
601
  clear() {
622
- if (prewarmedThreadManager?.discardAllPrewarmedThreads) {
623
- prewarmedThreadManager.discardAllPrewarmedThreads();
624
- return Promise.resolve();
625
- }
626
- if (clearInFlight === null) {
627
- clearInFlight = Promise.resolve(
628
- originalSend.call(bridge, "clear-prewarmed-threads-for-host", { hostId })
629
- ).then(() => void 0).finally(() => {
630
- clearInFlight = null;
631
- });
632
- }
633
- return clearInFlight;
602
+ prewarmedThreadManager.discardAllPrewarmedThreads();
603
+ return Promise.resolve();
634
604
  },
635
605
  dispose() {
636
606
  if (bridge.sendRequest === routedSend) bridge.sendRequest = originalSend;
637
607
  if (bridge.prewarmThreadStart === routedPrewarm) {
638
- if (originalPrewarm) bridge.prewarmThreadStart = originalPrewarm;
639
- else delete bridge.prewarmThreadStart;
608
+ bridge.prewarmThreadStart = originalPrewarm;
640
609
  }
641
610
  selectedModel = null;
642
611
  }
@@ -685,84 +654,13 @@ async function installDraftPrewarmPolicyInRenderer(contents, findRequestManagerE
685
654
  if (candidateCount !== 1 || typeof hostId !== "string" || hostId.length === 0 || typeof manager?.objectId !== "string") {
686
655
  throw new Error("Renderer request manager is ambiguous");
687
656
  }
688
- const managerFunctions = await contents.debugger.sendCommand("Runtime.getProperties", {
689
- objectId: manager.objectId
690
- });
691
- const managerPropertyNames = new Set(
692
- managerFunctions.result?.map((property) => String(property.name)) ?? []
693
- );
694
- let hostBridgeObjectId = managerPropertyNames.has("sendRequest") && managerPropertyNames.has("prewarmThreadStart") && managerPropertyNames.has("enqueueRequest") ? manager.objectId : void 0;
695
- if (!hostBridgeObjectId) {
696
- let managerSendRequestId = managerFunctions.result?.find(
697
- (property) => property.name === "sendRequest"
698
- )?.value?.objectId;
699
- const managerPrototypeId = managerFunctions.internalProperties?.find(
700
- (property) => property.name === "[[Prototype]]"
701
- )?.value?.objectId;
702
- if (typeof managerSendRequestId !== "string" && typeof managerPrototypeId === "string") {
703
- const prototypeFunctions = await contents.debugger.sendCommand("Runtime.getProperties", {
704
- objectId: managerPrototypeId,
705
- ownProperties: true
706
- });
707
- managerSendRequestId = prototypeFunctions.result?.find(
708
- (property) => property.name === "sendRequest"
709
- )?.value?.objectId;
710
- }
711
- if (typeof managerSendRequestId !== "string") {
712
- throw new Error("Renderer request manager sendRequest is unavailable");
713
- }
714
- const functionProperties = await contents.debugger.sendCommand("Runtime.getProperties", {
715
- objectId: managerSendRequestId
716
- });
717
- const scopesId = functionProperties.internalProperties?.find(
718
- (property) => property.name === "[[Scopes]]"
719
- )?.value?.objectId;
720
- const hostBridgeCandidates = [];
721
- if (typeof scopesId === "string") {
722
- const scopes = await contents.debugger.sendCommand("Runtime.getProperties", {
723
- objectId: scopesId,
724
- ownProperties: true
725
- });
726
- for (const scope of scopes.result ?? []) {
727
- if (typeof scope.value?.objectId !== "string") continue;
728
- const scopeProperties = await contents.debugger.sendCommand("Runtime.getProperties", {
729
- objectId: scope.value.objectId,
730
- ownProperties: true
731
- });
732
- for (const property of scopeProperties.result ?? []) {
733
- if (property.value?.type !== "object" || typeof property.value.objectId !== "string") {
734
- continue;
735
- }
736
- const candidateSignature = await contents.debugger.sendCommand(
737
- "Runtime.callFunctionOn",
738
- {
739
- objectId: property.value.objectId,
740
- functionDeclaration: "function(){const send=this.sendRequest;return typeof send==='function'&&Function.prototype.toString.call(send).includes('messageHandler')}",
741
- returnByValue: true
742
- }
743
- );
744
- if (candidateSignature.result?.value === true) {
745
- hostBridgeCandidates.push({
746
- name: String(property.name),
747
- objectId: property.value.objectId
748
- });
749
- }
750
- }
751
- }
752
- }
753
- const hostBridge = hostBridgeCandidates[0];
754
- if (hostBridgeCandidates.length !== 1 || !hostBridge) {
755
- throw new Error("Renderer Host request bridge is ambiguous");
756
- }
757
- hostBridgeObjectId = hostBridge.objectId;
657
+ if (typeof prewarmedThreadManager?.objectId !== "string") {
658
+ throw new Error("Renderer prewarmed Thread manager is unavailable");
758
659
  }
759
660
  const installed = await contents.debugger.sendCommand("Runtime.callFunctionOn", {
760
- objectId: hostBridgeObjectId,
661
+ objectId: manager.objectId,
761
662
  functionDeclaration: installRendererPolicyFunction,
762
- arguments: [
763
- { value: hostId },
764
- ...typeof prewarmedThreadManager?.objectId === "string" ? [{ objectId: prewarmedThreadManager.objectId }] : []
765
- ],
663
+ arguments: [{ value: hostId }, { objectId: prewarmedThreadManager.objectId }],
766
664
  awaitPromise: true,
767
665
  returnByValue: true
768
666
  });
@@ -825,6 +723,7 @@ var FIND_REQUEST_MANAGER_EXPRESSION = `(() => {
825
723
  typeof value.requestClient.prewarmThreadStart === 'function' &&
826
724
  typeof value.requestClient.sendRequest === 'function' &&
827
725
  typeof value.requestClient.enqueueRequest === 'function' &&
726
+ typeof value.prewarmedThreadManager?.discardAllPrewarmedThreads === 'function' &&
828
727
  typeof value.sendRequest === 'function'
829
728
  ) {
830
729
  managers.add(value);
@@ -63915,6 +63915,20 @@ function decodeThreadForkRequest(request) {
63915
63915
  ...optionalField(params, "serviceTier")
63916
63916
  };
63917
63917
  }
63918
+ function decodeThreadRevertRequest(request) {
63919
+ if (request.method !== "thread/revert")
63920
+ return null;
63921
+ if (!isRecord26(request.params))
63922
+ throw new Error("thread/revert params must be an object");
63923
+ const { threadId: threadId2, beforeTurnId } = request.params;
63924
+ if (typeof threadId2 !== "string" || threadId2.length === 0) {
63925
+ throw new Error("thread/revert params.threadId must be non-empty text");
63926
+ }
63927
+ if (typeof beforeTurnId !== "string" || beforeTurnId.length === 0) {
63928
+ throw new Error("thread/revert params.beforeTurnId must be non-empty text");
63929
+ }
63930
+ return { threadId: threadId2, beforeTurnId: hostTurnIdSchema.parse(beforeTurnId) };
63931
+ }
63918
63932
  function decodeThreadRollbackRequest(request) {
63919
63933
  if (request.method !== "thread/rollback")
63920
63934
  return null;
@@ -63957,6 +63971,9 @@ function mapExternalThreadHarnessError(error54, operation) {
63957
63971
  return { code: -32076, message: `External Thread ${operation} failed` };
63958
63972
  }
63959
63973
  }
63974
+ function threadRevertResult(thread) {
63975
+ return { thread: { ...thread, turns: [] } };
63976
+ }
63960
63977
  function threadRollbackResult(thread) {
63961
63978
  return { thread };
63962
63979
  }
@@ -65250,12 +65267,18 @@ async function executeCurrentLastTurnRollback(input) {
65250
65267
  return { ok: true, thread };
65251
65268
  }
65252
65269
  async function executeExternalThreadRollback(input) {
65253
- const { derived, rollback, adapters, repository, runtime } = input;
65270
+ const { derived, rollback, adapters, repository, runtime, expectedLastTurnId } = input;
65254
65271
  if (derived.running) {
65255
65272
  return { ok: false, error: { code: -32072, message: "External Thread has an active Turn" } };
65256
65273
  }
65257
65274
  const refreshError = await runtime.refresh(derived);
65258
65275
  if (refreshError) return { ok: false, error: refreshError };
65276
+ if (expectedLastTurnId !== void 0 && derived.record.turnMappings.at(-1)?.hostTurnId !== expectedLastTurnId) {
65277
+ return {
65278
+ ok: false,
65279
+ error: { code: -32080, message: "External Revert boundary is unavailable" }
65280
+ };
65281
+ }
65259
65282
  if (rollback.numTurns === 1 && derived.session.capabilities.history.rollbackLastTurn) {
65260
65283
  return executeCurrentLastTurnRollback({
65261
65284
  current: derived,
@@ -66209,6 +66232,7 @@ var EXPLICIT_EXTERNAL_THREAD_METHODS = /* @__PURE__ */ new Set([
66209
66232
  "thread/name/set",
66210
66233
  "thread/read",
66211
66234
  "thread/resume",
66235
+ "thread/revert",
66212
66236
  "thread/rollback",
66213
66237
  "thread/turns/list",
66214
66238
  "thread/unarchive",
@@ -66566,6 +66590,29 @@ var AppServerHost = class {
66566
66590
  continue;
66567
66591
  }
66568
66592
  }
66593
+ if (request.method === "thread/revert") {
66594
+ const params = isRecord31(request.params) ? request.params : {};
66595
+ const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
66596
+ if (resolution.kind === "error") {
66597
+ await this.#writer.json(
66598
+ rpcError(request, resolution.error.code, resolution.error.message)
66599
+ );
66600
+ continue;
66601
+ }
66602
+ if (resolution.kind === "external") {
66603
+ let revert;
66604
+ try {
66605
+ const decoded = decodeThreadRevertRequest(request);
66606
+ if (!decoded) throw new Error("Expected thread/revert request");
66607
+ revert = decoded;
66608
+ } catch (error54) {
66609
+ await this.#writer.json(rpcError(request, -32602, errorMessage4(error54)));
66610
+ continue;
66611
+ }
66612
+ await this.#revertExternalThread(request, resolution.thread, revert);
66613
+ continue;
66614
+ }
66615
+ }
66569
66616
  if (request.method === "thread/rollback") {
66570
66617
  const params = isRecord31(request.params) ? request.params : {};
66571
66618
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
@@ -67527,6 +67574,28 @@ var AppServerHost = class {
67527
67574
  params: { thread: { ...thread, turns: [] } }
67528
67575
  });
67529
67576
  }
67577
+ async #revertExternalThread(request, thread, revert) {
67578
+ if (thread.record.historyMode !== "paginated") {
67579
+ await this.#writer.json(
67580
+ rpcError(request, -32602, "External thread/revert requires paginated history")
67581
+ );
67582
+ return;
67583
+ }
67584
+ const result = await executeExternalThreadRollback({
67585
+ derived: thread,
67586
+ rollback: { threadId: revert.threadId, numTurns: 1 },
67587
+ expectedLastTurnId: revert.beforeTurnId,
67588
+ adapters: this.#externalAdapters,
67589
+ repository: this.#repository,
67590
+ runtime: this.#externalRuntime
67591
+ });
67592
+ if (!result.ok) {
67593
+ await this.#writer.json(rpcError(request, result.error.code, result.error.message));
67594
+ return;
67595
+ }
67596
+ await this.#writer.json(rpcEnvelope(request, { result: threadRevertResult(result.thread) }));
67597
+ await this.#writer.json({ method: "thread/reverted", params: { threadId: thread.id } });
67598
+ }
67530
67599
  async #rollbackExternalThread(request, derived, rollback) {
67531
67600
  const result = await executeExternalThreadRollback({
67532
67601
  derived,
@@ -69282,10 +69351,14 @@ function installManagedProfileBlock(contents, manifest) {
69282
69351
  "export CODEXHOST_REMOTE_SSH_MANAGED='1'",
69283
69352
  ...manifest.claudeCommand ? [`export CODEXHOST_CLAUDE_COMMAND=${shellQuote(manifest.claudeCommand)}`] : []
69284
69353
  ];
69285
- const block = `${PROFILE_START}
69286
- ${environment.join("\n")}
69287
- ${PROFILE_END}
69288
- `;
69354
+ const block = [
69355
+ PROFILE_START,
69356
+ 'if [ -n "${SSH_CONNECTION:-}" ] || [ -n "${SSH_CLIENT:-}" ]; then',
69357
+ ...environment.map((entry) => ` ${entry}`),
69358
+ "fi",
69359
+ PROFILE_END,
69360
+ ""
69361
+ ].join("\n");
69289
69362
  if (path24.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
69290
69363
  const separator = base.length > 0 && !base.endsWith("\n") ? "\n" : "";
69291
69364
  return `${base}${separator}${block}`;