happy-coder 0.11.0 → 0.11.1

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.
@@ -3,7 +3,7 @@
3
3
  var chalk = require('chalk');
4
4
  var os = require('node:os');
5
5
  var node_crypto = require('node:crypto');
6
- var types = require('./types-BTQ3mv47.cjs');
6
+ var types = require('./types-CLqX6MO0.cjs');
7
7
  var node_child_process = require('node:child_process');
8
8
  var node_path = require('node:path');
9
9
  var node_readline = require('node:readline');
@@ -981,7 +981,7 @@ class AbortError extends Error {
981
981
  }
982
982
  }
983
983
 
984
- const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CnbpW8M_.cjs', document.baseURI).href)));
984
+ const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-BiTPY0Al.cjs', document.baseURI).href)));
985
985
  const __dirname$1 = node_path.join(__filename$1, "..");
986
986
  function getDefaultClaudeCodePath() {
987
987
  return node_path.join(__dirname$1, "..", "..", "..", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
@@ -5803,7 +5803,7 @@ async function handleConnectVendor(vendor, displayName) {
5803
5803
  return;
5804
5804
  } else if (subcommand === "codex") {
5805
5805
  try {
5806
- const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-C72IQzVj.cjs'); });
5806
+ const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-DPfGXNTG.cjs'); });
5807
5807
  let startedBy = void 0;
5808
5808
  for (let i = 1; i < args.length; i++) {
5809
5809
  if (args[i] === "--started-by") {
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import os$1, { homedir } from 'node:os';
3
3
  import { randomUUID, randomBytes } from 'node:crypto';
4
- import { l as logger, p as projectPath, d as backoff, e as delay, R as RawJSONLinesSchema, f as AsyncLock, g as readDaemonState, h as clearDaemonState, b as packageJson, c as configuration, r as readSettings, i as readCredentials, j as encodeBase64, u as updateSettings, k as encodeBase64Url, m as decodeBase64, w as writeCredentialsLegacy, n as writeCredentialsDataKey, o as acquireDaemonLock, q as writeDaemonState, A as ApiClient, s as releaseDaemonLock, t as clearCredentials, v as clearMachineId, x as getLatestDaemonLog } from './types-B_jcUADp.mjs';
4
+ import { l as logger, p as projectPath, d as backoff, e as delay, R as RawJSONLinesSchema, f as AsyncLock, g as readDaemonState, h as clearDaemonState, b as packageJson, c as configuration, r as readSettings, i as readCredentials, j as encodeBase64, u as updateSettings, k as encodeBase64Url, m as decodeBase64, w as writeCredentialsLegacy, n as writeCredentialsDataKey, o as acquireDaemonLock, q as writeDaemonState, A as ApiClient, s as releaseDaemonLock, t as clearCredentials, v as clearMachineId, x as getLatestDaemonLog } from './types-CcqgHf_D.mjs';
5
5
  import { spawn, execSync, execFileSync } from 'node:child_process';
6
6
  import { resolve, join } from 'node:path';
7
7
  import { createInterface } from 'node:readline';
@@ -5781,7 +5781,7 @@ async function handleConnectVendor(vendor, displayName) {
5781
5781
  return;
5782
5782
  } else if (subcommand === "codex") {
5783
5783
  try {
5784
- const { runCodex } = await import('./runCodex-DGxLYcn4.mjs');
5784
+ const { runCodex } = await import('./runCodex-DJP0Q2zV.mjs');
5785
5785
  let startedBy = void 0;
5786
5786
  for (let i = 1; i < args.length; i++) {
5787
5787
  if (args[i] === "--started-by") {
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-CnbpW8M_.cjs');
5
- require('./types-BTQ3mv47.cjs');
4
+ require('./index-BiTPY0Al.cjs');
5
+ require('./types-CLqX6MO0.cjs');
6
6
  require('zod');
7
7
  require('node:child_process');
8
8
  require('node:os');
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'chalk';
2
- import './index-DGSQ98ZI.mjs';
3
- import './types-B_jcUADp.mjs';
2
+ import './index-SvbP5WOt.mjs';
3
+ import './types-CcqgHf_D.mjs';
4
4
  import 'zod';
5
5
  import 'node:child_process';
6
6
  import 'node:os';
package/dist/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var types = require('./types-BTQ3mv47.cjs');
3
+ var types = require('./types-CLqX6MO0.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('fs');
package/dist/lib.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-B_jcUADp.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-CcqgHf_D.mjs';
2
2
  import 'axios';
3
3
  import 'chalk';
4
4
  import 'fs';
@@ -1,12 +1,12 @@
1
1
  import { useStdout, useInput, Box, Text, render } from 'ink';
2
2
  import React, { useState, useRef, useEffect, useCallback } from 'react';
3
- import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, b as packageJson } from './types-B_jcUADp.mjs';
3
+ import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, b as packageJson } from './types-CcqgHf_D.mjs';
4
4
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
5
5
  import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
6
6
  import { z } from 'zod';
7
7
  import { ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js';
8
8
  import { randomUUID } from 'node:crypto';
9
- import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler, a as MessageBuffer, s as startHappyServer, t as trimIdent, b as stopCaffeinate } from './index-DGSQ98ZI.mjs';
9
+ import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler, a as MessageBuffer, s as startHappyServer, t as trimIdent, b as stopCaffeinate } from './index-SvbP5WOt.mjs';
10
10
  import os from 'node:os';
11
11
  import { resolve, join } from 'node:path';
12
12
  import fs from 'node:fs';
@@ -46,6 +46,7 @@ class CodexMcpClient {
46
46
  transport = null;
47
47
  connected = false;
48
48
  sessionId = null;
49
+ conversationId = null;
49
50
  handler = null;
50
51
  permissionHandler = null;
51
52
  constructor() {
@@ -59,10 +60,9 @@ class CodexMcpClient {
59
60
  msg: z.any()
60
61
  })
61
62
  }).passthrough(), (data) => {
62
- if (data.params.msg.type === "session_configured") {
63
- this.sessionId = data.params.msg.session_id;
64
- }
65
- this.handler?.(data.params.msg);
63
+ const msg = data.params.msg;
64
+ this.updateIdentifiersFromEvent(msg);
65
+ this.handler?.(msg);
66
66
  });
67
67
  }
68
68
  setHandler(handler) {
@@ -134,8 +134,8 @@ class CodexMcpClient {
134
134
  timeout: DEFAULT_TIMEOUT
135
135
  // maxTotalTimeout: 10000000000
136
136
  });
137
- console.log("[CodexMCP] Response:", response);
138
- this.extractSessionId(response);
137
+ logger.debug("[CodexMCP] startSession response:", response);
138
+ this.extractIdentifiers(response);
139
139
  return response;
140
140
  }
141
141
  async continueSession(prompt, options) {
@@ -143,7 +143,11 @@ class CodexMcpClient {
143
143
  if (!this.sessionId) {
144
144
  throw new Error("No active session. Call startSession first.");
145
145
  }
146
- const args = { sessionId: this.sessionId, prompt };
146
+ if (!this.conversationId) {
147
+ this.conversationId = this.sessionId;
148
+ logger.debug("[CodexMCP] conversationId missing, defaulting to sessionId:", this.conversationId);
149
+ }
150
+ const args = { sessionId: this.sessionId, conversationId: this.conversationId, prompt };
147
151
  logger.debug("[CodexMCP] Continuing Codex session:", args);
148
152
  const response = await this.client.callTool({
149
153
  name: "codex-reply",
@@ -152,24 +156,57 @@ class CodexMcpClient {
152
156
  signal: options?.signal,
153
157
  timeout: DEFAULT_TIMEOUT
154
158
  });
159
+ logger.debug("[CodexMCP] continueSession response:", response);
160
+ this.extractIdentifiers(response);
155
161
  return response;
156
162
  }
157
- extractSessionId(response) {
158
- if (response?.meta?.sessionId) {
159
- this.sessionId = response.meta.sessionId;
163
+ updateIdentifiersFromEvent(event) {
164
+ if (!event || typeof event !== "object") {
165
+ return;
166
+ }
167
+ const candidates = [event];
168
+ if (event.data && typeof event.data === "object") {
169
+ candidates.push(event.data);
170
+ }
171
+ for (const candidate of candidates) {
172
+ const sessionId = candidate.session_id ?? candidate.sessionId;
173
+ if (sessionId) {
174
+ this.sessionId = sessionId;
175
+ logger.debug("[CodexMCP] Session ID extracted from event:", this.sessionId);
176
+ }
177
+ const conversationId = candidate.conversation_id ?? candidate.conversationId;
178
+ if (conversationId) {
179
+ this.conversationId = conversationId;
180
+ logger.debug("[CodexMCP] Conversation ID extracted from event:", this.conversationId);
181
+ }
182
+ }
183
+ }
184
+ extractIdentifiers(response) {
185
+ const meta = response?.meta || {};
186
+ if (meta.sessionId) {
187
+ this.sessionId = meta.sessionId;
160
188
  logger.debug("[CodexMCP] Session ID extracted:", this.sessionId);
161
189
  } else if (response?.sessionId) {
162
190
  this.sessionId = response.sessionId;
163
191
  logger.debug("[CodexMCP] Session ID extracted:", this.sessionId);
164
- } else {
165
- const content = response?.content;
166
- if (Array.isArray(content)) {
167
- for (const item of content) {
168
- if (item?.sessionId) {
169
- this.sessionId = item.sessionId;
170
- logger.debug("[CodexMCP] Session ID extracted from content:", this.sessionId);
171
- break;
172
- }
192
+ }
193
+ if (meta.conversationId) {
194
+ this.conversationId = meta.conversationId;
195
+ logger.debug("[CodexMCP] Conversation ID extracted:", this.conversationId);
196
+ } else if (response?.conversationId) {
197
+ this.conversationId = response.conversationId;
198
+ logger.debug("[CodexMCP] Conversation ID extracted:", this.conversationId);
199
+ }
200
+ const content = response?.content;
201
+ if (Array.isArray(content)) {
202
+ for (const item of content) {
203
+ if (!this.sessionId && item?.sessionId) {
204
+ this.sessionId = item.sessionId;
205
+ logger.debug("[CodexMCP] Session ID extracted from content:", this.sessionId);
206
+ }
207
+ if (!this.conversationId && item && typeof item === "object" && "conversationId" in item && item.conversationId) {
208
+ this.conversationId = item.conversationId;
209
+ logger.debug("[CodexMCP] Conversation ID extracted from content:", this.conversationId);
173
210
  }
174
211
  }
175
212
  }
@@ -183,6 +220,7 @@ class CodexMcpClient {
183
220
  clearSession() {
184
221
  const previousSessionId = this.sessionId;
185
222
  this.sessionId = null;
223
+ this.conversationId = null;
186
224
  logger.debug("[CodexMCP] Session cleared, previous sessionId:", previousSessionId);
187
225
  }
188
226
  /**
@@ -223,6 +261,7 @@ class CodexMcpClient {
223
261
  this.transport = null;
224
262
  this.connected = false;
225
263
  this.sessionId = null;
264
+ this.conversationId = null;
226
265
  logger.debug("[CodexMCP] Disconnected");
227
266
  }
228
267
  }
@@ -685,6 +724,20 @@ const CodexDisplay = ({ messageBuffer, logPath, onExit }) => {
685
724
  ));
686
725
  };
687
726
 
727
+ function emitReadyIfIdle({ pending, queueSize, shouldExit, sendReady, notify }) {
728
+ if (shouldExit) {
729
+ return false;
730
+ }
731
+ if (pending) {
732
+ return false;
733
+ }
734
+ if (queueSize() > 0) {
735
+ return false;
736
+ }
737
+ sendReady();
738
+ notify?.();
739
+ return true;
740
+ }
688
741
  async function runCodex(opts) {
689
742
  const sessionTag = randomUUID();
690
743
  const api = await ApiClient.create(opts.credentials);
@@ -773,6 +826,18 @@ async function runCodex(opts) {
773
826
  const keepAliveInterval = setInterval(() => {
774
827
  session.keepAlive(thinking, "remote");
775
828
  }, 2e3);
829
+ const sendReady = () => {
830
+ session.sendSessionEvent({ type: "ready" });
831
+ try {
832
+ api.push().sendToAllDevices(
833
+ "It's ready!",
834
+ "Codex is waiting for your command",
835
+ { sessionId: session.sessionId }
836
+ );
837
+ } catch (pushError) {
838
+ logger.debug("[Codex] Failed to send ready push", pushError);
839
+ }
840
+ };
776
841
  function logActiveHandles(tag) {
777
842
  if (!process.env.DEBUG) return;
778
843
  const anyProc = process;
@@ -927,8 +992,10 @@ async function runCodex(opts) {
927
992
  messageBuffer.addMessage("Starting task...", "status");
928
993
  } else if (msg.type === "task_complete") {
929
994
  messageBuffer.addMessage("Task completed", "status");
995
+ sendReady();
930
996
  } else if (msg.type === "turn_aborted") {
931
997
  messageBuffer.addMessage("Turn aborted", "status");
998
+ sendReady();
932
999
  }
933
1000
  if (msg.type === "task_started") {
934
1001
  if (!thinking) {
@@ -1153,10 +1220,11 @@ async function runCodex(opts) {
1153
1220
  wasCreated = true;
1154
1221
  first = false;
1155
1222
  } else {
1156
- await client.continueSession(
1223
+ const response2 = await client.continueSession(
1157
1224
  message.message,
1158
1225
  { signal: abortController.signal }
1159
1226
  );
1227
+ logger.debug("[Codex] continueSession response:", response2);
1160
1228
  }
1161
1229
  } catch (error) {
1162
1230
  logger.warn("Error in codex session:", error);
@@ -1181,6 +1249,12 @@ async function runCodex(opts) {
1181
1249
  diffProcessor.reset();
1182
1250
  thinking = false;
1183
1251
  session.keepAlive(thinking, "remote");
1252
+ emitReadyIfIdle({
1253
+ pending,
1254
+ queueSize: () => messageQueue.size(),
1255
+ shouldExit,
1256
+ sendReady
1257
+ });
1184
1258
  logActiveHandles("after-turn");
1185
1259
  }
1186
1260
  }
@@ -1230,4 +1304,4 @@ async function runCodex(opts) {
1230
1304
  }
1231
1305
  }
1232
1306
 
1233
- export { runCodex };
1307
+ export { emitReadyIfIdle, runCodex };
@@ -2,13 +2,13 @@
2
2
 
3
3
  var ink = require('ink');
4
4
  var React = require('react');
5
- var types = require('./types-BTQ3mv47.cjs');
5
+ var types = require('./types-CLqX6MO0.cjs');
6
6
  var index_js = require('@modelcontextprotocol/sdk/client/index.js');
7
7
  var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
8
8
  var z = require('zod');
9
9
  var types_js = require('@modelcontextprotocol/sdk/types.js');
10
10
  var node_crypto = require('node:crypto');
11
- var index = require('./index-CnbpW8M_.cjs');
11
+ var index = require('./index-BiTPY0Al.cjs');
12
12
  var os = require('node:os');
13
13
  var node_path = require('node:path');
14
14
  var fs = require('node:fs');
@@ -48,6 +48,7 @@ class CodexMcpClient {
48
48
  transport = null;
49
49
  connected = false;
50
50
  sessionId = null;
51
+ conversationId = null;
51
52
  handler = null;
52
53
  permissionHandler = null;
53
54
  constructor() {
@@ -61,10 +62,9 @@ class CodexMcpClient {
61
62
  msg: z.z.any()
62
63
  })
63
64
  }).passthrough(), (data) => {
64
- if (data.params.msg.type === "session_configured") {
65
- this.sessionId = data.params.msg.session_id;
66
- }
67
- this.handler?.(data.params.msg);
65
+ const msg = data.params.msg;
66
+ this.updateIdentifiersFromEvent(msg);
67
+ this.handler?.(msg);
68
68
  });
69
69
  }
70
70
  setHandler(handler) {
@@ -136,8 +136,8 @@ class CodexMcpClient {
136
136
  timeout: DEFAULT_TIMEOUT
137
137
  // maxTotalTimeout: 10000000000
138
138
  });
139
- console.log("[CodexMCP] Response:", response);
140
- this.extractSessionId(response);
139
+ types.logger.debug("[CodexMCP] startSession response:", response);
140
+ this.extractIdentifiers(response);
141
141
  return response;
142
142
  }
143
143
  async continueSession(prompt, options) {
@@ -145,7 +145,11 @@ class CodexMcpClient {
145
145
  if (!this.sessionId) {
146
146
  throw new Error("No active session. Call startSession first.");
147
147
  }
148
- const args = { sessionId: this.sessionId, prompt };
148
+ if (!this.conversationId) {
149
+ this.conversationId = this.sessionId;
150
+ types.logger.debug("[CodexMCP] conversationId missing, defaulting to sessionId:", this.conversationId);
151
+ }
152
+ const args = { sessionId: this.sessionId, conversationId: this.conversationId, prompt };
149
153
  types.logger.debug("[CodexMCP] Continuing Codex session:", args);
150
154
  const response = await this.client.callTool({
151
155
  name: "codex-reply",
@@ -154,24 +158,57 @@ class CodexMcpClient {
154
158
  signal: options?.signal,
155
159
  timeout: DEFAULT_TIMEOUT
156
160
  });
161
+ types.logger.debug("[CodexMCP] continueSession response:", response);
162
+ this.extractIdentifiers(response);
157
163
  return response;
158
164
  }
159
- extractSessionId(response) {
160
- if (response?.meta?.sessionId) {
161
- this.sessionId = response.meta.sessionId;
165
+ updateIdentifiersFromEvent(event) {
166
+ if (!event || typeof event !== "object") {
167
+ return;
168
+ }
169
+ const candidates = [event];
170
+ if (event.data && typeof event.data === "object") {
171
+ candidates.push(event.data);
172
+ }
173
+ for (const candidate of candidates) {
174
+ const sessionId = candidate.session_id ?? candidate.sessionId;
175
+ if (sessionId) {
176
+ this.sessionId = sessionId;
177
+ types.logger.debug("[CodexMCP] Session ID extracted from event:", this.sessionId);
178
+ }
179
+ const conversationId = candidate.conversation_id ?? candidate.conversationId;
180
+ if (conversationId) {
181
+ this.conversationId = conversationId;
182
+ types.logger.debug("[CodexMCP] Conversation ID extracted from event:", this.conversationId);
183
+ }
184
+ }
185
+ }
186
+ extractIdentifiers(response) {
187
+ const meta = response?.meta || {};
188
+ if (meta.sessionId) {
189
+ this.sessionId = meta.sessionId;
162
190
  types.logger.debug("[CodexMCP] Session ID extracted:", this.sessionId);
163
191
  } else if (response?.sessionId) {
164
192
  this.sessionId = response.sessionId;
165
193
  types.logger.debug("[CodexMCP] Session ID extracted:", this.sessionId);
166
- } else {
167
- const content = response?.content;
168
- if (Array.isArray(content)) {
169
- for (const item of content) {
170
- if (item?.sessionId) {
171
- this.sessionId = item.sessionId;
172
- types.logger.debug("[CodexMCP] Session ID extracted from content:", this.sessionId);
173
- break;
174
- }
194
+ }
195
+ if (meta.conversationId) {
196
+ this.conversationId = meta.conversationId;
197
+ types.logger.debug("[CodexMCP] Conversation ID extracted:", this.conversationId);
198
+ } else if (response?.conversationId) {
199
+ this.conversationId = response.conversationId;
200
+ types.logger.debug("[CodexMCP] Conversation ID extracted:", this.conversationId);
201
+ }
202
+ const content = response?.content;
203
+ if (Array.isArray(content)) {
204
+ for (const item of content) {
205
+ if (!this.sessionId && item?.sessionId) {
206
+ this.sessionId = item.sessionId;
207
+ types.logger.debug("[CodexMCP] Session ID extracted from content:", this.sessionId);
208
+ }
209
+ if (!this.conversationId && item && typeof item === "object" && "conversationId" in item && item.conversationId) {
210
+ this.conversationId = item.conversationId;
211
+ types.logger.debug("[CodexMCP] Conversation ID extracted from content:", this.conversationId);
175
212
  }
176
213
  }
177
214
  }
@@ -185,6 +222,7 @@ class CodexMcpClient {
185
222
  clearSession() {
186
223
  const previousSessionId = this.sessionId;
187
224
  this.sessionId = null;
225
+ this.conversationId = null;
188
226
  types.logger.debug("[CodexMCP] Session cleared, previous sessionId:", previousSessionId);
189
227
  }
190
228
  /**
@@ -225,6 +263,7 @@ class CodexMcpClient {
225
263
  this.transport = null;
226
264
  this.connected = false;
227
265
  this.sessionId = null;
266
+ this.conversationId = null;
228
267
  types.logger.debug("[CodexMCP] Disconnected");
229
268
  }
230
269
  }
@@ -687,6 +726,20 @@ const CodexDisplay = ({ messageBuffer, logPath, onExit }) => {
687
726
  ));
688
727
  };
689
728
 
729
+ function emitReadyIfIdle({ pending, queueSize, shouldExit, sendReady, notify }) {
730
+ if (shouldExit) {
731
+ return false;
732
+ }
733
+ if (pending) {
734
+ return false;
735
+ }
736
+ if (queueSize() > 0) {
737
+ return false;
738
+ }
739
+ sendReady();
740
+ notify?.();
741
+ return true;
742
+ }
690
743
  async function runCodex(opts) {
691
744
  const sessionTag = node_crypto.randomUUID();
692
745
  const api = await types.ApiClient.create(opts.credentials);
@@ -775,6 +828,18 @@ async function runCodex(opts) {
775
828
  const keepAliveInterval = setInterval(() => {
776
829
  session.keepAlive(thinking, "remote");
777
830
  }, 2e3);
831
+ const sendReady = () => {
832
+ session.sendSessionEvent({ type: "ready" });
833
+ try {
834
+ api.push().sendToAllDevices(
835
+ "It's ready!",
836
+ "Codex is waiting for your command",
837
+ { sessionId: session.sessionId }
838
+ );
839
+ } catch (pushError) {
840
+ types.logger.debug("[Codex] Failed to send ready push", pushError);
841
+ }
842
+ };
778
843
  function logActiveHandles(tag) {
779
844
  if (!process.env.DEBUG) return;
780
845
  const anyProc = process;
@@ -929,8 +994,10 @@ async function runCodex(opts) {
929
994
  messageBuffer.addMessage("Starting task...", "status");
930
995
  } else if (msg.type === "task_complete") {
931
996
  messageBuffer.addMessage("Task completed", "status");
997
+ sendReady();
932
998
  } else if (msg.type === "turn_aborted") {
933
999
  messageBuffer.addMessage("Turn aborted", "status");
1000
+ sendReady();
934
1001
  }
935
1002
  if (msg.type === "task_started") {
936
1003
  if (!thinking) {
@@ -1155,10 +1222,11 @@ async function runCodex(opts) {
1155
1222
  wasCreated = true;
1156
1223
  first = false;
1157
1224
  } else {
1158
- await client.continueSession(
1225
+ const response2 = await client.continueSession(
1159
1226
  message.message,
1160
1227
  { signal: abortController.signal }
1161
1228
  );
1229
+ types.logger.debug("[Codex] continueSession response:", response2);
1162
1230
  }
1163
1231
  } catch (error) {
1164
1232
  types.logger.warn("Error in codex session:", error);
@@ -1183,6 +1251,12 @@ async function runCodex(opts) {
1183
1251
  diffProcessor.reset();
1184
1252
  thinking = false;
1185
1253
  session.keepAlive(thinking, "remote");
1254
+ emitReadyIfIdle({
1255
+ pending,
1256
+ queueSize: () => messageQueue.size(),
1257
+ shouldExit,
1258
+ sendReady
1259
+ });
1186
1260
  logActiveHandles("after-turn");
1187
1261
  }
1188
1262
  }
@@ -1232,4 +1306,5 @@ async function runCodex(opts) {
1232
1306
  }
1233
1307
  }
1234
1308
 
1309
+ exports.emitReadyIfIdle = emitReadyIfIdle;
1235
1310
  exports.runCodex = runCodex;
@@ -42,7 +42,7 @@ function _interopNamespaceDefault(e) {
42
42
  var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
43
43
 
44
44
  var name = "happy-coder";
45
- var version = "0.11.0";
45
+ var version = "0.11.1";
46
46
  var description = "Mobile and Web client for Claude Code and Codex";
47
47
  var author = "Kirill Dubovitskiy";
48
48
  var license = "MIT";
@@ -102,7 +102,7 @@ var scripts = {
102
102
  build: "shx rm -rf dist && npx tsc --noEmit && pkgroll",
103
103
  test: "yarn build && tsx --env-file .env.integration-test node_modules/.bin/vitest run",
104
104
  start: "yarn build && ./bin/happy.mjs",
105
- dev: "tsx --env-file .env.dev src/index.ts",
105
+ dev: "tsx src/index.ts",
106
106
  "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
107
107
  "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
108
108
  prepublishOnly: "yarn build && yarn test",
@@ -1017,7 +1017,7 @@ class RpcHandlerManager {
1017
1017
  }
1018
1018
  }
1019
1019
 
1020
- const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-BTQ3mv47.cjs', document.baseURI).href))));
1020
+ const __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-CLqX6MO0.cjs', document.baseURI).href))));
1021
1021
  function projectPath() {
1022
1022
  const path$1 = path.resolve(__dirname$1, "..");
1023
1023
  return path$1;
@@ -21,7 +21,7 @@ import { platform } from 'os';
21
21
  import { Expo } from 'expo-server-sdk';
22
22
 
23
23
  var name = "happy-coder";
24
- var version = "0.11.0";
24
+ var version = "0.11.1";
25
25
  var description = "Mobile and Web client for Claude Code and Codex";
26
26
  var author = "Kirill Dubovitskiy";
27
27
  var license = "MIT";
@@ -81,7 +81,7 @@ var scripts = {
81
81
  build: "shx rm -rf dist && npx tsc --noEmit && pkgroll",
82
82
  test: "yarn build && tsx --env-file .env.integration-test node_modules/.bin/vitest run",
83
83
  start: "yarn build && ./bin/happy.mjs",
84
- dev: "tsx --env-file .env.dev src/index.ts",
84
+ dev: "tsx src/index.ts",
85
85
  "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
86
86
  "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
87
87
  prepublishOnly: "yarn build && yarn test",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happy-coder",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Mobile and Web client for Claude Code and Codex",
5
5
  "author": "Kirill Dubovitskiy",
6
6
  "license": "MIT",
@@ -60,7 +60,7 @@
60
60
  "build": "shx rm -rf dist && npx tsc --noEmit && pkgroll",
61
61
  "test": "yarn build && tsx --env-file .env.integration-test node_modules/.bin/vitest run",
62
62
  "start": "yarn build && ./bin/happy.mjs",
63
- "dev": "tsx --env-file .env.dev src/index.ts",
63
+ "dev": "tsx src/index.ts",
64
64
  "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
65
65
  "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
66
66
  "prepublishOnly": "yarn build && yarn test",