codexui-android 0.1.101 → 0.1.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.html CHANGED
@@ -12,8 +12,8 @@
12
12
  <link rel="icon" type="image/png" sizes="192x192" href="/icons/pwa-192x192.png" />
13
13
  <link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png" />
14
14
  <title>Codex Web</title>
15
- <script type="module" crossorigin src="/assets/index-DzzwK-KG.js"></script>
16
- <link rel="stylesheet" crossorigin href="/assets/index-B6Gx9sFJ.css">
15
+ <script type="module" crossorigin src="/assets/index-Dpl251IF.js"></script>
16
+ <link rel="stylesheet" crossorigin href="/assets/index-CDFerptZ.css">
17
17
  </head>
18
18
  <body class="bg-slate-950">
19
19
  <div id="app"></div>
package/dist-cli/index.js CHANGED
@@ -6867,6 +6867,60 @@ async function writeThreadQueueState(nextState) {
6867
6867
  }
6868
6868
  await writeFile4(statePath, JSON.stringify(payload), "utf8");
6869
6869
  }
6870
+ function normalizeReasoningEffort(value) {
6871
+ const allowed = ["none", "minimal", "low", "medium", "high", "xhigh"];
6872
+ return typeof value === "string" && allowed.includes(value) ? value : "";
6873
+ }
6874
+ function normalizeCollaborationModeReasoningEffort(value) {
6875
+ return value && value.length > 0 ? value : null;
6876
+ }
6877
+ function extractLocalImagePathFromUrl(value) {
6878
+ if (!value) return null;
6879
+ try {
6880
+ const parsed = new URL(value, "http://localhost");
6881
+ if (parsed.pathname !== "/codex-local-image") return null;
6882
+ const path = parsed.searchParams.get("path")?.trim() ?? "";
6883
+ return path.length > 0 ? path : null;
6884
+ } catch {
6885
+ return null;
6886
+ }
6887
+ }
6888
+ function buildTextWithAttachments(prompt, files) {
6889
+ if (files.length === 0) return prompt;
6890
+ let prefix = "# Files mentioned by the user:\n";
6891
+ for (const f of files) {
6892
+ prefix += `
6893
+ ## ${f.label}: ${f.path}
6894
+ `;
6895
+ }
6896
+ return `${prefix}
6897
+ ## My request for Codex:
6898
+
6899
+ ${prompt}
6900
+ `;
6901
+ }
6902
+ function fileNameFromPath(pathValue) {
6903
+ const normalized = pathValue.replace(/\\/g, "/");
6904
+ const segments = normalized.split("/").filter(Boolean);
6905
+ return segments.at(-1) ?? normalized;
6906
+ }
6907
+ function extractThreadIdFromNotificationParams(params) {
6908
+ const record = asRecord5(params);
6909
+ if (!record) return "";
6910
+ const threadId = (typeof record.threadId === "string" ? record.threadId : "") || (typeof record.thread_id === "string" ? record.thread_id : "") || (typeof record.conversationId === "string" ? record.conversationId : "") || (typeof record.conversation_id === "string" ? record.conversation_id : "");
6911
+ if (threadId) return threadId;
6912
+ const thread = asRecord5(record.thread);
6913
+ if (thread && typeof thread.id === "string") return thread.id;
6914
+ const turn = asRecord5(record.turn);
6915
+ if (turn) {
6916
+ const turnThreadId = (typeof turn.threadId === "string" ? turn.threadId : "") || (typeof turn.thread_id === "string" ? turn.thread_id : "");
6917
+ if (turnThreadId) return turnThreadId;
6918
+ }
6919
+ return "";
6920
+ }
6921
+ function isTurnCompletedNotification(notification) {
6922
+ return notification.method === "turn/completed";
6923
+ }
6870
6924
  async function readFirstLaunchPluginsCardDismissed() {
6871
6925
  const statePath = getCodexGlobalStatePath();
6872
6926
  try {
@@ -7636,6 +7690,147 @@ var AppServerProcess = class {
7636
7690
  forceKillTimer.unref();
7637
7691
  }
7638
7692
  };
7693
+ var BackendQueueProcessor = class {
7694
+ constructor(appServer) {
7695
+ this.appServer = appServer;
7696
+ this.processingThreadIds = /* @__PURE__ */ new Set();
7697
+ this.unsubscribe = appServer.onNotification((notification) => {
7698
+ if (!isTurnCompletedNotification(notification)) return;
7699
+ const threadId = extractThreadIdFromNotificationParams(notification.params);
7700
+ if (!threadId) return;
7701
+ void this.processThreadQueue(threadId);
7702
+ });
7703
+ }
7704
+ dispose() {
7705
+ this.unsubscribe();
7706
+ this.processingThreadIds.clear();
7707
+ }
7708
+ async processThreadQueue(threadId) {
7709
+ if (this.processingThreadIds.has(threadId)) return;
7710
+ this.processingThreadIds.add(threadId);
7711
+ try {
7712
+ const next = await this.popNextQueuedTurn(threadId);
7713
+ if (!next) return;
7714
+ try {
7715
+ await this.startQueuedTurn(next);
7716
+ } catch {
7717
+ await this.restoreQueuedTurn(next);
7718
+ }
7719
+ } catch {
7720
+ } finally {
7721
+ this.processingThreadIds.delete(threadId);
7722
+ }
7723
+ }
7724
+ async popNextQueuedTurn(threadId) {
7725
+ const state = await readThreadQueueState();
7726
+ const queue = state[threadId];
7727
+ if (!queue || queue.length === 0) return null;
7728
+ const [message, ...rest] = queue;
7729
+ const nextState = { ...state };
7730
+ if (rest.length > 0) {
7731
+ nextState[threadId] = rest;
7732
+ } else {
7733
+ delete nextState[threadId];
7734
+ }
7735
+ await writeThreadQueueState(nextState);
7736
+ return { threadId, message };
7737
+ }
7738
+ async restoreQueuedTurn(turn) {
7739
+ const state = await readThreadQueueState();
7740
+ const queue = state[turn.threadId] ?? [];
7741
+ await writeThreadQueueState({
7742
+ ...state,
7743
+ [turn.threadId]: [turn.message, ...queue]
7744
+ });
7745
+ }
7746
+ async resolveCollaborationModeSettings(mode) {
7747
+ let currentConfig = null;
7748
+ try {
7749
+ const configPayload = asRecord5(await this.appServer.rpc("config/read", {}));
7750
+ currentConfig = asRecord5(configPayload?.config);
7751
+ } catch {
7752
+ currentConfig = null;
7753
+ }
7754
+ const configuredModel = readNonEmptyString(currentConfig?.model);
7755
+ if (configuredModel) {
7756
+ return {
7757
+ model: configuredModel,
7758
+ reasoningEffort: normalizeCollaborationModeReasoningEffort(normalizeReasoningEffort(currentConfig?.model_reasoning_effort))
7759
+ };
7760
+ }
7761
+ try {
7762
+ const modelsPayload = asRecord5(await this.appServer.rpc("model/list", {}));
7763
+ const models = Array.isArray(modelsPayload?.data) ? modelsPayload.data : [];
7764
+ for (const row of models) {
7765
+ const record = asRecord5(row);
7766
+ const candidate = readNonEmptyString(record?.id) || readNonEmptyString(record?.model);
7767
+ if (candidate) {
7768
+ return {
7769
+ model: candidate,
7770
+ reasoningEffort: normalizeCollaborationModeReasoningEffort(normalizeReasoningEffort(currentConfig?.model_reasoning_effort))
7771
+ };
7772
+ }
7773
+ }
7774
+ } catch {
7775
+ }
7776
+ throw new Error(`${mode === "plan" ? "Plan" : "Default"} mode requires an available model.`);
7777
+ }
7778
+ async buildQueuedTurnParams(turn) {
7779
+ const localImageAttachments = [];
7780
+ for (const imageUrl of turn.message.imageUrls) {
7781
+ const localImagePath = extractLocalImagePathFromUrl(imageUrl.trim());
7782
+ if (!localImagePath) continue;
7783
+ localImageAttachments.push({
7784
+ label: fileNameFromPath(localImagePath),
7785
+ path: localImagePath,
7786
+ fsPath: localImagePath
7787
+ });
7788
+ }
7789
+ const allFileAttachments = [...turn.message.fileAttachments, ...localImageAttachments];
7790
+ const dedupedFileAttachments = allFileAttachments.filter((entry, index) => allFileAttachments.findIndex((candidate) => candidate.fsPath === entry.fsPath) === index);
7791
+ const input = [{
7792
+ type: "text",
7793
+ text: buildTextWithAttachments(turn.message.text, dedupedFileAttachments)
7794
+ }];
7795
+ for (const imageUrl of turn.message.imageUrls) {
7796
+ const normalizedUrl = imageUrl.trim();
7797
+ if (!normalizedUrl) continue;
7798
+ const localImagePath = extractLocalImagePathFromUrl(normalizedUrl);
7799
+ if (localImagePath) {
7800
+ input.push({ type: "localImage", path: localImagePath });
7801
+ } else {
7802
+ input.push({ type: "image", url: normalizedUrl, image_url: normalizedUrl });
7803
+ }
7804
+ }
7805
+ for (const skill of turn.message.skills) {
7806
+ input.push({ type: "skill", name: skill.name, path: skill.path });
7807
+ }
7808
+ const params = {
7809
+ threadId: turn.threadId,
7810
+ input
7811
+ };
7812
+ if (dedupedFileAttachments.length > 0) {
7813
+ params.attachments = dedupedFileAttachments.map((f) => ({ label: f.label, path: f.path, fsPath: f.fsPath }));
7814
+ }
7815
+ try {
7816
+ const settings = await this.resolveCollaborationModeSettings(turn.message.collaborationMode);
7817
+ params.collaborationMode = {
7818
+ mode: turn.message.collaborationMode,
7819
+ settings: {
7820
+ model: settings.model,
7821
+ reasoning_effort: settings.reasoningEffort,
7822
+ developer_instructions: null
7823
+ }
7824
+ };
7825
+ } catch {
7826
+ }
7827
+ return params;
7828
+ }
7829
+ async startQueuedTurn(turn) {
7830
+ await this.appServer.rpc("thread/resume", { threadId: turn.threadId });
7831
+ await this.appServer.rpc("turn/start", await this.buildQueuedTurnParams(turn));
7832
+ }
7833
+ };
7639
7834
  var MethodCatalog = class {
7640
7835
  constructor() {
7641
7836
  this.methodCache = null;
@@ -7738,15 +7933,18 @@ function getSharedBridgeState() {
7738
7933
  return existing;
7739
7934
  }
7740
7935
  existing.appServer.dispose();
7936
+ existing.backendQueueProcessor?.dispose();
7741
7937
  existing.terminalManager?.dispose();
7742
7938
  }
7743
7939
  const appServer = new AppServerProcess();
7744
7940
  const terminalManager = new ThreadTerminalManager();
7941
+ const backendQueueProcessor = new BackendQueueProcessor(appServer);
7745
7942
  const created = {
7746
7943
  version: SHARED_BRIDGE_VERSION,
7747
7944
  appServer,
7748
7945
  terminalManager,
7749
7946
  methodCatalog: new MethodCatalog(),
7947
+ backendQueueProcessor,
7750
7948
  telegramBridge: new TelegramThreadBridge(appServer, {
7751
7949
  onChatSeen: (chatId) => {
7752
7950
  void rememberTelegramChatId(chatId).catch(() => {
@@ -7826,7 +8024,7 @@ async function buildThreadSearchIndex(appServer) {
7826
8024
  return { docsById };
7827
8025
  }
7828
8026
  function createCodexBridgeMiddleware() {
7829
- const { appServer, terminalManager, methodCatalog, telegramBridge } = getSharedBridgeState();
8027
+ const { appServer, terminalManager, methodCatalog, telegramBridge, backendQueueProcessor } = getSharedBridgeState();
7830
8028
  let threadSearchIndex = null;
7831
8029
  let threadSearchIndexPromise = null;
7832
8030
  async function getThreadSearchIndex() {
@@ -9219,6 +9417,7 @@ data: ${JSON.stringify({ ok: true })}
9219
9417
  threadSearchIndex = null;
9220
9418
  telegramBridge.stop();
9221
9419
  terminalManager.dispose();
9420
+ backendQueueProcessor.dispose();
9222
9421
  appServer.dispose();
9223
9422
  };
9224
9423
  middleware.subscribeNotifications = (listener) => {