codexui-android 0.1.100 → 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-Cmr8liLe.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
@@ -5613,20 +5613,53 @@ async function startComposioLogin() {
5613
5613
  if (!command) {
5614
5614
  throw new Error("Composio CLI is not installed");
5615
5615
  }
5616
- const invocation = getSpawnInvocation(command, ["login", "-y"]);
5616
+ const invocation = getSpawnInvocation(command, ["login", "--no-browser", "-y"]);
5617
5617
  const proc = spawn4(invocation.command, invocation.args, {
5618
5618
  cwd: process.cwd(),
5619
5619
  env: process.env,
5620
5620
  detached: true,
5621
- stdio: "ignore",
5621
+ stdio: ["ignore", "pipe", "pipe"],
5622
5622
  windowsHide: true
5623
5623
  });
5624
5624
  proc.unref();
5625
+ let stdout = "";
5626
+ let stderr = "";
5627
+ proc.stdout.setEncoding("utf8");
5628
+ proc.stderr.setEncoding("utf8");
5629
+ proc.stderr.on("data", (chunk) => {
5630
+ stderr += chunk;
5631
+ });
5632
+ const loginUrl = await new Promise((resolveLoginUrl, reject) => {
5633
+ const timeout = setTimeout(() => {
5634
+ proc.kill("SIGTERM");
5635
+ reject(new Error(stderr.trim() || stdout.trim() || "Timed out waiting for Composio CLI login URL"));
5636
+ }, 1e4);
5637
+ const finish = (url) => {
5638
+ clearTimeout(timeout);
5639
+ proc.stdout.destroy();
5640
+ proc.stderr.destroy();
5641
+ resolveLoginUrl(url);
5642
+ };
5643
+ proc.once("error", (error) => {
5644
+ clearTimeout(timeout);
5645
+ reject(error);
5646
+ });
5647
+ proc.once("close", (code) => {
5648
+ clearTimeout(timeout);
5649
+ reject(new Error(stderr.trim() || stdout.trim() || `Composio CLI login exited with code ${code ?? 0}`));
5650
+ });
5651
+ proc.stdout.on("data", (chunk) => {
5652
+ stdout += chunk;
5653
+ const url = stdout.match(/https?:\/\/\S+/)?.[0] ?? "";
5654
+ if (url) finish(url);
5655
+ });
5656
+ });
5657
+ const cliKey = loginUrl ? new URL(loginUrl).searchParams.get("cliKey") ?? "" : "";
5625
5658
  return {
5626
5659
  status: "started",
5627
- message: "Composio CLI login started",
5628
- loginUrl: "",
5629
- cliKey: "",
5660
+ message: "Composio CLI login URL created",
5661
+ loginUrl,
5662
+ cliKey,
5630
5663
  expiresAt: ""
5631
5664
  };
5632
5665
  }
@@ -6834,6 +6867,60 @@ async function writeThreadQueueState(nextState) {
6834
6867
  }
6835
6868
  await writeFile4(statePath, JSON.stringify(payload), "utf8");
6836
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
+ }
6837
6924
  async function readFirstLaunchPluginsCardDismissed() {
6838
6925
  const statePath = getCodexGlobalStatePath();
6839
6926
  try {
@@ -7603,6 +7690,147 @@ var AppServerProcess = class {
7603
7690
  forceKillTimer.unref();
7604
7691
  }
7605
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
+ };
7606
7834
  var MethodCatalog = class {
7607
7835
  constructor() {
7608
7836
  this.methodCache = null;
@@ -7705,15 +7933,18 @@ function getSharedBridgeState() {
7705
7933
  return existing;
7706
7934
  }
7707
7935
  existing.appServer.dispose();
7936
+ existing.backendQueueProcessor?.dispose();
7708
7937
  existing.terminalManager?.dispose();
7709
7938
  }
7710
7939
  const appServer = new AppServerProcess();
7711
7940
  const terminalManager = new ThreadTerminalManager();
7941
+ const backendQueueProcessor = new BackendQueueProcessor(appServer);
7712
7942
  const created = {
7713
7943
  version: SHARED_BRIDGE_VERSION,
7714
7944
  appServer,
7715
7945
  terminalManager,
7716
7946
  methodCatalog: new MethodCatalog(),
7947
+ backendQueueProcessor,
7717
7948
  telegramBridge: new TelegramThreadBridge(appServer, {
7718
7949
  onChatSeen: (chatId) => {
7719
7950
  void rememberTelegramChatId(chatId).catch(() => {
@@ -7793,7 +8024,7 @@ async function buildThreadSearchIndex(appServer) {
7793
8024
  return { docsById };
7794
8025
  }
7795
8026
  function createCodexBridgeMiddleware() {
7796
- const { appServer, terminalManager, methodCatalog, telegramBridge } = getSharedBridgeState();
8027
+ const { appServer, terminalManager, methodCatalog, telegramBridge, backendQueueProcessor } = getSharedBridgeState();
7797
8028
  let threadSearchIndex = null;
7798
8029
  let threadSearchIndexPromise = null;
7799
8030
  async function getThreadSearchIndex() {
@@ -9186,6 +9417,7 @@ data: ${JSON.stringify({ ok: true })}
9186
9417
  threadSearchIndex = null;
9187
9418
  telegramBridge.stop();
9188
9419
  terminalManager.dispose();
9420
+ backendQueueProcessor.dispose();
9189
9421
  appServer.dispose();
9190
9422
  };
9191
9423
  middleware.subscribeNotifications = (listener) => {