happy-coder 0.11.0 → 0.11.1-0
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-CnbpW8M_.cjs → index-BN1H_2wt.cjs} +3 -3
- package/dist/{index-DGSQ98ZI.mjs → index-DutM9a5s.mjs} +2 -2
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.mjs +1 -1
- package/dist/{runCodex-DGxLYcn4.mjs → runCodex-B3H8yB3Q.mjs} +97 -23
- package/dist/{runCodex-C72IQzVj.cjs → runCodex-BBqp_JVS.cjs} +97 -22
- package/dist/{types-B_jcUADp.mjs → types-0Hm6NOkj.mjs} +2 -2
- package/dist/{types-BTQ3mv47.cjs → types-D-P1Kg34.cjs} +3 -3
- package/package.json +2 -2
|
@@ -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-
|
|
6
|
+
var types = require('./types-D-P1Kg34.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-
|
|
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-BN1H_2wt.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-
|
|
5806
|
+
const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-BBqp_JVS.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-
|
|
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-0Hm6NOkj.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-
|
|
5784
|
+
const { runCodex } = await import('./runCodex-B3H8yB3Q.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
package/dist/index.mjs
CHANGED
package/dist/lib.cjs
CHANGED
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-
|
|
1
|
+
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-0Hm6NOkj.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-
|
|
3
|
+
import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, b as packageJson } from './types-0Hm6NOkj.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-
|
|
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-DutM9a5s.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
|
-
|
|
63
|
-
|
|
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
|
-
|
|
138
|
-
this.
|
|
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
|
-
|
|
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
|
-
|
|
158
|
-
if (
|
|
159
|
-
|
|
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
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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-
|
|
5
|
+
var types = require('./types-D-P1Kg34.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-
|
|
11
|
+
var index = require('./index-BN1H_2wt.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
|
-
|
|
65
|
-
|
|
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
|
-
|
|
140
|
-
this.
|
|
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
|
-
|
|
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
|
-
|
|
160
|
-
if (
|
|
161
|
-
|
|
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
|
-
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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;
|
|
@@ -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-0";
|
|
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
|
|
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",
|
|
@@ -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-0";
|
|
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
|
|
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-
|
|
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-D-P1Kg34.cjs', document.baseURI).href))));
|
|
1021
1021
|
function projectPath() {
|
|
1022
1022
|
const path$1 = path.resolve(__dirname$1, "..");
|
|
1023
1023
|
return path$1;
|
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-0",
|
|
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
|
|
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",
|