@makerbi/remodex 1.5.8 → 2.0.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.
- package/bin/remodex.js +56 -5
- package/package.json +1 -1
- package/src/bridge.js +85 -2
- package/src/desktop-ipc-action-follower.js +836 -3
- package/src/git-handler.js +92 -28
- package/src/ios-app-compatibility.js +7 -7
- package/src/macos-launch-agent.js +46 -1
- package/src/qr.js +2 -5
- package/src/rollout-live-mirror.js +159 -3
- package/src/secure-device-state.js +41 -2
- package/src/secure-transport.js +7 -0
- package/src/session-jsonl-history.js +54 -1
- package/src/voice-handler.js +33 -3
package/bin/remodex.js
CHANGED
|
@@ -120,7 +120,7 @@ async function main({
|
|
|
120
120
|
ok: true,
|
|
121
121
|
currentVersion: version,
|
|
122
122
|
plistPath: result?.plistPath,
|
|
123
|
-
pairingSession: result?.pairingSession,
|
|
123
|
+
pairingSession: sanitizePairingSessionForOutput(result?.pairingSession),
|
|
124
124
|
},
|
|
125
125
|
message: "[remodex] macOS bridge service is running.",
|
|
126
126
|
jsonOutput,
|
|
@@ -141,7 +141,7 @@ async function main({
|
|
|
141
141
|
ok: true,
|
|
142
142
|
currentVersion: version,
|
|
143
143
|
plistPath: result?.plistPath,
|
|
144
|
-
pairingSession: result?.pairingSession,
|
|
144
|
+
pairingSession: sanitizePairingSessionForOutput(result?.pairingSession),
|
|
145
145
|
},
|
|
146
146
|
message: "[remodex] macOS bridge service restarted.",
|
|
147
147
|
jsonOutput,
|
|
@@ -156,10 +156,20 @@ async function main({
|
|
|
156
156
|
consoleImpl,
|
|
157
157
|
exitImpl,
|
|
158
158
|
});
|
|
159
|
-
consoleImpl.log("[remodex] Refreshing bridge pairing QR...");
|
|
160
159
|
const result = await deps.startMacOSBridgeService({
|
|
161
160
|
waitForPairing: true,
|
|
162
161
|
});
|
|
162
|
+
if (jsonOutput) {
|
|
163
|
+
emitJson({
|
|
164
|
+
ok: true,
|
|
165
|
+
currentVersion: version,
|
|
166
|
+
plistPath: result?.plistPath,
|
|
167
|
+
pairingSession: sanitizePairingSessionForOutput(result?.pairingSession),
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
consoleImpl.log("[remodex] Refreshing bridge pairing QR...");
|
|
163
173
|
deps.printMacOSBridgePairingQr({
|
|
164
174
|
pairingSession: result.pairingSession,
|
|
165
175
|
});
|
|
@@ -193,7 +203,7 @@ async function main({
|
|
|
193
203
|
});
|
|
194
204
|
if (jsonOutput) {
|
|
195
205
|
emitJson({
|
|
196
|
-
...deps.getMacOSBridgeServiceStatus(),
|
|
206
|
+
...sanitizeBridgeServiceStatusForOutput(deps.getMacOSBridgeServiceStatus()),
|
|
197
207
|
currentVersion: version,
|
|
198
208
|
});
|
|
199
209
|
return;
|
|
@@ -272,7 +282,7 @@ async function main({
|
|
|
272
282
|
"Usage: remodex up | remodex run [--extra-device|--extra-devices=N] | remodex start | remodex restart | "
|
|
273
283
|
+ "remodex qr | remodex pair | remodex stop | remodex status | "
|
|
274
284
|
+ "remodex reset-pairing | remodex resume | remodex watch [threadId] | remodex --version | "
|
|
275
|
-
+ "append --json to start/restart/stop/status/reset-pairing/resume for machine-readable output"
|
|
285
|
+
+ "append --json to start/restart/qr/pair/stop/status/reset-pairing/resume for machine-readable output"
|
|
276
286
|
);
|
|
277
287
|
exitImpl(1);
|
|
278
288
|
}
|
|
@@ -361,6 +371,47 @@ function emitJson(payload) {
|
|
|
361
371
|
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
362
372
|
}
|
|
363
373
|
|
|
374
|
+
// Keeps machine-readable CLI output useful without exposing relay endpoints or live pairing payloads.
|
|
375
|
+
function sanitizeBridgeServiceStatusForOutput(status = {}) {
|
|
376
|
+
const sanitized = {
|
|
377
|
+
...status,
|
|
378
|
+
daemonConfig: sanitizeDaemonConfigForOutput(status.daemonConfig),
|
|
379
|
+
pairingSession: sanitizePairingSessionForOutput(status.pairingSession),
|
|
380
|
+
};
|
|
381
|
+
return sanitized;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function sanitizeDaemonConfigForOutput(config) {
|
|
385
|
+
if (!config || typeof config !== "object") {
|
|
386
|
+
return config || null;
|
|
387
|
+
}
|
|
388
|
+
const { relayUrl, pushServiceUrl, ...rest } = config;
|
|
389
|
+
return {
|
|
390
|
+
...rest,
|
|
391
|
+
relayConfigured: Boolean(relayUrl),
|
|
392
|
+
pushServiceConfigured: Boolean(pushServiceUrl),
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function sanitizePairingSessionForOutput(pairingSession) {
|
|
397
|
+
if (!pairingSession || typeof pairingSession !== "object") {
|
|
398
|
+
return pairingSession || null;
|
|
399
|
+
}
|
|
400
|
+
const payload = pairingSession.pairingPayload || {};
|
|
401
|
+
return {
|
|
402
|
+
createdAt: pairingSession.createdAt,
|
|
403
|
+
pairingCode: pairingSession.pairingCode,
|
|
404
|
+
pairingPayload: {
|
|
405
|
+
v: payload.v,
|
|
406
|
+
expiresAt: payload.expiresAt,
|
|
407
|
+
hasRelay: Boolean(payload.relay),
|
|
408
|
+
hasSessionId: Boolean(payload.sessionId),
|
|
409
|
+
hasMacIdentityPublicKey: Boolean(payload.macIdentityPublicKey),
|
|
410
|
+
displayName: payload.displayName,
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
364
415
|
function assertMacOSCommand(name, {
|
|
365
416
|
platform = process.platform,
|
|
366
417
|
consoleImpl = console,
|
package/package.json
CHANGED
package/src/bridge.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// Depends on: ws, crypto, os, ./bridge-status, ./codex-desktop-refresher, ./codex-transport, ./rollout-watch, ./voice-handler
|
|
6
6
|
|
|
7
7
|
const WebSocket = require("ws");
|
|
8
|
-
const { randomBytes, randomUUID } = require("crypto");
|
|
8
|
+
const { createHash, randomBytes, randomUUID } = require("crypto");
|
|
9
9
|
const { execFile, spawn } = require("child_process");
|
|
10
10
|
const fs = require("fs");
|
|
11
11
|
const path = require("path");
|
|
@@ -46,6 +46,7 @@ const { createPushNotificationTracker } = require("./push-notification-tracker")
|
|
|
46
46
|
const { resolveCodexGeneratedImagesRoot } = require("./codex-home");
|
|
47
47
|
const {
|
|
48
48
|
loadOrCreateBridgeDeviceState,
|
|
49
|
+
rememberLastSeenClientDeviceKind,
|
|
49
50
|
rememberLastSeenPhoneAppVersion,
|
|
50
51
|
resolveBridgeRelaySession,
|
|
51
52
|
} = require("./secure-device-state");
|
|
@@ -238,6 +239,7 @@ function startBridge({
|
|
|
238
239
|
requestId: null,
|
|
239
240
|
startedAt: 0,
|
|
240
241
|
};
|
|
242
|
+
let activePhoneSummary = null;
|
|
241
243
|
const secureTransport = createBridgeSecureTransport({
|
|
242
244
|
sessionId,
|
|
243
245
|
relayUrl: relayBaseUrl,
|
|
@@ -247,6 +249,13 @@ function startBridge({
|
|
|
247
249
|
deviceState = nextDeviceState;
|
|
248
250
|
sendRelayRegistrationUpdate(nextDeviceState);
|
|
249
251
|
},
|
|
252
|
+
onSecureSessionReady(session) {
|
|
253
|
+
activePhoneSummary = buildActivePhoneSummary(session, deviceState);
|
|
254
|
+
const lastPublishedBridgeStatus = bridgeStatusPublisher.latest();
|
|
255
|
+
if (lastPublishedBridgeStatus) {
|
|
256
|
+
publishBridgeStatus(lastPublishedBridgeStatus);
|
|
257
|
+
}
|
|
258
|
+
},
|
|
250
259
|
});
|
|
251
260
|
let primaryRelayChannel = null;
|
|
252
261
|
// Keeps one stable sender identity across reconnects so buffered replay state
|
|
@@ -420,6 +429,9 @@ function startBridge({
|
|
|
420
429
|
|
|
421
430
|
lastConnectionStatus = status;
|
|
422
431
|
lastConnectionError = lastError;
|
|
432
|
+
if (status !== "connected") {
|
|
433
|
+
activePhoneSummary = null;
|
|
434
|
+
}
|
|
423
435
|
publishBridgeStatus({
|
|
424
436
|
state: "running",
|
|
425
437
|
connectionStatus: status,
|
|
@@ -1529,6 +1541,20 @@ function startBridge({
|
|
|
1529
1541
|
function bridgeManagedInitializeCompatibilityError(params) {
|
|
1530
1542
|
const clientInfo = params && typeof params === "object" ? params.clientInfo : null;
|
|
1531
1543
|
const clientName = normalizeNonEmptyString(clientInfo?.name);
|
|
1544
|
+
const clientDeviceKind = classifyClientDeviceKind(clientName);
|
|
1545
|
+
if (clientDeviceKind) {
|
|
1546
|
+
deviceState = rememberLastSeenClientDeviceKind(deviceState, clientDeviceKind);
|
|
1547
|
+
if (activePhoneSummary?.connected) {
|
|
1548
|
+
activePhoneSummary = {
|
|
1549
|
+
...activePhoneSummary,
|
|
1550
|
+
deviceKind: clientDeviceKind,
|
|
1551
|
+
};
|
|
1552
|
+
const lastPublishedBridgeStatus = bridgeStatusPublisher.latest();
|
|
1553
|
+
if (lastPublishedBridgeStatus) {
|
|
1554
|
+
publishBridgeStatus(lastPublishedBridgeStatus);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1532
1558
|
if (clientName !== "codexmobile_ios") {
|
|
1533
1559
|
return null;
|
|
1534
1560
|
}
|
|
@@ -1697,7 +1723,11 @@ function startBridge({
|
|
|
1697
1723
|
}
|
|
1698
1724
|
|
|
1699
1725
|
function publishBridgeStatus(status) {
|
|
1700
|
-
bridgeStatusPublisher.publish(
|
|
1726
|
+
bridgeStatusPublisher.publish({
|
|
1727
|
+
...status,
|
|
1728
|
+
activeDevice: activePhoneSummary,
|
|
1729
|
+
activePhone: activePhoneSummary,
|
|
1730
|
+
});
|
|
1701
1731
|
}
|
|
1702
1732
|
|
|
1703
1733
|
// Refreshes the relay's trusted-mac index after the QR bootstrap locks in a phone identity.
|
|
@@ -1950,6 +1980,47 @@ function buildMacRegistration(deviceState, pairingSession) {
|
|
|
1950
1980
|
};
|
|
1951
1981
|
}
|
|
1952
1982
|
|
|
1983
|
+
function buildActivePhoneSummary(session, deviceState = null) {
|
|
1984
|
+
const phoneFingerprint = shortFingerprint(session?.phoneDeviceId);
|
|
1985
|
+
if (!phoneFingerprint) {
|
|
1986
|
+
return null;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
return {
|
|
1990
|
+
connected: true,
|
|
1991
|
+
phoneFingerprint,
|
|
1992
|
+
deviceKind: normalizeNonEmptyString(deviceState?.lastSeenDeviceKind) || null,
|
|
1993
|
+
handshakeMode: normalizeNonEmptyString(session?.handshakeMode) || null,
|
|
1994
|
+
keyEpoch: Number.isFinite(session?.keyEpoch) ? session.keyEpoch : null,
|
|
1995
|
+
updatedAt: new Date().toISOString(),
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
function classifyClientDeviceKind(clientName) {
|
|
2000
|
+
const normalized = normalizeNonEmptyString(clientName).toLowerCase();
|
|
2001
|
+
if (!normalized) {
|
|
2002
|
+
return null;
|
|
2003
|
+
}
|
|
2004
|
+
if (normalized.includes("android")) {
|
|
2005
|
+
return "android";
|
|
2006
|
+
}
|
|
2007
|
+
if (normalized.includes("ios") || normalized.includes("iphone")) {
|
|
2008
|
+
return "iphone";
|
|
2009
|
+
}
|
|
2010
|
+
if (normalized.includes("macos") || normalized.includes("mac")) {
|
|
2011
|
+
return "mac";
|
|
2012
|
+
}
|
|
2013
|
+
return null;
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
function shortFingerprint(value) {
|
|
2017
|
+
const normalized = normalizeNonEmptyString(value);
|
|
2018
|
+
if (!normalized) {
|
|
2019
|
+
return null;
|
|
2020
|
+
}
|
|
2021
|
+
return createHash("sha256").update(normalized).digest("hex").slice(0, 8);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
1953
2024
|
function shutdown(codex, getSocket, beforeExit = () => {}, { exitCode = 0 } = {}) {
|
|
1954
2025
|
beforeExit();
|
|
1955
2026
|
|
|
@@ -2553,6 +2624,10 @@ function compactEmergencySingleTurnForRelay(turn, maxChars, maxItems) {
|
|
|
2553
2624
|
"created_at",
|
|
2554
2625
|
"completedAt",
|
|
2555
2626
|
"completed_at",
|
|
2627
|
+
"timeZoneIdentifier",
|
|
2628
|
+
"timeZone",
|
|
2629
|
+
"timezone",
|
|
2630
|
+
"time_zone",
|
|
2556
2631
|
"status",
|
|
2557
2632
|
"role",
|
|
2558
2633
|
"kind",
|
|
@@ -3822,8 +3897,16 @@ function compactHistoryItemForRelay(item, maxChars) {
|
|
|
3822
3897
|
turn_id: typeof item?.turn_id === "string" ? item.turn_id : undefined,
|
|
3823
3898
|
createdAt: relayScalarHistoryMetadata(item?.createdAt),
|
|
3824
3899
|
created_at: relayScalarHistoryMetadata(item?.created_at),
|
|
3900
|
+
startedAt: relayScalarHistoryMetadata(item?.startedAt),
|
|
3901
|
+
started_at: relayScalarHistoryMetadata(item?.started_at),
|
|
3902
|
+
completedAt: relayScalarHistoryMetadata(item?.completedAt),
|
|
3903
|
+
completed_at: relayScalarHistoryMetadata(item?.completed_at),
|
|
3825
3904
|
timestamp: relayScalarHistoryMetadata(item?.timestamp),
|
|
3826
3905
|
time: relayScalarHistoryMetadata(item?.time),
|
|
3906
|
+
timeZoneIdentifier: relayScalarHistoryMetadata(item?.timeZoneIdentifier),
|
|
3907
|
+
timeZone: relayScalarHistoryMetadata(item?.timeZone),
|
|
3908
|
+
timezone: relayScalarHistoryMetadata(item?.timezone),
|
|
3909
|
+
time_zone: relayScalarHistoryMetadata(item?.time_zone),
|
|
3827
3910
|
relayPayloadTruncated: true,
|
|
3828
3911
|
};
|
|
3829
3912
|
const tailText = maxChars > 0 ? firstRelayTextTail(item, maxChars) : "";
|