grok-bot-cli 0.4.1 → 0.4.5
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/CHANGELOG.md +25 -0
- package/README.md +20 -2
- package/dist/.claude-plugin/marketplace.json +1 -1
- package/dist/.claude-plugin/plugin.json +1 -1
- package/dist/.codex-plugin/plugin.json +1 -1
- package/dist/.cursor-plugin/plugin.json +1 -1
- package/dist/INSTALL.md +1 -1
- package/dist/README.md +20 -2
- package/dist/agent-bundle.compile-evidence.json +1 -1
- package/dist/agent-bundle.manifest.json +1 -1
- package/dist/bin/gbot-flight.mjs +965 -81
- package/dist/bin/gbot.mjs +990 -82
- package/dist/install.mjs +1 -1
- package/dist/mcp/mcp-grok-bot-b8c2461e-flight.mjs +12 -1
- package/dist/mcp/mcp-grok-bot-b8c2461e.mjs +13 -2
- package/dist/package.json +1 -1
- package/dist/plugin.json +1 -1
- package/package.json +1 -1
package/dist/bin/gbot-flight.mjs
CHANGED
|
@@ -13884,6 +13884,140 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
13884
13884
|
});
|
|
13885
13885
|
|
|
13886
13886
|
|
|
13887
|
+
},
|
|
13888
|
+
"./src/cli/codex/desktop-shim.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
13889
|
+
__webpack_require__.r(__webpack_exports__);
|
|
13890
|
+
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.react-server.js");
|
|
13891
|
+
/* import */ var _agent_bundle_runtime__rspack_import_3 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
13892
|
+
/* import */ var zod__rspack_import_2 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js");
|
|
13893
|
+
/* import */ var _core_desktop_shim_js__rspack_import_1 = __webpack_require__("./src/core/desktop-shim.js");
|
|
13894
|
+
/* import */ var _core_format_js__rspack_import_4 = __webpack_require__("./src/core/format.js");
|
|
13895
|
+
|
|
13896
|
+
|
|
13897
|
+
|
|
13898
|
+
|
|
13899
|
+
|
|
13900
|
+
const config = {
|
|
13901
|
+
description: 'Install, remove, or check the ChatGPT Desktop shim: a CODEX_CLI_PATH wrapper that bridges Desktop stdio onto the managed Codex daemon (stock app-server proxy hangs). macOS persists via LaunchAgent; always fails open to real Codex.',
|
|
13902
|
+
exitCode: 'result',
|
|
13903
|
+
inputJsonSchema: {
|
|
13904
|
+
additionalProperties: false,
|
|
13905
|
+
properties: {
|
|
13906
|
+
action: {
|
|
13907
|
+
description: 'install | uninstall | status',
|
|
13908
|
+
enum: [
|
|
13909
|
+
'install',
|
|
13910
|
+
'uninstall',
|
|
13911
|
+
'status'
|
|
13912
|
+
],
|
|
13913
|
+
type: 'string'
|
|
13914
|
+
}
|
|
13915
|
+
},
|
|
13916
|
+
required: [
|
|
13917
|
+
'action'
|
|
13918
|
+
],
|
|
13919
|
+
type: 'object'
|
|
13920
|
+
},
|
|
13921
|
+
positionals: [
|
|
13922
|
+
'action'
|
|
13923
|
+
]
|
|
13924
|
+
};
|
|
13925
|
+
const inputSchema = zod__rspack_import_2/* .object */.Ikc({
|
|
13926
|
+
action: zod__rspack_import_2/* ["enum"] */.k5n([
|
|
13927
|
+
'install',
|
|
13928
|
+
'uninstall',
|
|
13929
|
+
'status'
|
|
13930
|
+
])
|
|
13931
|
+
}).strict();
|
|
13932
|
+
const resultSchema = zod__rspack_import_2/* .object */.Ikc({
|
|
13933
|
+
exitCode: zod__rspack_import_2/* .union */.KCZ([
|
|
13934
|
+
zod__rspack_import_2/* .literal */.euz(0),
|
|
13935
|
+
zod__rspack_import_2/* .literal */.euz(1)
|
|
13936
|
+
])
|
|
13937
|
+
}).passthrough();
|
|
13938
|
+
const formatWarnings = (warnings)=>warnings.length === 0 ? '' : `\nwarnings:\n${warnings.map((w)=>` - ${String(w)}`).join('\n')}`;
|
|
13939
|
+
async function codexDesktopShim({ input }) {
|
|
13940
|
+
switch(input.action){
|
|
13941
|
+
case 'install':
|
|
13942
|
+
{
|
|
13943
|
+
let out;
|
|
13944
|
+
try {
|
|
13945
|
+
out = (0,_core_desktop_shim_js__rspack_import_1/* .installDesktopShim */.B0)();
|
|
13946
|
+
} catch (error) {
|
|
13947
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
13948
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Result */.g6.Result, {
|
|
13949
|
+
value: {
|
|
13950
|
+
action: 'install',
|
|
13951
|
+
error: message,
|
|
13952
|
+
exitCode: 1
|
|
13953
|
+
},
|
|
13954
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Text */.g6.Text, {
|
|
13955
|
+
children: `Desktop shim install failed: ${message}`
|
|
13956
|
+
})
|
|
13957
|
+
});
|
|
13958
|
+
}
|
|
13959
|
+
const text = `Installed ChatGPT Desktop shim:\n` + ` wrapper: ${out.wrapperPath}\n` + ` bridge: ${out.bridgePath}\n` + ` login env: ${out.envScriptPath}` + (out.plistPath ? `\n LaunchAgent: ${out.plistPath}` : '\n LaunchAgent: n/a (macOS-only)') + `\nFully quit and relaunch ChatGPT.app so it inherits CODEX_CLI_PATH; ` + `Desktop falls back to stock Codex if the shim is ever removed.` + formatWarnings(out.warnings);
|
|
13960
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Result */.g6.Result, {
|
|
13961
|
+
value: out,
|
|
13962
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Text */.g6.Text, {
|
|
13963
|
+
children: text
|
|
13964
|
+
})
|
|
13965
|
+
});
|
|
13966
|
+
}
|
|
13967
|
+
case 'uninstall':
|
|
13968
|
+
{
|
|
13969
|
+
let out;
|
|
13970
|
+
try {
|
|
13971
|
+
out = (0,_core_desktop_shim_js__rspack_import_1/* .uninstallDesktopShim */.gM)();
|
|
13972
|
+
} catch (error) {
|
|
13973
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
13974
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Result */.g6.Result, {
|
|
13975
|
+
value: {
|
|
13976
|
+
action: 'uninstall',
|
|
13977
|
+
error: message,
|
|
13978
|
+
exitCode: 1
|
|
13979
|
+
},
|
|
13980
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Text */.g6.Text, {
|
|
13981
|
+
children: `Desktop shim uninstall failed: ${message}`
|
|
13982
|
+
})
|
|
13983
|
+
});
|
|
13984
|
+
}
|
|
13985
|
+
const removed = out.removed.length === 0 ? '(nothing installed)' : out.removed.join(', ');
|
|
13986
|
+
const text = `Removed ChatGPT Desktop shim: ${removed}. ` + `Desktop and Codex fall back to stock behavior; relaunch ChatGPT.app to pick it up.` + formatWarnings(out.warnings);
|
|
13987
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Result */.g6.Result, {
|
|
13988
|
+
value: out,
|
|
13989
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Text */.g6.Text, {
|
|
13990
|
+
children: text
|
|
13991
|
+
})
|
|
13992
|
+
});
|
|
13993
|
+
}
|
|
13994
|
+
case 'status':
|
|
13995
|
+
{
|
|
13996
|
+
const out = (0,_core_desktop_shim_js__rspack_import_1/* .desktopShimStatus */.em)();
|
|
13997
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Result */.g6.Result, {
|
|
13998
|
+
value: out,
|
|
13999
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_3/* .Agent.Text */.g6.Text, {
|
|
14000
|
+
children: (0,_core_format_js__rspack_import_4/* .formatDesktopShimStatus */.fX)(out)
|
|
14001
|
+
})
|
|
14002
|
+
});
|
|
14003
|
+
}
|
|
14004
|
+
default:
|
|
14005
|
+
{
|
|
14006
|
+
const _exhaustive = input.action;
|
|
14007
|
+
throw new Error(`unknown desktop-shim action: ${String(_exhaustive)}`);
|
|
14008
|
+
}
|
|
14009
|
+
}
|
|
14010
|
+
}
|
|
14011
|
+
|
|
14012
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
14013
|
+
"default": () => (codexDesktopShim)
|
|
14014
|
+
}, {
|
|
14015
|
+
config: config,
|
|
14016
|
+
inputSchema: inputSchema,
|
|
14017
|
+
resultSchema: resultSchema
|
|
14018
|
+
});
|
|
14019
|
+
|
|
14020
|
+
|
|
13887
14021
|
},
|
|
13888
14022
|
"./src/cli/codex/list-threads.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
13889
14023
|
__webpack_require__.r(__webpack_exports__);
|
|
@@ -26276,6 +26410,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
26276
26410
|
/* import */ var node_child_process__rspack_import_5 = __webpack_require__("node:child_process");
|
|
26277
26411
|
/* import */ var node_module__rspack_import_6 = __webpack_require__("node:module");
|
|
26278
26412
|
/* import */ var _codex_contract_js__rspack_import_7 = __webpack_require__("./src/core/codex/contract.js");
|
|
26413
|
+
/* import */ var _desktop_shim_js__rspack_import_8 = __webpack_require__("./src/core/desktop-shim.js");
|
|
26414
|
+
|
|
26279
26415
|
|
|
26280
26416
|
|
|
26281
26417
|
|
|
@@ -26303,6 +26439,9 @@ const textDecoder = new TextDecoder("utf-8", {
|
|
|
26303
26439
|
});
|
|
26304
26440
|
const pkg = (0,node_module__rspack_import_6.createRequire)(import.meta.url)("../../package.json");
|
|
26305
26441
|
function codexSocketPath(env = process.env) {
|
|
26442
|
+
// Explicit socket wins so status/send/queue agree with a shim-installed or
|
|
26443
|
+
// operator-exported CODEX_APP_SERVER_SOCK; otherwise derive from CODEX_HOME.
|
|
26444
|
+
if (env.CODEX_APP_SERVER_SOCK) return env.CODEX_APP_SERVER_SOCK;
|
|
26306
26445
|
const home = env.CODEX_HOME || (0,node_path__rspack_import_4.join)((0,node_os__rspack_import_3.homedir)(), ".codex");
|
|
26307
26446
|
return (0,node_path__rspack_import_4.join)(home, "app-server-control", "app-server-control.sock");
|
|
26308
26447
|
}
|
|
@@ -26319,7 +26458,15 @@ function codexSocketPath(env = process.env) {
|
|
|
26319
26458
|
/** Single-line fields (ids, names, paths, cursors, header tokens): no line breaks or tabs survive. */ function singleLine(text) {
|
|
26320
26459
|
return stripTerminalControls(text).replace(/[\t\n\r\u2028\u2029]+/g, " ");
|
|
26321
26460
|
}
|
|
26322
|
-
function unreachableMessage(path) {
|
|
26461
|
+
function unreachableMessage(path, desktopAttached = "unknown") {
|
|
26462
|
+
if (desktopAttached === "private-stdio") {
|
|
26463
|
+
return [
|
|
26464
|
+
"ChatGPT Desktop is running its private stdio app-server, which external clients cannot reach",
|
|
26465
|
+
"(" + UPSTREAM_DESKTOP_ISSUES.join(", ") + ").",
|
|
26466
|
+
"No Codex app-server control socket at " + path + ": start a managed standalone daemon with `codex app-server daemon start`.",
|
|
26467
|
+
"gbot codex targets daemon-managed threads only."
|
|
26468
|
+
].join("\n");
|
|
26469
|
+
}
|
|
26323
26470
|
return [
|
|
26324
26471
|
"No Codex app-server control socket at " + path + ".",
|
|
26325
26472
|
"Either no daemon is running (start one with `codex app-server daemon start`),",
|
|
@@ -26522,6 +26669,43 @@ function isObject(value) {
|
|
|
26522
26669
|
const sendJson = (obj)=>write(0x1, Buffer.from(JSON.stringify(obj)));
|
|
26523
26670
|
const client = {
|
|
26524
26671
|
refused,
|
|
26672
|
+
// Server-initiated requests are only *answered* once our own turn/start
|
|
26673
|
+
// is in flight, and then only when they name our own thread/turn:
|
|
26674
|
+
// anything earlier — or naming another thread or Desktop turn — belongs
|
|
26675
|
+
// to another client and must never be rejected on their behalf. Early
|
|
26676
|
+
// and foreign requests are still recorded; the connection closes right
|
|
26677
|
+
// after, so a pending request simply dies with it instead of denying
|
|
26678
|
+
// someone's approval.
|
|
26679
|
+
answerServerRequests: false,
|
|
26680
|
+
expectedThreadId: null,
|
|
26681
|
+
expectedTurnId: null,
|
|
26682
|
+
// Approvals that name a turn while our own turn id is still unknown
|
|
26683
|
+
// (arriving before — or in the same socket batch as — the turn/start
|
|
26684
|
+
// acknowledgment) wait here instead of being classified foreign: once
|
|
26685
|
+
// the acknowledgment supplies the turn id, matching ones are answered
|
|
26686
|
+
// and the rest stay silent.
|
|
26687
|
+
deferred: [],
|
|
26688
|
+
// Adopt the acknowledged turn id, answering deferred requests that
|
|
26689
|
+
// prove to be ours. Runs inside the connection closure so it can send.
|
|
26690
|
+
_adoptTurn (turnId) {
|
|
26691
|
+
client.expectedTurnId = turnId;
|
|
26692
|
+
for (const entry of client.deferred.splice(0)){
|
|
26693
|
+
const params = entry.params && typeof entry.params === "object" && !Array.isArray(entry.params) ? entry.params : null;
|
|
26694
|
+
const threadId = params ? params.threadId ?? params.thread_id : null;
|
|
26695
|
+
const namedTurnId = params ? params.turnId ?? params.turn_id ?? (params.turn && params.turn.id) : null;
|
|
26696
|
+
if (threadId === client.expectedThreadId && namedTurnId === turnId) {
|
|
26697
|
+
entry.answered = true;
|
|
26698
|
+
sendJson({
|
|
26699
|
+
jsonrpc: "2.0",
|
|
26700
|
+
id: entry.id,
|
|
26701
|
+
error: {
|
|
26702
|
+
code: -32601,
|
|
26703
|
+
message: "gbot codex does not answer " + entry.method + "; configure approval_policy on the daemon"
|
|
26704
|
+
}
|
|
26705
|
+
});
|
|
26706
|
+
}
|
|
26707
|
+
}
|
|
26708
|
+
},
|
|
26525
26709
|
request (method, params) {
|
|
26526
26710
|
const id = nextId++;
|
|
26527
26711
|
return new Promise((res, rej)=>{
|
|
@@ -26585,11 +26769,37 @@ function isObject(value) {
|
|
|
26585
26769
|
};
|
|
26586
26770
|
const onMessage = (msg)=>{
|
|
26587
26771
|
if (msg.id != null && msg.method) {
|
|
26588
|
-
|
|
26772
|
+
let answered = client.answerServerRequests;
|
|
26773
|
+
let defer = false;
|
|
26774
|
+
// Approval ownership: only answer requests for the turn gbot itself
|
|
26775
|
+
// started. A request naming another thread — or naming a turn that is
|
|
26776
|
+
// not ours — is recorded foreign-silent, never rejected. A request
|
|
26777
|
+
// naming a turn while our turn id is still unknown is deferred, not
|
|
26778
|
+
// classified: the turn/start acknowledgment decides it.
|
|
26779
|
+
if (answered) {
|
|
26780
|
+
const params = msg.params && typeof msg.params === "object" && !Array.isArray(msg.params) ? msg.params : null;
|
|
26781
|
+
if (params) {
|
|
26782
|
+
const threadId = params.threadId ?? params.thread_id;
|
|
26783
|
+
const turnId = params.turnId ?? params.turn_id ?? (params.turn && params.turn.id);
|
|
26784
|
+
if (threadId !== client.expectedThreadId || turnId == null) answered = false;
|
|
26785
|
+
else if (client.expectedTurnId == null) {
|
|
26786
|
+
answered = false;
|
|
26787
|
+
defer = true;
|
|
26788
|
+
} else if (turnId !== client.expectedTurnId) answered = false;
|
|
26789
|
+
} else answered = false;
|
|
26790
|
+
}
|
|
26791
|
+
const entry = {
|
|
26589
26792
|
id: msg.id,
|
|
26590
26793
|
method: msg.method,
|
|
26591
|
-
params: msg.params
|
|
26592
|
-
|
|
26794
|
+
params: msg.params,
|
|
26795
|
+
answered
|
|
26796
|
+
};
|
|
26797
|
+
refused.push(entry);
|
|
26798
|
+
if (defer) {
|
|
26799
|
+
client.deferred.push(entry);
|
|
26800
|
+
return;
|
|
26801
|
+
}
|
|
26802
|
+
if (!answered) return;
|
|
26593
26803
|
sendJson({
|
|
26594
26804
|
jsonrpc: "2.0",
|
|
26595
26805
|
id: msg.id,
|
|
@@ -26793,32 +27003,98 @@ const CODEX_VERSION_PROBE_TIMEOUT_MS = 3000;
|
|
|
26793
27003
|
probe: "error"
|
|
26794
27004
|
};
|
|
26795
27005
|
}
|
|
27006
|
+
/** Bounded `ps` snapshot for Desktop detection: process names only, never pipes or sockets. */ const DESKTOP_PROCESS_LIST_TIMEOUT_MS = 3000;
|
|
27007
|
+
function listDesktopProcesses(timeoutMs = DESKTOP_PROCESS_LIST_TIMEOUT_MS) {
|
|
27008
|
+
if (process.platform === "win32") return "";
|
|
27009
|
+
try {
|
|
27010
|
+
const out = (0,node_child_process__rspack_import_5.spawnSync)("ps", [
|
|
27011
|
+
"-eo",
|
|
27012
|
+
"args"
|
|
27013
|
+
], {
|
|
27014
|
+
encoding: "utf8",
|
|
27015
|
+
timeout: timeoutMs
|
|
27016
|
+
});
|
|
27017
|
+
if (out.error || out.status !== 0 || typeof out.stdout !== "string") return "";
|
|
27018
|
+
return out.stdout;
|
|
27019
|
+
} catch {
|
|
27020
|
+
return "";
|
|
27021
|
+
}
|
|
27022
|
+
}
|
|
27023
|
+
/**
|
|
27024
|
+
* Pure Desktop private-stdio detector. Returns `"private-stdio"` when the process list
|
|
27025
|
+
* shows Desktop's bundled `.../ChatGPT.app/.../Resources/codex` running `app-server`
|
|
27026
|
+
* (the `codex_app` override corroborates, the Resources path alone suffices); `"unknown"`
|
|
27027
|
+
* otherwise. Never `"detached"`: absence of a match means "not observed", not "not running".
|
|
27028
|
+
* Windows stays `"unknown"` (unsupported route, unchanged).
|
|
27029
|
+
*
|
|
27030
|
+
* @param {{ platform?: string, listProcesses?: string | string[] | null }} [opts]
|
|
27031
|
+
*/ function detectDesktopPrivateAppServer({ platform = process.platform, listProcesses = "" } = {}) {
|
|
27032
|
+
if (platform === "win32") return "unknown";
|
|
27033
|
+
const lines = Array.isArray(listProcesses) ? listProcesses : String(listProcesses ?? "").split(/\r?\n/);
|
|
27034
|
+
for (const line of lines){
|
|
27035
|
+
if (!/app-server/.test(line)) continue;
|
|
27036
|
+
// Desktop's bundled binary, Mac or Windows-style separators with optional .exe.
|
|
27037
|
+
if (/ChatGPT\.app[\\/].*Resources[\\/]codex(\.exe)?(["'\s]|$)/.test(line)) return "private-stdio";
|
|
27038
|
+
// Same app-server line owned by ChatGPT.app carrying the app-tools override.
|
|
27039
|
+
if (/ChatGPT\.app/.test(line) && /(codex_app|mcp_servers\.codex_app|codex-app-tools)/.test(line)) return "private-stdio";
|
|
27040
|
+
}
|
|
27041
|
+
return "unknown";
|
|
27042
|
+
}
|
|
26796
27043
|
/**
|
|
26797
27044
|
* Status contract: `reachable` is endpoint reachability only. `schema.compatibility` is
|
|
26798
27045
|
* `exact` when the daemon reports the pinned version, otherwise `unverified` (methods
|
|
26799
|
-
* usually survive upgrades) or `unknown`.
|
|
26800
|
-
*
|
|
26801
|
-
|
|
27046
|
+
* usually survive upgrades) or `unknown`. `desktopShimConfigured` records an installed
|
|
27047
|
+
* wrapper selected by Desktop-facing CODEX_CLI_PATH (the GUI domain on Darwin).
|
|
27048
|
+
* Configuration does not prove a running Desktop inherited it or connected.
|
|
27049
|
+
* `desktopAttached` is `"private-stdio"` when a Desktop-bundled app-server process
|
|
27050
|
+
* is visible, otherwise `"unknown"`. Managed attachment is not observable here.
|
|
27051
|
+
*
|
|
27052
|
+
* @param {NodeJS.ProcessEnv} [env]
|
|
27053
|
+
* @param {{ listProcesses?: string | string[], shim?: { installed?: boolean, wrapperPointsAtShim?: boolean } | null }} [opts]
|
|
27054
|
+
* injected process list and shim state for tests; defaults to a live `ps` snapshot and
|
|
27055
|
+
* `desktopShimStatus`. Never reads pipes or connects to Desktop.
|
|
27056
|
+
*/ async function codexStatus(env = process.env, { listProcesses, shim } = {}) {
|
|
26802
27057
|
const path = codexSocketPath(env);
|
|
26803
27058
|
const cli = probeLocalCodexVersion();
|
|
27059
|
+
let desktopShimConfigured = Boolean(shim && shim.installed && shim.wrapperPointsAtShim);
|
|
27060
|
+
if (shim === undefined) {
|
|
27061
|
+
try {
|
|
27062
|
+
const live = (0,_desktop_shim_js__rspack_import_8/* .desktopShimStatus */.em)({
|
|
27063
|
+
env
|
|
27064
|
+
});
|
|
27065
|
+
desktopShimConfigured = Boolean(live.installed && live.wrapperPointsAtShim);
|
|
27066
|
+
} catch {
|
|
27067
|
+
desktopShimConfigured = false;
|
|
27068
|
+
}
|
|
27069
|
+
}
|
|
27070
|
+
const desktopAttached = detectDesktopPrivateAppServer({
|
|
27071
|
+
platform: process.platform,
|
|
27072
|
+
listProcesses: listProcesses ?? listDesktopProcesses()
|
|
27073
|
+
});
|
|
26804
27074
|
const base = {
|
|
26805
27075
|
socketPath: path,
|
|
26806
27076
|
socketState: socketState(path),
|
|
26807
27077
|
pinnedVersion: PINNED_CODEX_VERSION,
|
|
26808
27078
|
cliVersion: cli.version,
|
|
26809
27079
|
cliVersionProbe: cli.probe,
|
|
26810
|
-
desktopAttached
|
|
27080
|
+
desktopAttached,
|
|
27081
|
+
desktopShimConfigured
|
|
26811
27082
|
};
|
|
26812
27083
|
let session;
|
|
26813
27084
|
try {
|
|
26814
27085
|
session = await openSession(env);
|
|
26815
27086
|
} catch (err) {
|
|
26816
|
-
if (err instanceof CodexRouteError)
|
|
26817
|
-
|
|
26818
|
-
|
|
26819
|
-
mode: err.
|
|
26820
|
-
|
|
26821
|
-
|
|
27087
|
+
if (err instanceof CodexRouteError) {
|
|
27088
|
+
// Name the private-stdio case explicitly: Desktop is up but unreachable, so the
|
|
27089
|
+
// operator needs a managed standalone daemon, not a Desktop reconnect.
|
|
27090
|
+
const message = err.mode === "socket-absent" ? unreachableMessage(path, desktopAttached) : err.message;
|
|
27091
|
+
return (0,_codex_contract_js__rspack_import_7/* .withStatusExitCode */.AQ)({
|
|
27092
|
+
...base,
|
|
27093
|
+
reachable: false,
|
|
27094
|
+
mode: err.mode,
|
|
27095
|
+
message
|
|
27096
|
+
});
|
|
27097
|
+
}
|
|
26822
27098
|
// The endpoint answered; what it said does not match the pinned schema.
|
|
26823
27099
|
if (err instanceof CodexProtocolError) return (0,_codex_contract_js__rspack_import_7/* .withStatusExitCode */.AQ)({
|
|
26824
27100
|
...base,
|
|
@@ -27204,6 +27480,16 @@ async function sendToCodexThreadInner(threadId, text, { env, envelope, whenBusy
|
|
|
27204
27480
|
// the daemon exposes no compare-and-start request. Upgrade path: thread/queue/add + thread/queue/start once stable.
|
|
27205
27481
|
// Scope refusals to this turn: server requests from earlier calls belong to another context.
|
|
27206
27482
|
const seenRefused = client.refused.length;
|
|
27483
|
+
// Arm refusal replies only now that our own turn/start is in flight, scoped
|
|
27484
|
+
// to our own thread/turn: anything recorded earlier (resume, busy reject,
|
|
27485
|
+
// queue) — or naming another thread or Desktop turn — stays unanswered so
|
|
27486
|
+
// gbot never rejects another client's approval. Requests naming a turn
|
|
27487
|
+
// that arrives before the acknowledgment supplies our turn id wait in
|
|
27488
|
+
// client.deferred and are adopted only on a match. Requests missing
|
|
27489
|
+
// thread or turn IDs remain unanswered because ownership is unknown.
|
|
27490
|
+
client.expectedThreadId = threadId;
|
|
27491
|
+
client.expectedTurnId = null;
|
|
27492
|
+
client.answerServerRequests = true;
|
|
27207
27493
|
let turn;
|
|
27208
27494
|
try {
|
|
27209
27495
|
turn = await client.request("turn/start", {
|
|
@@ -27238,7 +27524,17 @@ async function sendToCodexThreadInner(threadId, text, { env, envelope, whenBusy
|
|
|
27238
27524
|
envelope
|
|
27239
27525
|
});
|
|
27240
27526
|
}
|
|
27241
|
-
|
|
27527
|
+
client._adoptTurn(turnId);
|
|
27528
|
+
const freshRefused = client.refused.slice(seenRefused).filter((r)=>{
|
|
27529
|
+
if (!r.answered) return false;
|
|
27530
|
+
const params = r.params && typeof r.params === "object" && !Array.isArray(r.params) ? r.params : null;
|
|
27531
|
+
if (!params) return true;
|
|
27532
|
+
const refusedThreadId = params.threadId ?? params.thread_id;
|
|
27533
|
+
const refusedTurnId = params.turnId ?? params.turn_id ?? (params.turn && params.turn.id);
|
|
27534
|
+
if (refusedThreadId != null && refusedThreadId !== threadId) return false;
|
|
27535
|
+
if (refusedTurnId != null && refusedTurnId !== turnId) return false;
|
|
27536
|
+
return true;
|
|
27537
|
+
});
|
|
27242
27538
|
if (freshRefused.length) {
|
|
27243
27539
|
const methods = freshRefused.map((r)=>r.method).join(", ");
|
|
27244
27540
|
throw new CodexSendError("Turn " + turnId + " started on thread " + threadId + " but Codex asked for " + methods + ", which gbot refused. " + "Answer it in a Codex client, or set `approval_policy = \"never\"` in the daemon's config.toml for unattended sends.", {
|
|
@@ -27474,6 +27770,548 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
27474
27770
|
});
|
|
27475
27771
|
|
|
27476
27772
|
|
|
27773
|
+
},
|
|
27774
|
+
"./src/core/desktop-shim-bridge.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
27775
|
+
// Stdio JSONL (Desktop) <-> WebSocket-over-unix bridge onto the managed
|
|
27776
|
+
// Codex app-server control socket. Vendored from uploads/codex-stdio-to-daemon-ws.py
|
|
27777
|
+
// (ChatGPT Desktop -> managed daemon shim) with fail-open deltas, marked below:
|
|
27778
|
+
// (1) ws_connect enforces one absolute monotonic deadline for connect + HTTP
|
|
27779
|
+
// upgrade (CODEX_BRIDGE_CONNECT_TIMEOUT, default 10s), requires HTTP/1.1 101
|
|
27780
|
+
// plus a matching Sec-WebSocket-Accept (a 200 fails even with a valid hash),
|
|
27781
|
+
// and retains bytes coalesced after the upgrade headers instead of discarding
|
|
27782
|
+
// the first data frame.
|
|
27783
|
+
// (2) read_message assembles continuation frames; control frames answer inline;
|
|
27784
|
+
// every socket send/lock shares one monotonic budget (remaining first-RPC
|
|
27785
|
+
// budget, else the mid-session write budget) so a non-reading peer cannot
|
|
27786
|
+
// wedge pong writes or timeout cleanup; timeouts close and exit. Reads wait
|
|
27787
|
+
// with no timeout after the handshake so healthy idle sessions survive.
|
|
27788
|
+
// The wrapper never starts the daemon on the spawn path, so no daemon lock can
|
|
27789
|
+
// block pre-stdin Desktop.
|
|
27790
|
+
// (3) A first-response deadline (CODEX_BRIDGE_FIRST_MESSAGE_TIMEOUT, default
|
|
27791
|
+
// 30s) bounds connect-to-matching-daemon-response covering the first RPC;
|
|
27792
|
+
// unrelated notifications and foreign responses never satisfy it, only the
|
|
27793
|
+
// matching response/error (or timeout) clears it. The preflight (3s) +
|
|
27794
|
+
// upgrade (10s) + first RPC (30s) budget stays far below a daemon-lock hang.
|
|
27795
|
+
// Exits are 0 served, 1 pre-stdio (wrapper falls back to real Codex on pristine
|
|
27796
|
+
// stdio+stdout), 2 mid-session (wrapper exits so Desktop reconnects).
|
|
27797
|
+
// (4) Byte-precise commit on input OR output, committed BEFORE the stdout
|
|
27798
|
+
// write: os.read into a userspace line buffer counts every stdin byte (even
|
|
27799
|
+
// an unforwarded blank line), and any daemon payload marks stdout used before
|
|
27800
|
+
// it is written via a bounded stdout write, so the fallback only ever runs
|
|
27801
|
+
// on truly pristine stdio+stdout and never spawns a second Codex after used
|
|
27802
|
+
// stdout. Buffered EOF-tail data flushes before the WS Close, which drains
|
|
27803
|
+
// via shutdown+close with a bounded join. The reader signals a done event so
|
|
27804
|
+
// WS close wakes the select loop; no path leaves a thread hung.
|
|
27805
|
+
// Desktop stdio hangs with stock `codex app-server proxy`, so this custom
|
|
27806
|
+
// bridge is required. Install writes it to the CODEX_HOME bin dir. Never reads
|
|
27807
|
+
// Desktop private pipes (CODEX_APP_TOOLS_PIPE_PATH, /tmp/codex-browser-use/).
|
|
27808
|
+
const BRIDGE_SOURCE = "#!/usr/bin/env python3\n\"\"\"Stdio JSONL (Desktop) <-> WebSocket-over-unix (managed app-server daemon).\nReversible: remove CODEX_CLI_PATH wrapper. Does not read Desktop private pipes.\n\"\"\"\nfrom __future__ import annotations\nimport base64, hashlib, json, os, select, socket, struct, sys, threading, time\n\nSOCK = os.environ.get(\n \"CODEX_APP_SERVER_SOCK\",\n os.path.expanduser(\"~/.codex/app-server-control/app-server-control.sock\"),\n)\nLOG = os.environ.get(\"CODEX_STDIO_BRIDGE_LOG\", os.path.expanduser(\"~/.codex/bin/codex-stdio-to-daemon-ws.log\"))\nWS_GUID = \"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\"\n\n# Wrapper contract: 0 served the session, 1 failed while stdio was still\n# pristine -- no stdin byte consumed and no stdout frame committed (wrapper\n# falls back to real Codex), 2 failed mid-session (wrapper exits promptly so\n# Desktop reconnects; the fallback must never run on half-consumed stdin or\n# dirty stdout).\nEXIT_SERVED = 0\nEXIT_PRE_STDIO = 1\nEXIT_MID_SESSION = 2\n\nCONNECT_TIMEOUT_S = float(os.environ.get(\"CODEX_BRIDGE_CONNECT_TIMEOUT\", \"10\"))\n# Bound from connect to the matching first daemon response: a daemon that\n# completes the upgrade but never answers the first RPC must not hold Desktop\n# past this. Only the matching initialize response/error (or the deadline\n# itself) clears it; notifications never do.\nFIRST_MESSAGE_TIMEOUT_S = float(os.environ.get(\"CODEX_BRIDGE_FIRST_MESSAGE_TIMEOUT\", \"30\"))\n# Bound on every mid-session socket send and stdout write: a wedged or\n# non-reading peer must not hang Desktop past this. Reads after a successful\n# init block with no timeout so healthy idle sessions survive silence.\nIO_TIMEOUT_S = float(os.environ.get(\"CODEX_BRIDGE_IO_TIMEOUT\", \"30\"))\n\ndef log(msg: str) -> None:\n try:\n with open(LOG, \"a\") as f:\n f.write(time.strftime(\"%Y-%m-%dT%H:%M:%SZ\", time.gmtime()) + \" \" + msg + \"\\n\")\n except OSError:\n pass\n\ndef ws_connect(path: str, timeout: float = CONNECT_TIMEOUT_S):\n \"\"\"Connect + HTTP upgrade under one absolute monotonic deadline.\n\n Returns (socket, trailing) where trailing holds bytes coalesced after the\n upgrade headers (TCP may deliver the 101 and the first WS frame together;\n discarding them would lose the first message). Requires HTTP/1.1 101 plus\n a matching Sec-WebSocket-Accept so a 200 (or any non-101) fails fast even\n when the accept hash happens to be valid.\n \"\"\"\n deadline = time.monotonic() + timeout\n s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)\n s.settimeout(timeout)\n try:\n s.connect(path)\n key = base64.b64encode(os.urandom(16)).decode()\n expected = base64.b64encode(hashlib.sha1((key + WS_GUID).encode()).digest()).decode()\n req = (\n f\"GET /rpc HTTP/1.1\\r\\nHost: localhost\\r\\nUpgrade: websocket\\r\\n\"\n f\"Connection: Upgrade\\r\\nSec-WebSocket-Key: {key}\\r\\nSec-WebSocket-Version: 13\\r\\n\\r\\n\"\n ).encode()\n s.settimeout(max(0.0, deadline - time.monotonic()))\n s.sendall(req)\n buf = b\"\"\n while True:\n if b\"\\r\\n\\r\\n\" in buf:\n break\n remaining = deadline - time.monotonic()\n if remaining <= 0:\n raise TimeoutError(\"WebSocket upgrade timed out\")\n if len(buf) > 65536:\n raise ConnectionError(\"WS upgrade headers too large\")\n s.settimeout(remaining)\n chunk = s.recv(4096)\n if not chunk:\n raise ConnectionError(\"daemon closed during WS upgrade\")\n buf += chunk\n head, _, trailing = buf.partition(b\"\\r\\n\\r\\n\")\n lines = head.split(b\"\\r\\n\")\n if not lines or lines[0].split(b\" \", 2)[:2] != [b\"HTTP/1.1\", b\"101\"]:\n raise ConnectionError(f\"WS upgrade failed: {head[:200]!r}\")\n accept = None\n for line in lines[1:]:\n name, sep, value = line.partition(b\":\")\n if sep and name.strip().lower() == b\"sec-websocket-accept\":\n accept = value.strip().decode(\"latin-1\")\n if accept != expected:\n raise ConnectionError(\"WS upgrade accept mismatch\")\n except Exception:\n try:\n s.close()\n except OSError:\n pass\n raise\n # Keep one socket mode across reader and writer threads. Reads wait\n # indefinitely in select; sends use their own absolute deadline.\n s.setblocking(False)\n return s, trailing\n\ndef mask_send(sock: socket.socket, payload: bytes, opcode: int = 1, deadline=None) -> None:\n mask = os.urandom(4)\n ln = len(payload)\n if ln < 126:\n hdr = bytes([0x80 | opcode, 0x80 | ln])\n elif ln < 65536:\n hdr = bytes([0x80 | opcode, 0x80 | 126]) + struct.pack(\"!H\", ln)\n else:\n hdr = bytes([0x80 | opcode, 0x80 | 127]) + struct.pack(\"!Q\", ln)\n view = memoryview(hdr + mask + bytes(b ^ mask[i % 4] for i, b in enumerate(payload)))\n while view:\n remaining = deadline - time.monotonic()\n if remaining <= 0:\n raise TimeoutError(\"socket write timed out\")\n _, writable, _ = select.select([], [sock], [], remaining)\n if not writable:\n raise TimeoutError(\"socket write timed out\")\n try:\n n = sock.send(view)\n except BlockingIOError:\n continue\n if not n:\n raise ConnectionError(\"socket closed during write\")\n view = view[n:]\n\ndef locked_send(sock: socket.socket, lock: threading.Lock, payload: bytes, opcode: int = 1, timeout: float = CONNECT_TIMEOUT_S) -> None:\n \"\"\"Serialized send sharing one monotonic budget across lock wait + send.\n\n A non-reading peer must never wedge pong writes or timeout cleanup: on\n expiry raise TimeoutError so the caller closes and exits without hanging.\n \"\"\"\n if timeout is None:\n timeout = CONNECT_TIMEOUT_S\n deadline = time.monotonic() + timeout\n if timeout <= 0:\n raise TimeoutError(\"send budget expired\")\n if not lock.acquire(timeout=timeout):\n raise TimeoutError(\"send lock timed out\")\n try:\n remaining = deadline - time.monotonic()\n if remaining <= 0:\n raise TimeoutError(\"send budget expired\")\n mask_send(sock, payload, opcode=opcode, deadline=deadline)\n finally:\n lock.release()\n\ndef _buffered_reader(sock: socket.socket, initial: bytes = b\"\"):\n buf = bytearray(initial)\n def recv(n):\n while len(buf) < n:\n select.select([sock], [], [])\n try:\n chunk = sock.recv(n - len(buf))\n except BlockingIOError:\n continue\n if not chunk:\n raise ConnectionError(\"eof\")\n buf.extend(chunk)\n out = bytes(buf[:n])\n del buf[:n]\n return out\n return recv\n\ndef read_frame(recv):\n hdr = recv(2)\n fin = bool(hdr[0] & 0x80)\n opcode = hdr[0] & 0x0F\n masked = bool(hdr[1] & 0x80)\n ln = hdr[1] & 0x7F\n if ln == 126:\n ln = struct.unpack(\"!H\", recv(2))[0]\n elif ln == 127:\n ln = struct.unpack(\"!Q\", recv(8))[0]\n mask = recv(4) if masked else b\"\"\n payload = recv(ln)\n if masked:\n payload = bytes(b ^ mask[i % 4] for i, b in enumerate(payload))\n return fin, opcode, payload\n\ndef read_message(recv, send_pong):\n \"\"\"Next complete data message, assembling continuation frames.\n\n Control frames are handled inline (pong answered, close reported) so a\n fragmented message split around a ping still reassembles.\n \"\"\"\n opcode = None\n parts = []\n while True:\n fin, op, payload = read_frame(recv)\n if op == 0x8:\n return (\"close\", None, b\"\")\n if op == 0x9:\n send_pong(payload)\n continue\n if op == 0xA:\n continue\n if op in (0x1, 0x2):\n if opcode is not None:\n raise ConnectionError(\"data frame inside fragmented message\")\n if fin:\n return (\"data\", op, payload)\n opcode = op\n parts.append(payload)\n continue\n if op == 0x0:\n if opcode is None:\n raise ConnectionError(\"stray continuation frame\")\n parts.append(payload)\n if fin:\n return (\"data\", opcode, b\"\".join(parts))\n continue\n raise ConnectionError(f\"unsupported opcode {op}\")\n\ndef _is_daemon_response(payload: bytes, expect_id=None, known_ids=None) -> bool:\n \"\"\"True only for the matching JSON-RPC response/error, never a notification.\n\n The first-RPC timer must survive unrelated daemon notifications and foreign\n responses: only the response/error whose id matches the client's initialize\n (or, before it is known, any id the client already sent) proves the first\n RPC got an answer. Timeouts clear it via the deadline, never via data.\n \"\"\"\n try:\n text = payload.decode(\"utf-8\").strip()\n msg = json.loads(text)\n except Exception:\n return False\n if not isinstance(msg, dict):\n return False\n rid = msg.get(\"id\")\n if rid is None or \"method\" in msg or (\"result\" not in msg and \"error\" not in msg):\n return False\n if expect_id is not None:\n return rid == expect_id\n if known_ids:\n return rid in known_ids\n return False\n\ndef _bounded_stdout_write(data: bytes, timeout: float = IO_TIMEOUT_S) -> None:\n \"\"\"Write one daemon frame to stdout without hanging on a non-reading peer.\n\n Waits for writability under the mid-session write budget and writes via\n os.write in a loop, so a Desktop that stopped reading cannot hang the\n bridge and then exit 1 on dirty stdout.\n \"\"\"\n if timeout is None:\n timeout = IO_TIMEOUT_S\n if timeout <= 0:\n raise TimeoutError(\"stdout budget expired\")\n fd = sys.stdout.fileno()\n deadline = time.monotonic() + timeout\n was_blocking = os.get_blocking(fd)\n os.set_blocking(fd, False)\n try:\n view = memoryview(data)\n while view:\n remaining = deadline - time.monotonic()\n if remaining <= 0:\n raise TimeoutError(\"stdout write timed out\")\n _, writable, _ = select.select([], [fd], [], remaining)\n if not writable:\n raise TimeoutError(\"stdout write timed out\")\n try:\n n = os.write(fd, view)\n except BlockingIOError:\n continue\n view = view[n:]\n finally:\n os.set_blocking(fd, was_blocking)\n\ndef stdout_writer(sock: socket.socket, recv, send_pong, done: threading.Event, first_msg: threading.Event, output_forwarded: threading.Event, client_ids=None, init_state=None) -> None:\n try:\n while True:\n kind, opcode, payload = read_message(recv, send_pong)\n if kind == \"close\":\n log(\"daemon WS close\")\n return\n if opcode == 0x1:\n # Desktop StdioConnection expects newline-delimited JSON text\n if not payload.endswith(b\"\\n\"):\n payload += b\"\\n\"\n # Commit BEFORE writing: once a daemon byte is about to hit\n # stdout, the session is dirty and the fallback must never run,\n # even if the write itself blocks or fails.\n output_forwarded.set()\n _bounded_stdout_write(payload)\n if opcode == 0x1:\n expect = (init_state or {}).get(\"initialize_id\") if isinstance(init_state, dict) else None\n if _is_daemon_response(payload, expect, client_ids or ()):\n first_msg.set()\n except Exception as e:\n log(f\"stdout_writer exit: {e}\")\n finally:\n done.set()\n\ndef main() -> int:\n log(f\"start sock={SOCK}\")\n try:\n sock, pending = ws_connect(SOCK)\n except Exception as e:\n log(f\"connect failed: {e}\")\n sys.stderr.write(f\"codex-stdio-to-daemon-ws: {e}\\n\")\n return EXIT_PRE_STDIO\n log(\"connected\")\n connected_at = time.monotonic()\n first_deadline = connected_at + FIRST_MESSAGE_TIMEOUT_S\n send_lock = threading.Lock()\n done = threading.Event()\n first_msg = threading.Event()\n output_forwarded = threading.Event()\n client_ids = set()\n init_state = {\"initialize_id\": None}\n\n def _send_timeout() -> float:\n # Before the first matching daemon response the remaining first-RPC\n # budget bounds every send; after it each send gets the mid-session\n # write budget. Idle reads are never timed out.\n if not first_msg.is_set():\n return max(0.0, first_deadline - time.monotonic())\n return IO_TIMEOUT_S\n\n def _cleanup_timeout() -> float:\n # Timeout cleanup stays within the expired session budget: once the\n # first-RPC deadline has passed, close directly instead of opening\n # fresh windows that let a short budget take several timeout periods.\n if not first_msg.is_set():\n return max(0.0, first_deadline - time.monotonic())\n return CONNECT_TIMEOUT_S\n\n def send_pong(payload: bytes) -> None:\n locked_send(sock, send_lock, payload, opcode=0xA, timeout=_send_timeout())\n recv = _buffered_reader(sock, pending)\n t = threading.Thread(target=stdout_writer, args=(sock, recv, send_pong, done, first_msg, output_forwarded, client_ids, init_state), daemon=True)\n t.start()\n # Byte-precise commit point: the fallback may run only while zero stdin\n # bytes have left the pipe and no daemon payload was committed to stdout.\n # Reads use os.read into a userspace line buffer (buffered readline could\n # readahead past the commit point), and every byte read counts -- even a\n # blank line. first_msg tracks the matching daemon response/error, never\n # a notification.\n stdin_bytes = 0\n pending_in = b\"\"\n clean_eof = False\n try:\n fd = sys.stdin.fileno()\n while not done.is_set():\n if not first_msg.is_set() and time.monotonic() >= first_deadline:\n log(\"first daemon message timed out\")\n break\n ready, _, _ = select.select([fd], [], [], 0.5)\n if not ready:\n continue\n chunk = os.read(fd, 65536)\n if not chunk:\n clean_eof = True\n break\n stdin_bytes += len(chunk)\n pending_in += chunk\n while b\"\\n\" in pending_in:\n line, _, pending_in = pending_in.partition(b\"\\n\")\n line = line.strip()\n if not line:\n continue\n try:\n try:\n obj = json.loads(line.decode(\"utf-8\"))\n except Exception:\n obj = None\n if isinstance(obj, dict) and obj.get(\"id\") is not None:\n client_ids.add(obj.get(\"id\"))\n if obj.get(\"method\") == \"initialize\" and init_state[\"initialize_id\"] is None:\n init_state[\"initialize_id\"] = obj.get(\"id\")\n except Exception:\n pass\n try:\n locked_send(sock, send_lock, line, timeout=_send_timeout())\n except TimeoutError as e:\n log(f\"stdin forward timed out: {e}\")\n break\n except Exception as e:\n log(f\"stdin forward failed: {e}\")\n break\n else:\n continue\n break\n except Exception as e:\n log(f\"stdin loop exit: {e}\")\n # Flush any buffered EOF-tail data BEFORE the WS Close: sending Close\n # first would let the daemon discard the tail.\n if clean_eof:\n tail = pending_in.strip()\n if tail and not done.is_set():\n try:\n locked_send(sock, send_lock, tail, timeout=_cleanup_timeout())\n except Exception as e:\n log(f\"eof flush failed: {e}\")\n try:\n locked_send(sock, send_lock, b\"\", opcode=0x8, timeout=_cleanup_timeout())\n except Exception as e:\n log(f\"close send failed: {e}\")\n try:\n try:\n sock.shutdown(socket.SHUT_RDWR)\n except OSError:\n pass\n sock.close()\n except OSError:\n pass\n # Bound termination: wake the reader so no thread is left hung on recv.\n t.join(timeout=0.5)\n # A reader still exiting could commit output after this check. In that\n # case pristine stdio cannot be proven, so never permit fallback.\n if t.is_alive():\n output_forwarded.set()\n if clean_eof:\n log(\"exit\")\n return EXIT_SERVED\n # Reader died, first RPC timed out, post-upgrade I/O timed out, or stdin\n # broke: fail open only while stdio is still pristine -- no stdin byte\n # ever consumed AND no daemon payload ever committed to stdout. Committed\n # output forces a mid-session exit so Desktop reconnects instead of\n # falling back to stock Codex on a corrupted stream.\n rc = EXIT_MID_SESSION if (stdin_bytes or output_forwarded.is_set()) else EXIT_PRE_STDIO\n log(f\"exit rc={rc}\")\n return rc\n\nif __name__ == \"__main__\":\n raise SystemExit(main())\n";
|
|
27809
|
+
|
|
27810
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27811
|
+
}, {
|
|
27812
|
+
w: BRIDGE_SOURCE
|
|
27813
|
+
});
|
|
27814
|
+
|
|
27815
|
+
|
|
27816
|
+
},
|
|
27817
|
+
"./src/core/desktop-shim.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
27818
|
+
/* import */ var node_child_process__rspack_import_0 = __webpack_require__("node:child_process");
|
|
27819
|
+
/* import */ var node_fs__rspack_import_1 = __webpack_require__("node:fs");
|
|
27820
|
+
/* import */ var node_os__rspack_import_2 = __webpack_require__("node:os");
|
|
27821
|
+
/* import */ var node_path__rspack_import_3 = __webpack_require__("node:path");
|
|
27822
|
+
/* import */ var _desktop_shim_bridge_js__rspack_import_4 = __webpack_require__("./src/core/desktop-shim-bridge.js");
|
|
27823
|
+
|
|
27824
|
+
|
|
27825
|
+
|
|
27826
|
+
|
|
27827
|
+
|
|
27828
|
+
/**
|
|
27829
|
+
* ChatGPT Desktop -> managed Codex daemon shim (CODEX_CLI_PATH bridge).
|
|
27830
|
+
*
|
|
27831
|
+
* Desktop injects `codex_app` overrides so CODEX_APP_SERVER_USE_LOCAL_DAEMON=1
|
|
27832
|
+
* alone cannot select the managed daemon, and stock `codex app-server proxy`
|
|
27833
|
+
* hangs for Desktop stdio. The winning path is a wrapper on CODEX_CLI_PATH
|
|
27834
|
+
* that rewrites Desktop's `codex ... app-server` spawn into the stdio<->WS
|
|
27835
|
+
* bridge (desktop-shim-bridge.js) onto the managed control socket.
|
|
27836
|
+
* Provenance: uploads/codex-desktop-to-daemon + codex-desktop-shared-daemon-env.sh.
|
|
27837
|
+
*
|
|
27838
|
+
* Fail-open is the hard rule: the wrapper execs the real standalone `codex`
|
|
27839
|
+
* for non-app-server spawns and whenever the bridge/python/socket side is
|
|
27840
|
+
* missing or broken. Never touches Desktop binaries, /tmp/codex-browser-use/,
|
|
27841
|
+
* or CODEX_APP_TOOLS_PIPE_PATH. No protocol change: gbot already speaks the
|
|
27842
|
+
* managed control socket.
|
|
27843
|
+
*/ const SHIM_LABEL = "com.zackjackson.codex-desktop-shared-daemon";
|
|
27844
|
+
const WRAPPER_FILENAME = "codex-desktop-to-daemon";
|
|
27845
|
+
const BRIDGE_FILENAME = "codex-stdio-to-daemon-ws.py";
|
|
27846
|
+
const ENV_SCRIPT_FILENAME = "codex-desktop-shared-daemon-env.sh";
|
|
27847
|
+
const BRIDGE_LOG_FILENAME = "codex-stdio-to-daemon-ws.log";
|
|
27848
|
+
const WRAPPER_LOG_FILENAME = "codex-desktop-to-daemon.log";
|
|
27849
|
+
const ENV_LOG_FILENAME = "codex-desktop-shared-daemon-env.log";
|
|
27850
|
+
const STANDALONE_REAL_SUFFIX = (0,node_path__rspack_import_3.join)("packages", "standalone", "current", "bin", "codex");
|
|
27851
|
+
function codexHomeDir(env = process.env) {
|
|
27852
|
+
return env.CODEX_HOME || join(env.HOME || homedir(), ".codex");
|
|
27853
|
+
}
|
|
27854
|
+
function userHomeDir(env = process.env) {
|
|
27855
|
+
return env.HOME || (0,node_os__rspack_import_2.homedir)();
|
|
27856
|
+
}
|
|
27857
|
+
function defaultPaths({ env = process.env, home = userHomeDir(env) } = {}) {
|
|
27858
|
+
const codexHome = env.CODEX_HOME || (0,node_path__rspack_import_3.join)(home, ".codex");
|
|
27859
|
+
const binDir = (0,node_path__rspack_import_3.join)(codexHome, "bin");
|
|
27860
|
+
return {
|
|
27861
|
+
binDir,
|
|
27862
|
+
bridgeLogPath: (0,node_path__rspack_import_3.join)(binDir, BRIDGE_LOG_FILENAME),
|
|
27863
|
+
bridgePath: (0,node_path__rspack_import_3.join)(binDir, BRIDGE_FILENAME),
|
|
27864
|
+
codexHome,
|
|
27865
|
+
envLogPath: (0,node_path__rspack_import_3.join)(binDir, ENV_LOG_FILENAME),
|
|
27866
|
+
envScriptPath: (0,node_path__rspack_import_3.join)(binDir, ENV_SCRIPT_FILENAME),
|
|
27867
|
+
label: SHIM_LABEL,
|
|
27868
|
+
launchAgentsDir: (0,node_path__rspack_import_3.join)(home, "Library", "LaunchAgents"),
|
|
27869
|
+
plistPath: (0,node_path__rspack_import_3.join)(home, "Library", "LaunchAgents", `${SHIM_LABEL}.plist`),
|
|
27870
|
+
realPath: (0,node_path__rspack_import_3.join)(codexHome, STANDALONE_REAL_SUFFIX),
|
|
27871
|
+
socketPath: (0,node_path__rspack_import_3.join)(codexHome, "app-server-control", "app-server-control.sock"),
|
|
27872
|
+
wrapperLogPath: (0,node_path__rspack_import_3.join)(binDir, WRAPPER_LOG_FILENAME),
|
|
27873
|
+
wrapperPath: (0,node_path__rspack_import_3.join)(binDir, WRAPPER_FILENAME)
|
|
27874
|
+
};
|
|
27875
|
+
}
|
|
27876
|
+
/**
|
|
27877
|
+
* Pure passthrough decision, mirroring the wrapper's argv scan. True only for
|
|
27878
|
+
* a bare `app-server` spawn: Desktop's private-stdio case. `daemon`, `proxy`,
|
|
27879
|
+
* and schema generations always exec the real Codex.
|
|
27880
|
+
*/ function shouldBridge(argv) {
|
|
27881
|
+
let appServer = false;
|
|
27882
|
+
let daemon = false;
|
|
27883
|
+
let proxy = false;
|
|
27884
|
+
let generate = false;
|
|
27885
|
+
for (const arg of argv ?? []){
|
|
27886
|
+
if (arg === "app-server") appServer = true;
|
|
27887
|
+
else if (arg === "daemon") daemon = true;
|
|
27888
|
+
else if (arg === "proxy") proxy = true;
|
|
27889
|
+
else if (arg === "generate-ts" || arg === "generate-json-schema") generate = true;
|
|
27890
|
+
}
|
|
27891
|
+
return appServer && !daemon && !proxy && !generate;
|
|
27892
|
+
}
|
|
27893
|
+
function renderWrapperScript({ realPath, bridgePath, wrapperLogPath, codexHome, bridgeLogPath }) {
|
|
27894
|
+
return `#!/bin/bash
|
|
27895
|
+
# Installed by \`gbot codex desktop-shim install\`. Rewrites ChatGPT Desktop's
|
|
27896
|
+
# \`codex ... app-server\` spawn into a stdio<->WebSocket bridge onto the managed
|
|
27897
|
+
# daemon's control socket. Reversible: \`gbot codex desktop-shim uninstall\`.
|
|
27898
|
+
# The daemon is kept up by the LaunchAgent login script, not here: this hot path
|
|
27899
|
+
# never starts the daemon itself, so a wedged daemon lock cannot hang
|
|
27900
|
+
# Desktop. Fail-open runs ONLY while stdio is still pristine (no stdin
|
|
27901
|
+
# consumed, no stdout written): an absent socket fails the preflight and a
|
|
27902
|
+
# pre-session bridge failure (exit 1) falls through
|
|
27903
|
+
# to the real standalone codex on pristine stdio. A mid-session bridge failure
|
|
27904
|
+
# (exit 2+) exits promptly so Desktop reconnects; the fallback never runs on
|
|
27905
|
+
# half-consumed stdin or dirty stdout. Bridge exit 0 means it served the session. Never touches
|
|
27906
|
+
# Desktop binaries or its private tool pipe.
|
|
27907
|
+
set -u
|
|
27908
|
+
REAL="\${CODEX_DESKTOP_WRAPPER_REAL:-${realPath}}"
|
|
27909
|
+
BRIDGE="\${CODEX_DESKTOP_BRIDGE:-${bridgePath}}"
|
|
27910
|
+
export CODEX_HOME="\${CODEX_HOME:-${codexHome}}"
|
|
27911
|
+
SOCK="\${CODEX_APP_SERVER_SOCK:-$CODEX_HOME/app-server-control/app-server-control.sock}"
|
|
27912
|
+
BRIDGE_LOG="\${CODEX_STDIO_BRIDGE_LOG:-${bridgeLogPath}}"
|
|
27913
|
+
LOG="\${CODEX_DESKTOP_WRAPPER_LOG:-${wrapperLogPath}}"
|
|
27914
|
+
export CODEX_APP_SERVER_SOCK="$SOCK"
|
|
27915
|
+
export CODEX_STDIO_BRIDGE_LOG="$BRIDGE_LOG"
|
|
27916
|
+
ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|
|
27917
|
+
echo "$(ts) argv: $*" >>"$LOG" 2>/dev/null || true
|
|
27918
|
+
|
|
27919
|
+
if [[ ! -x "$REAL" ]]; then
|
|
27920
|
+
FALLBACK="$(command -v codex 2>/dev/null || true)"
|
|
27921
|
+
if [[ -n "$FALLBACK" && -x "$FALLBACK" ]]; then
|
|
27922
|
+
if [[ "$FALLBACK" -ef "$0" ]] 2>/dev/null || { [[ -n "\${CODEX_CLI_PATH:-}" ]] && [[ "$FALLBACK" -ef "\${CODEX_CLI_PATH}" ]] 2>/dev/null; }; then
|
|
27923
|
+
echo "$(ts) refusing self fallback $FALLBACK" >>"$LOG" 2>/dev/null || true
|
|
27924
|
+
else
|
|
27925
|
+
REAL="$FALLBACK"
|
|
27926
|
+
fi
|
|
27927
|
+
fi
|
|
27928
|
+
fi
|
|
27929
|
+
|
|
27930
|
+
has_app_server=0; has_daemon=0; has_proxy=0; has_generate=0
|
|
27931
|
+
for a in "$@"; do
|
|
27932
|
+
case "$a" in
|
|
27933
|
+
app-server) has_app_server=1 ;;
|
|
27934
|
+
daemon) has_daemon=1 ;;
|
|
27935
|
+
proxy) has_proxy=1 ;;
|
|
27936
|
+
generate-ts|generate-json-schema) has_generate=1 ;;
|
|
27937
|
+
esac
|
|
27938
|
+
done
|
|
27939
|
+
|
|
27940
|
+
# Preflight the daemon socket with a short deadline: a refused/absent socket
|
|
27941
|
+
# means starting the bridge could never succeed, so skip straight to real codex.
|
|
27942
|
+
preflight() {
|
|
27943
|
+
python3 -c 'import os,socket,sys; s=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM); s.settimeout(float(os.environ.get("CODEX_DESKTOP_PREFLIGHT_TIMEOUT","3"))); s.connect(sys.argv[1]); s.close()' "$SOCK" 2>/dev/null
|
|
27944
|
+
}
|
|
27945
|
+
|
|
27946
|
+
if [[ "$has_app_server" -eq 1 && "$has_daemon" -eq 0 && "$has_proxy" -eq 0 && "$has_generate" -eq 0 ]]; then
|
|
27947
|
+
if [[ -f "$BRIDGE" ]] && command -v python3 >/dev/null 2>&1; then
|
|
27948
|
+
if preflight; then
|
|
27949
|
+
echo "$(ts) rewrite -> stdio-ws bridge" >>"$LOG" 2>/dev/null || true
|
|
27950
|
+
python3 "$BRIDGE"
|
|
27951
|
+
rc=$?
|
|
27952
|
+
case "$rc" in
|
|
27953
|
+
0)
|
|
27954
|
+
echo "$(ts) bridge served session" >>"$LOG" 2>/dev/null || true
|
|
27955
|
+
exit 0
|
|
27956
|
+
;;
|
|
27957
|
+
1)
|
|
27958
|
+
echo "$(ts) bridge failed before session start, falling through to real codex" >>"$LOG" 2>/dev/null || true
|
|
27959
|
+
;;
|
|
27960
|
+
*)
|
|
27961
|
+
echo "$(ts) bridge failed mid-session (rc=$rc); exiting so Desktop reconnects" >>"$LOG" 2>/dev/null || true
|
|
27962
|
+
exit "$rc"
|
|
27963
|
+
;;
|
|
27964
|
+
esac
|
|
27965
|
+
else
|
|
27966
|
+
echo "$(ts) daemon socket unreachable, passthrough to real codex" >>"$LOG" 2>/dev/null || true
|
|
27967
|
+
fi
|
|
27968
|
+
else
|
|
27969
|
+
echo "$(ts) bridge unavailable, passthrough to real codex" >>"$LOG" 2>/dev/null || true
|
|
27970
|
+
fi
|
|
27971
|
+
fi
|
|
27972
|
+
if [[ -x "$REAL" ]]; then
|
|
27973
|
+
exec "$REAL" "$@"
|
|
27974
|
+
fi
|
|
27975
|
+
echo "codex-desktop-to-daemon: no runnable codex found" >&2
|
|
27976
|
+
exit 1
|
|
27977
|
+
`;
|
|
27978
|
+
}
|
|
27979
|
+
function renderEnvScript({ wrapperPath, realPath, envLogPath, codexHome }) {
|
|
27980
|
+
return `#!/bin/bash
|
|
27981
|
+
# Installed by \`gbot codex desktop-shim install\`. Re-applies the GUI-domain env
|
|
27982
|
+
# so ChatGPT.app inherits CODEX_CLI_PATH after login, then best-effort starts the
|
|
27983
|
+
# managed daemon (this login script — never Desktop's spawn hot path — owns
|
|
27984
|
+
# daemon upkeep). No -e: every step is best-effort so login never breaks.
|
|
27985
|
+
# Revert: \`gbot codex desktop-shim uninstall\`.
|
|
27986
|
+
set -u
|
|
27987
|
+
WRAPPER="${wrapperPath}"
|
|
27988
|
+
REAL="${realPath}"
|
|
27989
|
+
LOG="${envLogPath}"
|
|
27990
|
+
CODEX_HOME_DIR="${codexHome}"
|
|
27991
|
+
# One CODEX_HOME for the GUI domain and this script's own daemon start, so the
|
|
27992
|
+
# daemon that is kept up is the one the wrapper bridges to.
|
|
27993
|
+
export CODEX_HOME="$CODEX_HOME_DIR"
|
|
27994
|
+
ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|
|
27995
|
+
{
|
|
27996
|
+
echo "$(ts) start"
|
|
27997
|
+
if [[ ! -x "$WRAPPER" ]]; then
|
|
27998
|
+
echo "$(ts) missing wrapper: $WRAPPER"
|
|
27999
|
+
exit 0
|
|
28000
|
+
fi
|
|
28001
|
+
# GUI domain setenv so ChatGPT.app inherits CODEX_CLI_PATH after login
|
|
28002
|
+
launchctl setenv CODEX_CLI_PATH "$WRAPPER"
|
|
28003
|
+
launchctl setenv CODEX_HOME "$CODEX_HOME_DIR"
|
|
28004
|
+
launchctl setenv CODEX_APP_SERVER_USE_LOCAL_DAEMON 1
|
|
28005
|
+
launchctl unsetenv CODEX_APP_SERVER_WS_URL 2>/dev/null || true
|
|
28006
|
+
echo "$(ts) CODEX_CLI_PATH=$(launchctl getenv CODEX_CLI_PATH)"
|
|
28007
|
+
if [[ -x "$REAL" ]]; then
|
|
28008
|
+
"$REAL" app-server daemon start >/dev/null 2>&1 || true
|
|
28009
|
+
echo "$(ts) daemon start attempted"
|
|
28010
|
+
fi
|
|
28011
|
+
echo "$(ts) done"
|
|
28012
|
+
} >>"$LOG" 2>&1
|
|
28013
|
+
`;
|
|
28014
|
+
}
|
|
28015
|
+
function renderPlist({ envScriptPath, label = SHIM_LABEL }) {
|
|
28016
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
28017
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
28018
|
+
<plist version="1.0">
|
|
28019
|
+
<dict>
|
|
28020
|
+
\t<key>Label</key>
|
|
28021
|
+
\t<string>${label}</string>
|
|
28022
|
+
\t<key>ProgramArguments</key>
|
|
28023
|
+
\t<array>
|
|
28024
|
+
\t\t<string>/bin/bash</string>
|
|
28025
|
+
\t\t<string>${envScriptPath}</string>
|
|
28026
|
+
\t</array>
|
|
28027
|
+
\t<key>RunAtLoad</key>
|
|
28028
|
+
\t<true/>
|
|
28029
|
+
\t<key>LimitLoadToSessionType</key>
|
|
28030
|
+
\t<string>Aqua</string>
|
|
28031
|
+
</dict>
|
|
28032
|
+
</plist>
|
|
28033
|
+
`;
|
|
28034
|
+
}
|
|
28035
|
+
const defaultRunner = (file, args)=>{
|
|
28036
|
+
try {
|
|
28037
|
+
return (0,node_child_process__rspack_import_0.spawnSync)(file, args, {
|
|
28038
|
+
encoding: "utf8",
|
|
28039
|
+
timeout: 15000
|
|
28040
|
+
});
|
|
28041
|
+
} catch (error) {
|
|
28042
|
+
return {
|
|
28043
|
+
error,
|
|
28044
|
+
status: null
|
|
28045
|
+
};
|
|
28046
|
+
}
|
|
28047
|
+
};
|
|
28048
|
+
function runBestEffort(runner, warnings, what, file, args) {
|
|
28049
|
+
const out = runner(file, args);
|
|
28050
|
+
if (out && (out.error || typeof out.status === "number" && out.status !== 0)) {
|
|
28051
|
+
const detail = out.error && out.error.message || out.stderr && String(out.stderr).trim() || `exit ${out.status}`;
|
|
28052
|
+
warnings.push(`${what} failed (${detail}); continuing`);
|
|
28053
|
+
}
|
|
28054
|
+
return out;
|
|
28055
|
+
}
|
|
28056
|
+
function writeExecutable(path, content) {
|
|
28057
|
+
(0,node_fs__rspack_import_1.writeFileSync)(path, content, {
|
|
28058
|
+
mode: 493
|
|
28059
|
+
});
|
|
28060
|
+
(0,node_fs__rspack_import_1.chmodSync)(path, 493);
|
|
28061
|
+
}
|
|
28062
|
+
function isExecutable(path) {
|
|
28063
|
+
try {
|
|
28064
|
+
(0,node_fs__rspack_import_1.statSync)(path);
|
|
28065
|
+
} catch {
|
|
28066
|
+
return false;
|
|
28067
|
+
}
|
|
28068
|
+
try {
|
|
28069
|
+
// X_OK without throwing: accessSync is clearer; stat mode bit check is sync-safe.
|
|
28070
|
+
return ((0,node_fs__rspack_import_1.statSync)(path).mode & 73) !== 0;
|
|
28071
|
+
} catch {
|
|
28072
|
+
return false;
|
|
28073
|
+
}
|
|
28074
|
+
}
|
|
28075
|
+
function fileExists(path) {
|
|
28076
|
+
try {
|
|
28077
|
+
(0,node_fs__rspack_import_1.statSync)(path);
|
|
28078
|
+
return true;
|
|
28079
|
+
} catch {
|
|
28080
|
+
return false;
|
|
28081
|
+
}
|
|
28082
|
+
}
|
|
28083
|
+
/**
|
|
28084
|
+
* Copy the wrapper + bridge + login env script out of the package into durable
|
|
28085
|
+
* ~/.codex paths (never a git checkout), then persist CODEX_CLI_PATH for the
|
|
28086
|
+
* macOS Aqua session via LaunchAgent. Idempotent.
|
|
28087
|
+
*/ function installDesktopShim({ env = process.env, home = userHomeDir(env), platform = process.platform, runner = defaultRunner } = {}) {
|
|
28088
|
+
const paths = defaultPaths({
|
|
28089
|
+
env,
|
|
28090
|
+
home
|
|
28091
|
+
});
|
|
28092
|
+
const warnings = [];
|
|
28093
|
+
(0,node_fs__rspack_import_1.mkdirSync)(paths.binDir, {
|
|
28094
|
+
recursive: true
|
|
28095
|
+
});
|
|
28096
|
+
writeExecutable(paths.wrapperPath, renderWrapperScript(paths));
|
|
28097
|
+
(0,node_fs__rspack_import_1.writeFileSync)(paths.bridgePath, _desktop_shim_bridge_js__rspack_import_4/* .BRIDGE_SOURCE.endsWith */.w.endsWith("\n") ? _desktop_shim_bridge_js__rspack_import_4/* .BRIDGE_SOURCE */.w : `${_desktop_shim_bridge_js__rspack_import_4/* .BRIDGE_SOURCE */.w}\n`, {
|
|
28098
|
+
mode: 420
|
|
28099
|
+
});
|
|
28100
|
+
writeExecutable(paths.envScriptPath, renderEnvScript(paths));
|
|
28101
|
+
let persisted = false;
|
|
28102
|
+
if (platform === "darwin") {
|
|
28103
|
+
(0,node_fs__rspack_import_1.mkdirSync)(paths.launchAgentsDir, {
|
|
28104
|
+
recursive: true
|
|
28105
|
+
});
|
|
28106
|
+
(0,node_fs__rspack_import_1.writeFileSync)(paths.plistPath, renderPlist({
|
|
28107
|
+
envScriptPath: paths.envScriptPath
|
|
28108
|
+
}), {
|
|
28109
|
+
mode: 420
|
|
28110
|
+
});
|
|
28111
|
+
const uid = typeof process.getuid === "function" ? process.getuid() : null;
|
|
28112
|
+
if (uid === null || uid === undefined) {
|
|
28113
|
+
warnings.push("could not determine uid; LaunchAgent file written but not bootstrapped — log out/in or bootstrap it manually");
|
|
28114
|
+
} else {
|
|
28115
|
+
const target = `gui/${uid}/${paths.label}`;
|
|
28116
|
+
runBestEffort(runner, warnings, "launchctl bootout (previous agent)", "launchctl", [
|
|
28117
|
+
"bootout",
|
|
28118
|
+
target
|
|
28119
|
+
]);
|
|
28120
|
+
runBestEffort(runner, warnings, "launchctl bootstrap", "launchctl", [
|
|
28121
|
+
"bootstrap",
|
|
28122
|
+
`gui/${uid}`,
|
|
28123
|
+
paths.plistPath
|
|
28124
|
+
]);
|
|
28125
|
+
}
|
|
28126
|
+
runBestEffort(runner, warnings, "launchctl setenv CODEX_CLI_PATH", "launchctl", [
|
|
28127
|
+
"setenv",
|
|
28128
|
+
"CODEX_CLI_PATH",
|
|
28129
|
+
paths.wrapperPath
|
|
28130
|
+
]);
|
|
28131
|
+
runBestEffort(runner, warnings, "launchctl setenv CODEX_APP_SERVER_USE_LOCAL_DAEMON", "launchctl", [
|
|
28132
|
+
"setenv",
|
|
28133
|
+
"CODEX_APP_SERVER_USE_LOCAL_DAEMON",
|
|
28134
|
+
"1"
|
|
28135
|
+
]);
|
|
28136
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_APP_SERVER_WS_URL", "launchctl", [
|
|
28137
|
+
"unsetenv",
|
|
28138
|
+
"CODEX_APP_SERVER_WS_URL"
|
|
28139
|
+
]);
|
|
28140
|
+
persisted = true;
|
|
28141
|
+
} else {
|
|
28142
|
+
warnings.push("LaunchAgent persistence is macOS-only; wrapper and bridge installed — export CODEX_CLI_PATH manually");
|
|
28143
|
+
}
|
|
28144
|
+
if (isExecutable(paths.realPath)) {
|
|
28145
|
+
runBestEffort(runner, warnings, "codex app-server daemon start", paths.realPath, [
|
|
28146
|
+
"app-server",
|
|
28147
|
+
"daemon",
|
|
28148
|
+
"start"
|
|
28149
|
+
]);
|
|
28150
|
+
} else {
|
|
28151
|
+
warnings.push(`managed daemon not started: no executable at ${paths.realPath}`);
|
|
28152
|
+
}
|
|
28153
|
+
return {
|
|
28154
|
+
action: "install",
|
|
28155
|
+
bridgePath: paths.bridgePath,
|
|
28156
|
+
envScriptPath: paths.envScriptPath,
|
|
28157
|
+
exitCode: 0,
|
|
28158
|
+
persisted,
|
|
28159
|
+
plistPath: platform === "darwin" ? paths.plistPath : null,
|
|
28160
|
+
realPath: paths.realPath,
|
|
28161
|
+
warnings,
|
|
28162
|
+
wrapperPath: paths.wrapperPath
|
|
28163
|
+
};
|
|
28164
|
+
}
|
|
28165
|
+
/** Remove what install wrote and unset the GUI env; Desktop/Codex fall back to stock. */ function uninstallDesktopShim({ env = process.env, home = userHomeDir(env), platform = process.platform, runner = defaultRunner } = {}) {
|
|
28166
|
+
const paths = defaultPaths({
|
|
28167
|
+
env,
|
|
28168
|
+
home
|
|
28169
|
+
});
|
|
28170
|
+
const warnings = [];
|
|
28171
|
+
const removed = [];
|
|
28172
|
+
for (const path of [
|
|
28173
|
+
paths.wrapperPath,
|
|
28174
|
+
paths.bridgePath,
|
|
28175
|
+
paths.envScriptPath
|
|
28176
|
+
]){
|
|
28177
|
+
const existed = fileExists(path);
|
|
28178
|
+
try {
|
|
28179
|
+
if ((0,node_fs__rspack_import_1.rmSync)(path, {
|
|
28180
|
+
force: true
|
|
28181
|
+
}) === undefined && fileExists(path)) warnings.push(`could not remove ${path}`);
|
|
28182
|
+
else if (existed && !fileExists(path)) removed.push(path);
|
|
28183
|
+
} catch (error) {
|
|
28184
|
+
warnings.push(`could not remove ${path} (${error instanceof Error ? error.message : String(error)})`);
|
|
28185
|
+
}
|
|
28186
|
+
}
|
|
28187
|
+
let plistRemoved = false;
|
|
28188
|
+
if (platform === "darwin") {
|
|
28189
|
+
const uid = typeof process.getuid === "function" ? process.getuid() : null;
|
|
28190
|
+
if (uid !== null && uid !== undefined) {
|
|
28191
|
+
runBestEffort(runner, warnings, "launchctl bootout", "launchctl", [
|
|
28192
|
+
"bootout",
|
|
28193
|
+
`gui/${uid}/${paths.label}`
|
|
28194
|
+
]);
|
|
28195
|
+
}
|
|
28196
|
+
try {
|
|
28197
|
+
(0,node_fs__rspack_import_1.rmSync)(paths.plistPath, {
|
|
28198
|
+
force: true
|
|
28199
|
+
});
|
|
28200
|
+
plistRemoved = !fileExists(paths.plistPath);
|
|
28201
|
+
} catch (error) {
|
|
28202
|
+
warnings.push(`could not remove ${paths.plistPath} (${error instanceof Error ? error.message : String(error)})`);
|
|
28203
|
+
}
|
|
28204
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_CLI_PATH", "launchctl", [
|
|
28205
|
+
"unsetenv",
|
|
28206
|
+
"CODEX_CLI_PATH"
|
|
28207
|
+
]);
|
|
28208
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_HOME", "launchctl", [
|
|
28209
|
+
"unsetenv",
|
|
28210
|
+
"CODEX_HOME"
|
|
28211
|
+
]);
|
|
28212
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_APP_SERVER_USE_LOCAL_DAEMON", "launchctl", [
|
|
28213
|
+
"unsetenv",
|
|
28214
|
+
"CODEX_APP_SERVER_USE_LOCAL_DAEMON"
|
|
28215
|
+
]);
|
|
28216
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_APP_SERVER_WS_URL", "launchctl", [
|
|
28217
|
+
"unsetenv",
|
|
28218
|
+
"CODEX_APP_SERVER_WS_URL"
|
|
28219
|
+
]);
|
|
28220
|
+
}
|
|
28221
|
+
return {
|
|
28222
|
+
action: "uninstall",
|
|
28223
|
+
exitCode: 0,
|
|
28224
|
+
plistPath: platform === "darwin" ? paths.plistPath : null,
|
|
28225
|
+
plistRemoved,
|
|
28226
|
+
removed,
|
|
28227
|
+
warnings,
|
|
28228
|
+
wrapperPath: paths.wrapperPath
|
|
28229
|
+
};
|
|
28230
|
+
}
|
|
28231
|
+
function socketStateOf(path) {
|
|
28232
|
+
try {
|
|
28233
|
+
return (0,node_fs__rspack_import_1.statSync)(path).isSocket() ? "socket" : "not-a-socket";
|
|
28234
|
+
} catch (error) {
|
|
28235
|
+
return error && (error.code === "EACCES" || error.code === "EPERM") ? "permission-denied" : "absent";
|
|
28236
|
+
}
|
|
28237
|
+
}
|
|
28238
|
+
/**
|
|
28239
|
+
* Inspect the shim without touching Desktop, pipes, or sockets beyond a stat.
|
|
28240
|
+
* On macOS the Desktop-facing CODEX_CLI_PATH lives in launchd's GUI domain,
|
|
28241
|
+
* which a shell-spawned `gbot` does not inherit — so status queries
|
|
28242
|
+
* `launchctl getenv` there (via the injectable runner) and reports the caller
|
|
28243
|
+
* environment separately. Elsewhere the process env is the whole story.
|
|
28244
|
+
*/ function desktopShimStatus({ env = process.env, home = userHomeDir(env), platform = process.platform, runner = defaultRunner } = {}) {
|
|
28245
|
+
const paths = defaultPaths({
|
|
28246
|
+
env,
|
|
28247
|
+
home
|
|
28248
|
+
});
|
|
28249
|
+
const warnings = [];
|
|
28250
|
+
const wrapperPresent = fileExists(paths.wrapperPath);
|
|
28251
|
+
const bridgePresent = fileExists(paths.bridgePath);
|
|
28252
|
+
const envScriptPresent = fileExists(paths.envScriptPath);
|
|
28253
|
+
const plistPresent = platform === "darwin" ? fileExists(paths.plistPath) : false;
|
|
28254
|
+
const cliPath = env.CODEX_CLI_PATH || null;
|
|
28255
|
+
let guiCliPath = null;
|
|
28256
|
+
if (platform === "darwin") {
|
|
28257
|
+
try {
|
|
28258
|
+
const out = runner("launchctl", [
|
|
28259
|
+
"getenv",
|
|
28260
|
+
"CODEX_CLI_PATH"
|
|
28261
|
+
]);
|
|
28262
|
+
const value = out && typeof out.stdout === "string" ? out.stdout.trim() : "";
|
|
28263
|
+
guiCliPath = value || null;
|
|
28264
|
+
if (out && (out.error || typeof out.status === "number" && out.status !== 0)) {
|
|
28265
|
+
warnings.push("launchctl getenv CODEX_CLI_PATH failed; GUI-domain state unknown");
|
|
28266
|
+
guiCliPath = null;
|
|
28267
|
+
}
|
|
28268
|
+
} catch (error) {
|
|
28269
|
+
warnings.push(`launchctl getenv CODEX_CLI_PATH failed (${error instanceof Error ? error.message : String(error)})`);
|
|
28270
|
+
guiCliPath = null;
|
|
28271
|
+
}
|
|
28272
|
+
}
|
|
28273
|
+
// Desktop-facing value: the GUI domain on macOS, the caller env elsewhere.
|
|
28274
|
+
const desktopCliPath = platform === "darwin" ? guiCliPath : cliPath;
|
|
28275
|
+
const installed = wrapperPresent && isExecutable(paths.wrapperPath) && bridgePresent;
|
|
28276
|
+
// Effective socket, resolved exactly like gbot's own client (CODEX_APP_SERVER_SOCK
|
|
28277
|
+
// wins, else the install-time CODEX_HOME) so status and send/queue/status never
|
|
28278
|
+
// disagree. Inlined here so codex-bridge can reuse desktopShimStatus without a cycle.
|
|
28279
|
+
const socketPath = env.CODEX_APP_SERVER_SOCK || (0,node_path__rspack_import_3.join)(paths.codexHome, "app-server-control", "app-server-control.sock");
|
|
28280
|
+
return {
|
|
28281
|
+
action: "status",
|
|
28282
|
+
bridgePath: paths.bridgePath,
|
|
28283
|
+
bridgePresent,
|
|
28284
|
+
cliPath,
|
|
28285
|
+
codexHome: paths.codexHome,
|
|
28286
|
+
desktopCliPath,
|
|
28287
|
+
envScriptPath: paths.envScriptPath,
|
|
28288
|
+
envScriptPresent,
|
|
28289
|
+
exitCode: installed ? 0 : 1,
|
|
28290
|
+
guiCliPath,
|
|
28291
|
+
installed,
|
|
28292
|
+
persisted: platform === "darwin" ? plistPresent : null,
|
|
28293
|
+
platform,
|
|
28294
|
+
plistPath: platform === "darwin" ? paths.plistPath : null,
|
|
28295
|
+
plistPresent,
|
|
28296
|
+
realPath: paths.realPath,
|
|
28297
|
+
socketPath,
|
|
28298
|
+
socketSource: env.CODEX_APP_SERVER_SOCK ? "CODEX_APP_SERVER_SOCK" : "CODEX_HOME",
|
|
28299
|
+
socketState: socketStateOf(socketPath),
|
|
28300
|
+
warnings,
|
|
28301
|
+
wrapperExecutable: wrapperPresent && isExecutable(paths.wrapperPath),
|
|
28302
|
+
wrapperPath: paths.wrapperPath,
|
|
28303
|
+
wrapperPointsAtShim: desktopCliPath === paths.wrapperPath,
|
|
28304
|
+
wrapperPresent
|
|
28305
|
+
};
|
|
28306
|
+
}
|
|
28307
|
+
|
|
28308
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
28309
|
+
B0: () => (installDesktopShim),
|
|
28310
|
+
em: () => (desktopShimStatus),
|
|
28311
|
+
gM: () => (uninstallDesktopShim)
|
|
28312
|
+
});
|
|
28313
|
+
|
|
28314
|
+
|
|
27477
28315
|
},
|
|
27478
28316
|
"./src/core/format.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
27479
28317
|
/* import */ var _transcript_js__rspack_import_0 = __webpack_require__("./src/core/transcript.js");
|
|
@@ -27546,6 +28384,7 @@ function formatCodexStatus(s) {
|
|
|
27546
28384
|
const lines = [
|
|
27547
28385
|
"socket: " + s.socketPath + " (" + s.socketState + ")"
|
|
27548
28386
|
];
|
|
28387
|
+
if (s.desktopShimConfigured) lines.push("desktop shim: configured (managed attachment unverified)");
|
|
27549
28388
|
if (!s.reachable) return lines.concat("reachable: no (" + s.mode + ")", s.message).join("\n");
|
|
27550
28389
|
if (s.mode !== "daemon") {
|
|
27551
28390
|
return lines.concat("reachable: yes, but unusable (" + s.mode + ")", s.message).join("\n");
|
|
@@ -27553,7 +28392,7 @@ function formatCodexStatus(s) {
|
|
|
27553
28392
|
lines.push("reachable: yes (daemon)");
|
|
27554
28393
|
const cli = s.cliVersion ?? (s.cliVersionProbe === "ok" ? "unknown" : "unknown, probe " + s.cliVersionProbe);
|
|
27555
28394
|
lines.push("daemon version: " + (s.daemonVersion ?? "unknown") + " cli version: " + cli + " pinned schema: " + s.pinnedVersion + " (" + s.schema.compatibility + ")");
|
|
27556
|
-
lines.push("desktop attached: unknown (not observable from the socket)");
|
|
28395
|
+
lines.push(s.desktopAttached === "private-stdio" ? "desktop attached: private-stdio (Desktop-bundled app-server process observed; managed attachment unverified)" : "desktop attached: unknown (not observable from the socket)");
|
|
27557
28396
|
if (s.versionMismatch) {
|
|
27558
28397
|
lines.push("warning: daemon and CLI versions differ; `codex app-server daemon restart` picks up the installed CLI");
|
|
27559
28398
|
}
|
|
@@ -27568,12 +28407,37 @@ function formatCodexThread(t) {
|
|
|
27568
28407
|
const preview = t.preview ? "\n " + stripTerminalControls(String(t.preview).replace(/\s+/g, " ")).slice(0, 200) : "";
|
|
27569
28408
|
return stripTerminalControls(t.id) + " " + stripTerminalControls(t.status) + title + "\n " + stripTerminalControls(t.cwd ?? "") + preview;
|
|
27570
28409
|
}
|
|
28410
|
+
/** Shell-safe single-quoting for copy-pasteable export lines (spaces, quotes, $). */ function shellQuote(value) {
|
|
28411
|
+
return "'" + String(value).replace(/'/g, "'\\''") + "'";
|
|
28412
|
+
}
|
|
28413
|
+
function formatDesktopShimStatus(s) {
|
|
28414
|
+
const mark = (ok)=>ok ? "yes" : "no";
|
|
28415
|
+
const cliLine = s.platform === "darwin" ? "CODEX_CLI_PATH: GUI domain " + (s.guiCliPath ?? "(unset)") + " / this shell " + (s.cliPath ?? "(unset)") + (s.wrapperPointsAtShim ? " (Desktop-facing value points at shim)" : "") : "CODEX_CLI_PATH: " + (s.cliPath ?? "(unset)") + (s.wrapperPointsAtShim ? " (points at shim)" : "");
|
|
28416
|
+
const lines = [
|
|
28417
|
+
"wrapper: " + s.wrapperPath + " (" + (s.wrapperExecutable ? "executable" : s.wrapperPresent ? "present, not executable" : "absent") + ")",
|
|
28418
|
+
"bridge: " + s.bridgePath + " (" + mark(s.bridgePresent) + ")",
|
|
28419
|
+
"login env: " + s.envScriptPath + " (" + mark(s.envScriptPresent) + ")",
|
|
28420
|
+
s.platform === "darwin" ? "LaunchAgent: " + s.plistPath + " (" + mark(s.plistPresent) + ")" : "LaunchAgent: n/a (macOS-only)",
|
|
28421
|
+
cliLine,
|
|
28422
|
+
"daemon socket: " + s.socketPath + " (" + s.socketState + ", from " + (s.socketSource ?? "CODEX_HOME") + ")"
|
|
28423
|
+
];
|
|
28424
|
+
if (!s.installed) {
|
|
28425
|
+
lines.push("shim: not installed — run `gbot codex desktop-shim install` (Desktop keeps stock behavior until then)");
|
|
28426
|
+
} else if (!s.wrapperPointsAtShim) {
|
|
28427
|
+
lines.push(s.platform === "darwin" ? "shim: installed but CODEX_CLI_PATH does not point at it — reinstall or relaunch ChatGPT.app after login" : "shim: installed but CODEX_CLI_PATH does not point at it — export CODEX_CLI_PATH=" + shellQuote(s.wrapperPath));
|
|
28428
|
+
} else {
|
|
28429
|
+
lines.push("shim: active — Desktop app-server spawns bridge onto the managed daemon");
|
|
28430
|
+
}
|
|
28431
|
+
for (const warning of s.warnings ?? [])lines.push("warning: " + String(warning));
|
|
28432
|
+
return lines.join("\n");
|
|
28433
|
+
}
|
|
27571
28434
|
|
|
27572
28435
|
__webpack_require__.d(__webpack_exports__, {
|
|
27573
28436
|
P2: () => (formatCodexStatus),
|
|
27574
28437
|
bM: () => (formatRecord),
|
|
27575
28438
|
e_: () => (formatCodexQueue),
|
|
27576
28439
|
eh: () => (summarize),
|
|
28440
|
+
fX: () => (formatDesktopShimStatus),
|
|
27577
28441
|
nz: () => (formatCodexThread),
|
|
27578
28442
|
oZ: () => (formatTranscript)
|
|
27579
28443
|
});
|
|
@@ -28657,6 +29521,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
28657
29521
|
* never *.cursorvm.com, so a CURSOR_ACCESS_TOKEN cannot be pointed at a box host.
|
|
28658
29522
|
* Local/dev gateways: http(s)://127.0.0.1|localhost|::1 when GROK_BOT_ALLOW_LOCAL_GATEWAY=1.
|
|
28659
29523
|
* Escape hatch: GROK_BOT_ALLOW_ANY_GATEWAY=1 (unsafe; disables host checks; warns once).
|
|
29524
|
+
* Test mode (GROK_BOT_TEST=1 or NODE_ENV=test): loopback only, for gateway and backend
|
|
29525
|
+
* alike, and the escape hatches are ignored — a test can never reach a live thread.
|
|
28660
29526
|
*/ function truthyEnv(name) {
|
|
28661
29527
|
const v = (process.env[name] || "").trim().toLowerCase();
|
|
28662
29528
|
return v === "1" || v === "true" || v === "yes";
|
|
@@ -28667,6 +29533,9 @@ function allowAnyGateway() {
|
|
|
28667
29533
|
function allowLocalGateway() {
|
|
28668
29534
|
return truthyEnv("GROK_BOT_ALLOW_LOCAL_GATEWAY");
|
|
28669
29535
|
}
|
|
29536
|
+
function testMode() {
|
|
29537
|
+
return truthyEnv("GROK_BOT_TEST") || process.env.NODE_ENV === "test";
|
|
29538
|
+
}
|
|
28670
29539
|
const warned = new Set();
|
|
28671
29540
|
function warnOnce(key, message) {
|
|
28672
29541
|
if (warned.has(key)) return;
|
|
@@ -28706,6 +29575,12 @@ function isCursorGatewayHostname(hostname) {
|
|
|
28706
29575
|
if (parsed.username || parsed.password) {
|
|
28707
29576
|
throw new Error("Rejected " + label + ": userinfo is not allowed.");
|
|
28708
29577
|
}
|
|
29578
|
+
if (testMode()) {
|
|
29579
|
+
if (!isLocalHostname(parsed.hostname) || parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
29580
|
+
throw new Error("Rejected " + label + " host \"" + parsed.hostname + "\": test mode (GROK_BOT_TEST / NODE_ENV=test) only allows http(s) loopback gateways.");
|
|
29581
|
+
}
|
|
29582
|
+
return String(rawUrl).replace(/\/$/, "");
|
|
29583
|
+
}
|
|
28709
29584
|
if (allowAnyGateway()) {
|
|
28710
29585
|
warnOnce("ALLOW_ANY", "warning: GROK_BOT_ALLOW_ANY_GATEWAY is set; credential host checks are disabled.");
|
|
28711
29586
|
return String(rawUrl).replace(/\/$/, "");
|
|
@@ -28821,32 +29696,33 @@ __webpack_require__.r = (exports) => {
|
|
|
28821
29696
|
var __webpack_exports__ = {};
|
|
28822
29697
|
/* import */ var node_worker_threads__rspack_import_0 = __webpack_require__("node:worker_threads");
|
|
28823
29698
|
/* import */ var react__rspack_import_1 = __webpack_require__("./node_modules/react/react.react-server.js");
|
|
28824
|
-
/* import */ var
|
|
28825
|
-
/* import */ var
|
|
28826
|
-
/* import */ var
|
|
29699
|
+
/* import */ var _agent_bundle_runtime_flight_server__rspack_import_28 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/flight/server.js");
|
|
29700
|
+
/* import */ var _agent_bundle_runtime__rspack_import_26 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/49.js");
|
|
29701
|
+
/* import */ var _agent_bundle_runtime__rspack_import_27 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
28827
29702
|
/* import */ var node_url__rspack_import_2 = __webpack_require__("node:url");
|
|
28828
29703
|
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_bots_create_tsx__rspack_import_3 = __webpack_require__("./src/cli/bots/create.tsx");
|
|
28829
29704
|
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_bots_delete_tsx__rspack_import_4 = __webpack_require__("./src/cli/bots/delete.tsx");
|
|
28830
29705
|
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_bots_get_tsx__rspack_import_5 = __webpack_require__("./src/cli/bots/get.tsx");
|
|
28831
29706
|
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_bots_list_tsx__rspack_import_6 = __webpack_require__("./src/cli/bots/list.tsx");
|
|
28832
29707
|
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_bots_update_tsx__rspack_import_7 = __webpack_require__("./src/cli/bots/update.tsx");
|
|
28833
|
-
/* import */ var
|
|
28834
|
-
/* import */ var
|
|
28835
|
-
/* import */ var
|
|
28836
|
-
/* import */ var
|
|
28837
|
-
/* import */ var
|
|
28838
|
-
/* import */ var
|
|
28839
|
-
/* import */ var
|
|
28840
|
-
/* import */ var
|
|
28841
|
-
/* import */ var
|
|
28842
|
-
/* import */ var
|
|
28843
|
-
/* import */ var
|
|
28844
|
-
/* import */ var
|
|
28845
|
-
/* import */ var
|
|
28846
|
-
/* import */ var
|
|
28847
|
-
/* import */ var
|
|
28848
|
-
/* import */ var
|
|
28849
|
-
/* import */ var
|
|
29708
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_desktop_shim_tsx__rspack_import_8 = __webpack_require__("./src/cli/codex/desktop-shim.tsx");
|
|
29709
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_list_threads_tsx__rspack_import_9 = __webpack_require__("./src/cli/codex/list-threads.tsx");
|
|
29710
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_queue_tsx__rspack_import_10 = __webpack_require__("./src/cli/codex/queue.tsx");
|
|
29711
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_send_tsx__rspack_import_11 = __webpack_require__("./src/cli/codex/send.tsx");
|
|
29712
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_status_tsx__rspack_import_12 = __webpack_require__("./src/cli/codex/status.tsx");
|
|
29713
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_doctor_tsx__rspack_import_13 = __webpack_require__("./src/cli/doctor.tsx");
|
|
29714
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_add_tsx__rspack_import_14 = __webpack_require__("./src/cli/groups/add.tsx");
|
|
29715
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_create_tsx__rspack_import_15 = __webpack_require__("./src/cli/groups/create.tsx");
|
|
29716
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_delete_tsx__rspack_import_16 = __webpack_require__("./src/cli/groups/delete.tsx");
|
|
29717
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_get_tsx__rspack_import_17 = __webpack_require__("./src/cli/groups/get.tsx");
|
|
29718
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_list_tsx__rspack_import_18 = __webpack_require__("./src/cli/groups/list.tsx");
|
|
29719
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_members_tsx__rspack_import_19 = __webpack_require__("./src/cli/groups/members.tsx");
|
|
29720
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_remove_tsx__rspack_import_20 = __webpack_require__("./src/cli/groups/remove.tsx");
|
|
29721
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_set_tsx__rspack_import_21 = __webpack_require__("./src/cli/groups/set.tsx");
|
|
29722
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_update_tsx__rspack_import_22 = __webpack_require__("./src/cli/groups/update.tsx");
|
|
29723
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_history_tsx__rspack_import_23 = __webpack_require__("./src/cli/history.tsx");
|
|
29724
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_send_tsx__rspack_import_24 = __webpack_require__("./src/cli/send.tsx");
|
|
29725
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_thread_tsx__rspack_import_25 = __webpack_require__("./src/cli/thread.tsx");
|
|
28850
29726
|
|
|
28851
29727
|
|
|
28852
29728
|
|
|
@@ -28863,40 +29739,42 @@ const route3 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok
|
|
|
28863
29739
|
|
|
28864
29740
|
const route4 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_bots_update_tsx__rspack_import_7, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_bots_update_tsx__rspack_import_7);
|
|
28865
29741
|
|
|
28866
|
-
const route5 = Object.assign({}, Reflect.get(
|
|
29742
|
+
const route5 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_desktop_shim_tsx__rspack_import_8, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_desktop_shim_tsx__rspack_import_8);
|
|
29743
|
+
|
|
29744
|
+
const route6 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_list_threads_tsx__rspack_import_9, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_list_threads_tsx__rspack_import_9);
|
|
28867
29745
|
|
|
28868
|
-
const
|
|
29746
|
+
const route7 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_queue_tsx__rspack_import_10, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_queue_tsx__rspack_import_10);
|
|
28869
29747
|
|
|
28870
|
-
const
|
|
29748
|
+
const route8 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_send_tsx__rspack_import_11, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_send_tsx__rspack_import_11);
|
|
28871
29749
|
|
|
28872
|
-
const
|
|
29750
|
+
const route9 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_status_tsx__rspack_import_12, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_codex_status_tsx__rspack_import_12);
|
|
28873
29751
|
|
|
28874
|
-
const
|
|
29752
|
+
const route10 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_doctor_tsx__rspack_import_13, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_doctor_tsx__rspack_import_13);
|
|
28875
29753
|
|
|
28876
|
-
const
|
|
29754
|
+
const route11 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_add_tsx__rspack_import_14, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_add_tsx__rspack_import_14);
|
|
28877
29755
|
|
|
28878
|
-
const
|
|
29756
|
+
const route12 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_create_tsx__rspack_import_15, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_create_tsx__rspack_import_15);
|
|
28879
29757
|
|
|
28880
|
-
const
|
|
29758
|
+
const route13 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_delete_tsx__rspack_import_16, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_delete_tsx__rspack_import_16);
|
|
28881
29759
|
|
|
28882
|
-
const
|
|
29760
|
+
const route14 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_get_tsx__rspack_import_17, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_get_tsx__rspack_import_17);
|
|
28883
29761
|
|
|
28884
|
-
const
|
|
29762
|
+
const route15 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_list_tsx__rspack_import_18, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_list_tsx__rspack_import_18);
|
|
28885
29763
|
|
|
28886
|
-
const
|
|
29764
|
+
const route16 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_members_tsx__rspack_import_19, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_members_tsx__rspack_import_19);
|
|
28887
29765
|
|
|
28888
|
-
const
|
|
29766
|
+
const route17 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_remove_tsx__rspack_import_20, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_remove_tsx__rspack_import_20);
|
|
28889
29767
|
|
|
28890
|
-
const
|
|
29768
|
+
const route18 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_set_tsx__rspack_import_21, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_set_tsx__rspack_import_21);
|
|
28891
29769
|
|
|
28892
|
-
const
|
|
29770
|
+
const route19 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_update_tsx__rspack_import_22, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_groups_update_tsx__rspack_import_22);
|
|
28893
29771
|
|
|
28894
|
-
const
|
|
29772
|
+
const route20 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_history_tsx__rspack_import_23, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_history_tsx__rspack_import_23);
|
|
28895
29773
|
|
|
28896
|
-
const
|
|
29774
|
+
const route21 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_send_tsx__rspack_import_24, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_send_tsx__rspack_import_24);
|
|
28897
29775
|
|
|
28898
|
-
const
|
|
28899
|
-
const pluginRoot = (0,
|
|
29776
|
+
const route22 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_thread_tsx__rspack_import_25, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_cli_thread_tsx__rspack_import_25);
|
|
29777
|
+
const pluginRoot = (0,_agent_bundle_runtime__rspack_import_26/* .resolvePluginRoot */.E7)({
|
|
28900
29778
|
fallback: (0,node_url__rspack_import_2.fileURLToPath)(new URL('..', import.meta.url)),
|
|
28901
29779
|
stateAnchor: 'user-data'
|
|
28902
29780
|
});
|
|
@@ -28944,107 +29822,113 @@ const routes = Object.freeze({
|
|
|
28944
29822
|
name: "bots update",
|
|
28945
29823
|
module: route4
|
|
28946
29824
|
}),
|
|
29825
|
+
"cli:codex/desktop-shim": Object.freeze({
|
|
29826
|
+
id: "cli:codex/desktop-shim",
|
|
29827
|
+
kind: "cli",
|
|
29828
|
+
name: "codex desktop-shim",
|
|
29829
|
+
module: route5
|
|
29830
|
+
}),
|
|
28947
29831
|
"cli:codex/list-threads": Object.freeze({
|
|
28948
29832
|
id: "cli:codex/list-threads",
|
|
28949
29833
|
kind: "cli",
|
|
28950
29834
|
name: "codex list-threads",
|
|
28951
|
-
module:
|
|
29835
|
+
module: route6
|
|
28952
29836
|
}),
|
|
28953
29837
|
"cli:codex/queue": Object.freeze({
|
|
28954
29838
|
id: "cli:codex/queue",
|
|
28955
29839
|
kind: "cli",
|
|
28956
29840
|
name: "codex queue",
|
|
28957
|
-
module:
|
|
29841
|
+
module: route7
|
|
28958
29842
|
}),
|
|
28959
29843
|
"cli:codex/send": Object.freeze({
|
|
28960
29844
|
id: "cli:codex/send",
|
|
28961
29845
|
kind: "cli",
|
|
28962
29846
|
name: "codex send",
|
|
28963
|
-
module:
|
|
29847
|
+
module: route8
|
|
28964
29848
|
}),
|
|
28965
29849
|
"cli:codex/status": Object.freeze({
|
|
28966
29850
|
id: "cli:codex/status",
|
|
28967
29851
|
kind: "cli",
|
|
28968
29852
|
name: "codex status",
|
|
28969
|
-
module:
|
|
29853
|
+
module: route9
|
|
28970
29854
|
}),
|
|
28971
29855
|
"cli:doctor": Object.freeze({
|
|
28972
29856
|
id: "cli:doctor",
|
|
28973
29857
|
kind: "cli",
|
|
28974
29858
|
name: "doctor",
|
|
28975
|
-
module:
|
|
29859
|
+
module: route10
|
|
28976
29860
|
}),
|
|
28977
29861
|
"cli:groups/add": Object.freeze({
|
|
28978
29862
|
id: "cli:groups/add",
|
|
28979
29863
|
kind: "cli",
|
|
28980
29864
|
name: "groups add",
|
|
28981
|
-
module:
|
|
29865
|
+
module: route11
|
|
28982
29866
|
}),
|
|
28983
29867
|
"cli:groups/create": Object.freeze({
|
|
28984
29868
|
id: "cli:groups/create",
|
|
28985
29869
|
kind: "cli",
|
|
28986
29870
|
name: "groups create",
|
|
28987
|
-
module:
|
|
29871
|
+
module: route12
|
|
28988
29872
|
}),
|
|
28989
29873
|
"cli:groups/delete": Object.freeze({
|
|
28990
29874
|
id: "cli:groups/delete",
|
|
28991
29875
|
kind: "cli",
|
|
28992
29876
|
name: "groups delete",
|
|
28993
|
-
module:
|
|
29877
|
+
module: route13
|
|
28994
29878
|
}),
|
|
28995
29879
|
"cli:groups/get": Object.freeze({
|
|
28996
29880
|
id: "cli:groups/get",
|
|
28997
29881
|
kind: "cli",
|
|
28998
29882
|
name: "groups get",
|
|
28999
|
-
module:
|
|
29883
|
+
module: route14
|
|
29000
29884
|
}),
|
|
29001
29885
|
"cli:groups/list": Object.freeze({
|
|
29002
29886
|
id: "cli:groups/list",
|
|
29003
29887
|
kind: "cli",
|
|
29004
29888
|
name: "groups list",
|
|
29005
|
-
module:
|
|
29889
|
+
module: route15
|
|
29006
29890
|
}),
|
|
29007
29891
|
"cli:groups/members": Object.freeze({
|
|
29008
29892
|
id: "cli:groups/members",
|
|
29009
29893
|
kind: "cli",
|
|
29010
29894
|
name: "groups members",
|
|
29011
|
-
module:
|
|
29895
|
+
module: route16
|
|
29012
29896
|
}),
|
|
29013
29897
|
"cli:groups/remove": Object.freeze({
|
|
29014
29898
|
id: "cli:groups/remove",
|
|
29015
29899
|
kind: "cli",
|
|
29016
29900
|
name: "groups remove",
|
|
29017
|
-
module:
|
|
29901
|
+
module: route17
|
|
29018
29902
|
}),
|
|
29019
29903
|
"cli:groups/set": Object.freeze({
|
|
29020
29904
|
id: "cli:groups/set",
|
|
29021
29905
|
kind: "cli",
|
|
29022
29906
|
name: "groups set",
|
|
29023
|
-
module:
|
|
29907
|
+
module: route18
|
|
29024
29908
|
}),
|
|
29025
29909
|
"cli:groups/update": Object.freeze({
|
|
29026
29910
|
id: "cli:groups/update",
|
|
29027
29911
|
kind: "cli",
|
|
29028
29912
|
name: "groups update",
|
|
29029
|
-
module:
|
|
29913
|
+
module: route19
|
|
29030
29914
|
}),
|
|
29031
29915
|
"cli:history": Object.freeze({
|
|
29032
29916
|
id: "cli:history",
|
|
29033
29917
|
kind: "cli",
|
|
29034
29918
|
name: "history",
|
|
29035
|
-
module:
|
|
29919
|
+
module: route20
|
|
29036
29920
|
}),
|
|
29037
29921
|
"cli:send": Object.freeze({
|
|
29038
29922
|
id: "cli:send",
|
|
29039
29923
|
kind: "cli",
|
|
29040
29924
|
name: "send",
|
|
29041
|
-
module:
|
|
29925
|
+
module: route21
|
|
29042
29926
|
}),
|
|
29043
29927
|
"cli:thread": Object.freeze({
|
|
29044
29928
|
id: "cli:thread",
|
|
29045
29929
|
kind: "cli",
|
|
29046
29930
|
name: "thread",
|
|
29047
|
-
module:
|
|
29931
|
+
module: route22
|
|
29048
29932
|
})
|
|
29049
29933
|
});
|
|
29050
29934
|
const requests = new Map();
|
|
@@ -29079,18 +29963,18 @@ const render = async (message)=>{
|
|
|
29079
29963
|
};
|
|
29080
29964
|
try {
|
|
29081
29965
|
const cwd = process.cwd();
|
|
29082
|
-
await (0,
|
|
29966
|
+
await (0,_agent_bundle_runtime__rspack_import_27/* .runAgentRequest */.iC)({
|
|
29083
29967
|
capabilities: {
|
|
29084
|
-
command: (0,
|
|
29085
|
-
filesystem: (0,
|
|
29086
|
-
network: (0,
|
|
29087
|
-
projectRoot: (0,
|
|
29968
|
+
command: (0,_agent_bundle_runtime__rspack_import_27/* .unavailable */.hU)(),
|
|
29969
|
+
filesystem: (0,_agent_bundle_runtime__rspack_import_27/* .unavailable */.hU)(),
|
|
29970
|
+
network: (0,_agent_bundle_runtime__rspack_import_27/* .unavailable */.hU)(),
|
|
29971
|
+
projectRoot: (0,_agent_bundle_runtime__rspack_import_27/* .available */.qC)({
|
|
29088
29972
|
root: cwd
|
|
29089
29973
|
}, 'derived')
|
|
29090
29974
|
},
|
|
29091
|
-
host: (0,
|
|
29975
|
+
host: (0,_agent_bundle_runtime__rspack_import_27/* .unavailable */.hU)('unsupported-surface'),
|
|
29092
29976
|
invocation: message.request,
|
|
29093
|
-
lineage: (0,
|
|
29977
|
+
lineage: (0,_agent_bundle_runtime__rspack_import_27/* .unavailable */.hU)('unsupported-surface'),
|
|
29094
29978
|
plugin: pluginRoot.identity,
|
|
29095
29979
|
progress: {
|
|
29096
29980
|
report: async (update)=>{
|
|
@@ -29103,8 +29987,8 @@ const render = async (message)=>{
|
|
|
29103
29987
|
},
|
|
29104
29988
|
process: processHit,
|
|
29105
29989
|
signal: controller.signal,
|
|
29106
|
-
terminal: message.terminal === undefined ? (0,
|
|
29107
|
-
workspace: (0,
|
|
29990
|
+
terminal: message.terminal === undefined ? (0,_agent_bundle_runtime__rspack_import_27/* .unavailable */.hU)('not-provided') : (0,_agent_bundle_runtime__rspack_import_27/* .available */.qC)(message.terminal, 'native'),
|
|
29991
|
+
workspace: (0,_agent_bundle_runtime__rspack_import_27/* .available */.qC)({
|
|
29108
29992
|
root: cwd
|
|
29109
29993
|
}, 'derived')
|
|
29110
29994
|
}, async ()=>{
|
|
@@ -29113,7 +29997,7 @@ const render = async (message)=>{
|
|
|
29113
29997
|
type: 'observed-render-start'
|
|
29114
29998
|
});
|
|
29115
29999
|
const renderStartedAt = performance.now();
|
|
29116
|
-
const flight = (0,
|
|
30000
|
+
const flight = (0,_agent_bundle_runtime_flight_server__rspack_import_28/* .renderAgentFlight */.y)(composeLayouts(observedRoute, {
|
|
29117
30001
|
...message.props,
|
|
29118
30002
|
signal: controller.signal
|
|
29119
30003
|
}, controller.signal), {
|