grok-bot-cli 0.4.5 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +91 -14
- 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/marketplace.json +1 -1
- package/dist/.cursor-plugin/plugin.json +1 -1
- package/dist/INSTALL.md +2 -2
- package/dist/README.md +91 -14
- package/dist/agent-bundle.compile-evidence.json +1 -1
- package/dist/agent-bundle.manifest.json +1 -1
- package/dist/bin/gbot-flight.mjs +2641 -370
- package/dist/bin/gbot.mjs +3019 -354
- package/dist/install.mjs +1 -1
- package/dist/mcp/mcp-grok-bot-b8c2461e-flight.mjs +6811 -2399
- package/dist/mcp/mcp-grok-bot-b8c2461e.mjs +4300 -97
- package/dist/package.json +1 -1
- package/dist/plugin.json +1 -1
- package/dist/scripts/gbot-relay.mjs +61013 -0
- package/dist/skills/talk-to-grok-bot/SKILL.md +70 -6
- package/package.json +1 -1
|
@@ -4,9 +4,11 @@ import * as __rspack_external_node_child_process_cd435d64 from "node:child_proce
|
|
|
4
4
|
import * as __rspack_external_node_crypto_2e7c4b46 from "node:crypto";
|
|
5
5
|
import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
6
6
|
import * as __rspack_external_node_fs_promises_3b710708 from "node:fs/promises";
|
|
7
|
+
import * as __rspack_external_node_net_5ed819e1 from "node:net";
|
|
7
8
|
import * as __rspack_external_node_os_4f3c9d58 from "node:os";
|
|
8
9
|
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
9
10
|
import * as __rspack_external_node_process_ee535471 from "node:process";
|
|
11
|
+
import * as __rspack_external_node_string_decoder_69b9bd04 from "node:string_decoder";
|
|
10
12
|
import * as __rspack_external_node_url_3991086a from "node:url";
|
|
11
13
|
import * as __rspack_external_node_worker_threads_28ca7740 from "node:worker_threads";
|
|
12
14
|
import { createRequire as __rspack_createRequire } from "node:module";
|
|
@@ -10983,6 +10985,412 @@ if (process.env.NODE_ENV === 'production') {
|
|
|
10983
10985
|
}
|
|
10984
10986
|
|
|
10985
10987
|
|
|
10988
|
+
},
|
|
10989
|
+
"./src/core/codex/routes.ts"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
10990
|
+
/* import */ var zod__rspack_import_3 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js");
|
|
10991
|
+
/* import */ var _codex_bridge_js__rspack_import_0 = __webpack_require__("./src/core/codex-bridge.js");
|
|
10992
|
+
/* import */ var _contract_js__rspack_import_1 = __webpack_require__("./src/core/codex/contract.js");
|
|
10993
|
+
/* import */ var _conversation_js__rspack_import_2 = __webpack_require__("./src/core/codex/conversation.js");
|
|
10994
|
+
|
|
10995
|
+
|
|
10996
|
+
|
|
10997
|
+
|
|
10998
|
+
const id = zod__rspack_import_3/* .string */.YjP().regex(/^[A-Za-z0-9_.:-]{1,128}$/);
|
|
10999
|
+
const observationFields = {
|
|
11000
|
+
expectedCwd: zod__rspack_import_3/* .string */.YjP().min(1).optional(),
|
|
11001
|
+
threadId: id,
|
|
11002
|
+
timeoutMs: zod__rspack_import_3/* .number */.aig().int().min(1).max(600000).optional()
|
|
11003
|
+
};
|
|
11004
|
+
const sendFields = {
|
|
11005
|
+
...observationFields,
|
|
11006
|
+
correlationId: id.optional(),
|
|
11007
|
+
envelope: zod__rspack_import_3/* .boolean */.zMY().optional(),
|
|
11008
|
+
hop: zod__rspack_import_3/* .number */.aig().int().min(0).optional(),
|
|
11009
|
+
replyTo: id.optional(),
|
|
11010
|
+
expectedTurnId: id.optional(),
|
|
11011
|
+
whenBusy: zod__rspack_import_3/* ["enum"] */.k5n([
|
|
11012
|
+
'reject',
|
|
11013
|
+
'queue',
|
|
11014
|
+
'steer'
|
|
11015
|
+
]).default('reject'),
|
|
11016
|
+
wait: zod__rspack_import_3/* .boolean */.zMY().default(false),
|
|
11017
|
+
maxOutputBytes: zod__rspack_import_3/* .number */.aig().int().min(1).max(4194304).optional()
|
|
11018
|
+
};
|
|
11019
|
+
const sendSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11020
|
+
...sendFields,
|
|
11021
|
+
message: zod__rspack_import_3/* .string */.YjP().min(1).max(4194304)
|
|
11022
|
+
}).strict();
|
|
11023
|
+
const waitSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11024
|
+
...observationFields,
|
|
11025
|
+
turnId: id,
|
|
11026
|
+
messageId: id.optional(),
|
|
11027
|
+
maxOutputBytes: zod__rspack_import_3/* .number */.aig().int().min(1).max(4194304).optional()
|
|
11028
|
+
}).strict();
|
|
11029
|
+
const watchSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11030
|
+
...observationFields,
|
|
11031
|
+
maxEvents: zod__rspack_import_3/* .number */.aig().int().min(1).max(500).default(100)
|
|
11032
|
+
}).strict();
|
|
11033
|
+
const threadsSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11034
|
+
limit: zod__rspack_import_3/* .number */.aig().int().min(1).max(200).default(20),
|
|
11035
|
+
cursor: zod__rspack_import_3/* .string */.YjP().min(1).max(4096).optional()
|
|
11036
|
+
}).strict();
|
|
11037
|
+
const resultSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11038
|
+
exitCode: zod__rspack_import_3/* .number */.aig().int().min(0).max(1),
|
|
11039
|
+
threadId: zod__rspack_import_3/* .string */.YjP().optional(),
|
|
11040
|
+
turnId: zod__rspack_import_3/* .string */.YjP().optional(),
|
|
11041
|
+
messageId: zod__rspack_import_3/* .string */.YjP().optional(),
|
|
11042
|
+
delivery: zod__rspack_import_3/* ["enum"] */.k5n([
|
|
11043
|
+
'accepted',
|
|
11044
|
+
'queued',
|
|
11045
|
+
'rejected',
|
|
11046
|
+
'unknown'
|
|
11047
|
+
]).optional(),
|
|
11048
|
+
execution: zod__rspack_import_3/* .object */.Ikc({
|
|
11049
|
+
state: zod__rspack_import_3/* ["enum"] */.k5n([
|
|
11050
|
+
'completed',
|
|
11051
|
+
'failed',
|
|
11052
|
+
'interrupted',
|
|
11053
|
+
'waiting-for-input',
|
|
11054
|
+
'timeout',
|
|
11055
|
+
'disconnected',
|
|
11056
|
+
'unknown'
|
|
11057
|
+
]),
|
|
11058
|
+
error: zod__rspack_import_3/* .unknown */.L5J().optional()
|
|
11059
|
+
}).optional(),
|
|
11060
|
+
reply: zod__rspack_import_3/* .object */.Ikc({
|
|
11061
|
+
text: zod__rspack_import_3/* .string */.YjP().max(4194304),
|
|
11062
|
+
items: zod__rspack_import_3/* .array */.YOg(zod__rspack_import_3/* .object */.Ikc({
|
|
11063
|
+
id: zod__rspack_import_3/* .string */.YjP(),
|
|
11064
|
+
type: zod__rspack_import_3/* .literal */.euz('agentMessage'),
|
|
11065
|
+
phase: zod__rspack_import_3/* ["enum"] */.k5n([
|
|
11066
|
+
'final_answer'
|
|
11067
|
+
]).nullable(),
|
|
11068
|
+
text: zod__rspack_import_3/* .string */.YjP().max(4194304)
|
|
11069
|
+
})).max(2000),
|
|
11070
|
+
truncated: zod__rspack_import_3/* .boolean */.zMY()
|
|
11071
|
+
}).optional(),
|
|
11072
|
+
interactions: zod__rspack_import_3/* .array */.YOg(zod__rspack_import_3/* .record */.g1P(zod__rspack_import_3/* .string */.YjP(), zod__rspack_import_3/* .unknown */.L5J())).max(500).optional(),
|
|
11073
|
+
events: zod__rspack_import_3/* .array */.YOg(zod__rspack_import_3/* .record */.g1P(zod__rspack_import_3/* .string */.YjP(), zod__rspack_import_3/* .unknown */.L5J())).max(500).optional(),
|
|
11074
|
+
reason: zod__rspack_import_3/* .string */.YjP().optional(),
|
|
11075
|
+
truncated: zod__rspack_import_3/* .boolean */.zMY().optional()
|
|
11076
|
+
}).passthrough();
|
|
11077
|
+
async function sendOperation(input, signal, progress, oneShot = false) {
|
|
11078
|
+
let envelope;
|
|
11079
|
+
let receipt;
|
|
11080
|
+
try {
|
|
11081
|
+
envelope = (0,_codex_bridge_js__rspack_import_0/* .buildEnvelope */.nq)(input);
|
|
11082
|
+
if (oneShot && !input.wait && input.whenBusy !== 'steer') {
|
|
11083
|
+
return await (0,_codex_bridge_js__rspack_import_0/* .sendToCodexThread */.ZS)(input.threadId, input.message, {
|
|
11084
|
+
envelope,
|
|
11085
|
+
whenBusy: input.whenBusy,
|
|
11086
|
+
expectedCwd: input.expectedCwd,
|
|
11087
|
+
signal
|
|
11088
|
+
});
|
|
11089
|
+
}
|
|
11090
|
+
await progress?.('Opening Codex conversation');
|
|
11091
|
+
const conversation = await (0,_conversation_js__rspack_import_2/* .openCodexConversation */.j)(input.threadId, {
|
|
11092
|
+
expectedCwd: input.expectedCwd,
|
|
11093
|
+
signal
|
|
11094
|
+
});
|
|
11095
|
+
try {
|
|
11096
|
+
receipt = await conversation.send(input.message, {
|
|
11097
|
+
envelope,
|
|
11098
|
+
whenBusy: input.whenBusy,
|
|
11099
|
+
expectedTurnId: input.expectedTurnId
|
|
11100
|
+
});
|
|
11101
|
+
if (!input.wait || receipt.delivery !== 'accepted' || !receipt.turnId) return receipt;
|
|
11102
|
+
await progress?.(`Accepted message ${receipt.messageId}; observing turn ${receipt.turnId}`);
|
|
11103
|
+
const result = await conversation.wait({
|
|
11104
|
+
turnId: receipt.turnId,
|
|
11105
|
+
messageId: receipt.messageId,
|
|
11106
|
+
timeoutMs: input.timeoutMs,
|
|
11107
|
+
maxOutputBytes: input.maxOutputBytes,
|
|
11108
|
+
signal
|
|
11109
|
+
});
|
|
11110
|
+
return {
|
|
11111
|
+
...receipt,
|
|
11112
|
+
execution: result.execution,
|
|
11113
|
+
reply: result.reply,
|
|
11114
|
+
interactions: result.interactions,
|
|
11115
|
+
exitCode: result.execution.state === 'completed' ? 0 : 1
|
|
11116
|
+
};
|
|
11117
|
+
} finally{
|
|
11118
|
+
await conversation.close();
|
|
11119
|
+
}
|
|
11120
|
+
} catch (error) {
|
|
11121
|
+
if (receipt?.delivery === 'accepted') return {
|
|
11122
|
+
...receipt,
|
|
11123
|
+
execution: {
|
|
11124
|
+
state: 'unknown',
|
|
11125
|
+
error: (0,_contract_js__rspack_import_1/* .outcomeFromError */.DG)(error).error
|
|
11126
|
+
},
|
|
11127
|
+
reply: {
|
|
11128
|
+
text: '',
|
|
11129
|
+
items: [],
|
|
11130
|
+
truncated: true
|
|
11131
|
+
},
|
|
11132
|
+
interactions: [],
|
|
11133
|
+
exitCode: 1
|
|
11134
|
+
};
|
|
11135
|
+
return {
|
|
11136
|
+
...(0,_contract_js__rspack_import_1/* .outcomeFromError */.DG)(error),
|
|
11137
|
+
threadId: input.threadId,
|
|
11138
|
+
...envelope ? {
|
|
11139
|
+
messageId: envelope.messageId,
|
|
11140
|
+
correlationId: envelope.correlationId,
|
|
11141
|
+
hop: envelope.hop
|
|
11142
|
+
} : {}
|
|
11143
|
+
};
|
|
11144
|
+
}
|
|
11145
|
+
}
|
|
11146
|
+
async function observeOperation(kind, input, signal, progress) {
|
|
11147
|
+
try {
|
|
11148
|
+
await progress?.(`Observing Codex thread ${input.threadId}`);
|
|
11149
|
+
const conversation = await (0,_conversation_js__rspack_import_2/* .openCodexConversation */.j)(input.threadId, {
|
|
11150
|
+
expectedCwd: input.expectedCwd,
|
|
11151
|
+
signal
|
|
11152
|
+
});
|
|
11153
|
+
try {
|
|
11154
|
+
if (kind === 'wait') {
|
|
11155
|
+
const result = await conversation.wait({
|
|
11156
|
+
...input,
|
|
11157
|
+
signal
|
|
11158
|
+
});
|
|
11159
|
+
return {
|
|
11160
|
+
...result,
|
|
11161
|
+
exitCode: result.execution.state === 'completed' ? 0 : 1
|
|
11162
|
+
};
|
|
11163
|
+
}
|
|
11164
|
+
const result = await conversation.watch({
|
|
11165
|
+
...input,
|
|
11166
|
+
signal
|
|
11167
|
+
});
|
|
11168
|
+
return {
|
|
11169
|
+
...result,
|
|
11170
|
+
exitCode: [
|
|
11171
|
+
'timeout',
|
|
11172
|
+
'event-limit'
|
|
11173
|
+
].includes(result.reason) ? 0 : 1
|
|
11174
|
+
};
|
|
11175
|
+
} finally{
|
|
11176
|
+
await conversation.close();
|
|
11177
|
+
}
|
|
11178
|
+
} catch (error) {
|
|
11179
|
+
return {
|
|
11180
|
+
...(0,_contract_js__rspack_import_1/* .outcomeFromError */.DG)(error),
|
|
11181
|
+
threadId: input.threadId,
|
|
11182
|
+
...'turnId' in input ? {
|
|
11183
|
+
turnId: input.turnId,
|
|
11184
|
+
messageId: input.messageId
|
|
11185
|
+
} : {}
|
|
11186
|
+
};
|
|
11187
|
+
}
|
|
11188
|
+
}
|
|
11189
|
+
async function threadsOperation(input) {
|
|
11190
|
+
try {
|
|
11191
|
+
return {
|
|
11192
|
+
...await (0,_codex_bridge_js__rspack_import_0/* .listCodexThreads */.X$)(input),
|
|
11193
|
+
exitCode: 0
|
|
11194
|
+
};
|
|
11195
|
+
} catch (error) {
|
|
11196
|
+
return (0,_contract_js__rspack_import_1/* .outcomeFromError */.DG)(error);
|
|
11197
|
+
}
|
|
11198
|
+
}
|
|
11199
|
+
function resultText(result) {
|
|
11200
|
+
if (result.execution && typeof result.execution === 'object' && 'state' in result.execution) return `Codex turn ${result.turnId}: ${result.execution.state}`;
|
|
11201
|
+
if (result.delivery === 'queued') return `Queued ${result.queuedSubmissionId} on busy Codex thread ${result.threadId}; message ${result.messageId}`;
|
|
11202
|
+
if (result.error) return String(result.error);
|
|
11203
|
+
if (result.delivery === 'accepted') return `Started turn ${result.turnId} (${result.turnStatus}) on Codex thread ${result.threadId}; message ${result.messageId}`;
|
|
11204
|
+
if (result.delivery) return `Codex delivery ${result.delivery} on thread ${result.threadId}`;
|
|
11205
|
+
if (result.reason) return `Codex observation: ${result.reason}`;
|
|
11206
|
+
if (Array.isArray(result.threads)) return `${result.threads.length} Codex threads`;
|
|
11207
|
+
return String(result.error ?? 'Codex observation complete');
|
|
11208
|
+
}
|
|
11209
|
+
|
|
11210
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
11211
|
+
$c: () => (threadsOperation),
|
|
11212
|
+
D6: () => (resultText),
|
|
11213
|
+
UP: () => (sendOperation),
|
|
11214
|
+
gT: () => (observeOperation)
|
|
11215
|
+
}, {
|
|
11216
|
+
FD: resultSchema,
|
|
11217
|
+
P3: threadsSchema,
|
|
11218
|
+
R9: watchSchema,
|
|
11219
|
+
Wi: sendSchema,
|
|
11220
|
+
jS: waitSchema
|
|
11221
|
+
});
|
|
11222
|
+
|
|
11223
|
+
|
|
11224
|
+
},
|
|
11225
|
+
"./src/core/relay/routes.ts"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
11226
|
+
/* import */ var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/40.js");
|
|
11227
|
+
/* import */ var zod__rspack_import_3 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js");
|
|
11228
|
+
/* import */ var _managed_js__rspack_import_0 = __webpack_require__("./src/core/relay/managed.js");
|
|
11229
|
+
/* import */ var _gbot_js__rspack_import_1 = __webpack_require__("./src/gbot.ts");
|
|
11230
|
+
/* import */ var _codex_bridge_js__rspack_import_2 = __webpack_require__("./src/core/codex-bridge.js");
|
|
11231
|
+
|
|
11232
|
+
|
|
11233
|
+
|
|
11234
|
+
|
|
11235
|
+
|
|
11236
|
+
const id = zod__rspack_import_3/* .string */.YjP().min(1).max(128);
|
|
11237
|
+
const routeFields = {
|
|
11238
|
+
codexThreadId: id.optional(),
|
|
11239
|
+
expectedCwd: zod__rspack_import_3/* .string */.YjP().min(1).max(4096).optional(),
|
|
11240
|
+
bindingId: zod__rspack_import_3/* .string */.YjP().min(1).max(512).optional(),
|
|
11241
|
+
requestId: id.optional()
|
|
11242
|
+
};
|
|
11243
|
+
const grokSendSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11244
|
+
target: zod__rspack_import_3/* .string */.YjP().min(1),
|
|
11245
|
+
message: zod__rspack_import_3/* .string */.YjP().min(1),
|
|
11246
|
+
replyMode: zod__rspack_import_3/* ["enum"] */.k5n([
|
|
11247
|
+
"auto",
|
|
11248
|
+
"manual"
|
|
11249
|
+
]).optional(),
|
|
11250
|
+
hop: zod__rspack_import_3/* .number */.aig().int().min(0).optional(),
|
|
11251
|
+
correlationId: id.optional(),
|
|
11252
|
+
...routeFields
|
|
11253
|
+
}).strict();
|
|
11254
|
+
const bridgeStartSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11255
|
+
grokTarget: zod__rspack_import_3/* .string */.YjP().min(1),
|
|
11256
|
+
codexThreadId: id.optional(),
|
|
11257
|
+
expectedCwd: zod__rspack_import_3/* .string */.YjP().min(1).max(4096).optional(),
|
|
11258
|
+
busyPolicy: zod__rspack_import_3/* ["enum"] */.k5n([
|
|
11259
|
+
"steer",
|
|
11260
|
+
"reject"
|
|
11261
|
+
]).optional(),
|
|
11262
|
+
requestId: id.optional()
|
|
11263
|
+
}).strict();
|
|
11264
|
+
const bridgeStatusSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11265
|
+
bindingId: zod__rspack_import_3/* .string */.YjP().min(1).max(512).optional(),
|
|
11266
|
+
limit: zod__rspack_import_3/* .number */.aig().int().min(1).max(100).optional()
|
|
11267
|
+
}).strict();
|
|
11268
|
+
const bridgeStopSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11269
|
+
bindingId: zod__rspack_import_3/* .string */.YjP().min(1).max(512).optional(),
|
|
11270
|
+
all: zod__rspack_import_3/* .boolean */.zMY().optional(),
|
|
11271
|
+
worker: zod__rspack_import_3/* .boolean */.zMY().optional()
|
|
11272
|
+
}).strict().refine((x)=>!!x.bindingId || x.all === true || x.worker === true, "Specify bindingId, all or worker");
|
|
11273
|
+
const respondSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
11274
|
+
interactionId: zod__rspack_import_3/* .string */.YjP().min(1).max(512),
|
|
11275
|
+
generation: id,
|
|
11276
|
+
threadId: id,
|
|
11277
|
+
turnId: id,
|
|
11278
|
+
bindingId: zod__rspack_import_3/* .string */.YjP().min(1).max(512).optional(),
|
|
11279
|
+
exchangeId: zod__rspack_import_3/* .string */.YjP().min(1).max(512).optional(),
|
|
11280
|
+
decision: zod__rspack_import_3/* ["enum"] */.k5n([
|
|
11281
|
+
"accept",
|
|
11282
|
+
"decline",
|
|
11283
|
+
"cancel"
|
|
11284
|
+
]).optional(),
|
|
11285
|
+
answersJson: zod__rspack_import_3/* .string */.YjP().min(2).max(65536).optional()
|
|
11286
|
+
}).strict().refine((x)=>!!x.bindingId || !!x.exchangeId, "Binding or exchange scope required").refine((x)=>!!x.decision !== !!x.answersJson, "Supply decision or answersJson");
|
|
11287
|
+
const answersSchema = zod__rspack_import_3/* .record */.g1P(zod__rspack_import_3/* .string */.YjP().min(1).max(128), zod__rspack_import_3/* .object */.Ikc({
|
|
11288
|
+
answers: zod__rspack_import_3/* .array */.YOg(zod__rspack_import_3/* .string */.YjP().max(8192)).max(20)
|
|
11289
|
+
}).strict());
|
|
11290
|
+
const relayResultSchema = zod__rspack_import_3/* .record */.g1P(zod__rspack_import_3/* .string */.YjP(), zod__rspack_import_3/* .json */.Pq9());
|
|
11291
|
+
function nativeCodexThread(context) {
|
|
11292
|
+
return context.host.state === "available" && (0,_agent_bundle_runtime__rspack_import_4/* .lineageHostFromClient */.bg)(context.host.value.name) === "codex" && context.lineage.state === "available" && context.lineage.source === "native" && context.lineage.value.resolution === "native" ? context.lineage.value.conversation : undefined;
|
|
11293
|
+
}
|
|
11294
|
+
function options(context) {
|
|
11295
|
+
return {
|
|
11296
|
+
pluginRoot: context?.plugin.state === "available" ? context.plugin.value.root : undefined,
|
|
11297
|
+
signal: context?.signal
|
|
11298
|
+
};
|
|
11299
|
+
}
|
|
11300
|
+
function destination(input, context) {
|
|
11301
|
+
const codexThreadId = input.codexThreadId ?? (context ? nativeCodexThread(context) : undefined);
|
|
11302
|
+
// Native workspace evidence belongs to the invocation, not the plugin installation directory.
|
|
11303
|
+
const workspace = context?.workspace;
|
|
11304
|
+
const expectedCwd = input.expectedCwd ?? (workspace?.state === "available" && workspace.source === "native" ? workspace.value.root : undefined);
|
|
11305
|
+
return {
|
|
11306
|
+
codexThreadId,
|
|
11307
|
+
expectedCwd
|
|
11308
|
+
};
|
|
11309
|
+
}
|
|
11310
|
+
async function grokSendOperation(input, context) {
|
|
11311
|
+
const route = destination(input, input.bindingId ? undefined : context);
|
|
11312
|
+
if (input.replyMode !== "manual" && (input.bindingId || route.codexThreadId)) return (0,_gbot_js__rspack_import_1/* .withRedactedErrors */.yF)(()=>(0,_managed_js__rspack_import_0/* .managedOperation */.Bb)("sendToGrok", {
|
|
11313
|
+
grokTarget: input.target,
|
|
11314
|
+
message: input.message,
|
|
11315
|
+
hop: input.hop,
|
|
11316
|
+
correlationId: input.correlationId,
|
|
11317
|
+
...route,
|
|
11318
|
+
...input.bindingId ? {
|
|
11319
|
+
bindingId: input.bindingId
|
|
11320
|
+
} : {},
|
|
11321
|
+
...input.requestId ? {
|
|
11322
|
+
requestId: input.requestId
|
|
11323
|
+
} : {}
|
|
11324
|
+
}, options(context)));
|
|
11325
|
+
if (input.replyMode === "auto") throw Error("Automatic reply delivery requires a native Codex source, codexThreadId or bindingId");
|
|
11326
|
+
const message = input.hop !== undefined || input.correlationId !== undefined ? (0,_codex_bridge_js__rspack_import_2/* .withEnvelopeHeader */.Mr)(input.message, (0,_codex_bridge_js__rspack_import_2/* .buildEnvelope */.nq)(input)) : input.message;
|
|
11327
|
+
const sent = await (0,_gbot_js__rspack_import_1/* .withRedactedErrors */.yF)(async ()=>(0,_gbot_js__rspack_import_1/* .sendPrompt */.LV)(await (0,_gbot_js__rspack_import_1/* .connectGateway */.Vq)(), input.target, message));
|
|
11328
|
+
return {
|
|
11329
|
+
result: sent.result,
|
|
11330
|
+
target: (0,_gbot_js__rspack_import_1/* .summarizeTarget */.rW)(sent.target),
|
|
11331
|
+
delivery: sent.delivery === "accepted" ? "accepted" : "unknown",
|
|
11332
|
+
...sent.delivery === "accepted" && typeof sent.messageId === "string" ? {
|
|
11333
|
+
messageId: sent.messageId
|
|
11334
|
+
} : {},
|
|
11335
|
+
replyRoute: {
|
|
11336
|
+
mode: "manual",
|
|
11337
|
+
reason: input.replyMode === "manual" ? "requested" : "source-unavailable"
|
|
11338
|
+
}
|
|
11339
|
+
};
|
|
11340
|
+
}
|
|
11341
|
+
async function bridgeOperation(method, input, context) {
|
|
11342
|
+
let routed = method === "startBinding" ? {
|
|
11343
|
+
...input,
|
|
11344
|
+
...destination(input, context)
|
|
11345
|
+
} : input;
|
|
11346
|
+
if (method === "respond") {
|
|
11347
|
+
const { decision, answersJson, ...scope } = respondSchema.parse(input);
|
|
11348
|
+
routed = {
|
|
11349
|
+
...scope,
|
|
11350
|
+
result: decision ? {
|
|
11351
|
+
decision
|
|
11352
|
+
} : {
|
|
11353
|
+
answers: answersSchema.parse(JSON.parse(answersJson))
|
|
11354
|
+
}
|
|
11355
|
+
};
|
|
11356
|
+
}
|
|
11357
|
+
if (method === "startBinding" && !routed.codexThreadId) throw Error("Specify codexThreadId when native Codex source identity is unavailable");
|
|
11358
|
+
return (0,_gbot_js__rspack_import_1/* .withRedactedErrors */.yF)(()=>(0,_managed_js__rspack_import_0/* .managedOperation */.Bb)(method, routed, options(context)));
|
|
11359
|
+
}
|
|
11360
|
+
function assertManagedSendOptions(input) {
|
|
11361
|
+
if (input.expectedTurnId !== undefined) throw Error("Managed relay does not support expectedTurnId; omit it to use managed guarded steering, or use a plain Codex send for an explicit turn guard");
|
|
11362
|
+
if (input.replyTo !== undefined || input.envelope === true) throw Error("Managed relay does not support legacy replyTo/envelope options; omit them or use a plain send. Use hop/correlationId for explicit managed chains");
|
|
11363
|
+
}
|
|
11364
|
+
async function codexReturnOperation(input, context) {
|
|
11365
|
+
assertManagedSendOptions(input);
|
|
11366
|
+
if (input.whenBusy === "queue") throw Error("Managed relay supports steer or reject, not experimental queue");
|
|
11367
|
+
return (0,_gbot_js__rspack_import_1/* .withRedactedErrors */.yF)(()=>(0,_managed_js__rspack_import_0/* .managedOperation */.Bb)("sendToCodex", {
|
|
11368
|
+
grokTarget: input.replyToGrok,
|
|
11369
|
+
codexThreadId: input.threadId,
|
|
11370
|
+
expectedCwd: input.expectedCwd,
|
|
11371
|
+
bindingId: input.bindingId,
|
|
11372
|
+
message: input.message,
|
|
11373
|
+
requestId: input.requestId,
|
|
11374
|
+
busyPolicy: input.whenBusy,
|
|
11375
|
+
hop: input.hop,
|
|
11376
|
+
correlationId: input.correlationId
|
|
11377
|
+
}, options(context)));
|
|
11378
|
+
}
|
|
11379
|
+
|
|
11380
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
11381
|
+
bv: () => (grokSendOperation),
|
|
11382
|
+
lt: () => (codexReturnOperation),
|
|
11383
|
+
n1: () => (bridgeOperation)
|
|
11384
|
+
}, {
|
|
11385
|
+
Ax: relayResultSchema,
|
|
11386
|
+
bw: grokSendSchema,
|
|
11387
|
+
d5: bridgeStopSchema,
|
|
11388
|
+
np: bridgeStatusSchema,
|
|
11389
|
+
v1: respondSchema,
|
|
11390
|
+
xD: bridgeStartSchema
|
|
11391
|
+
});
|
|
11392
|
+
|
|
11393
|
+
|
|
10986
11394
|
},
|
|
10987
11395
|
"./src/gbot.ts"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
10988
11396
|
/* import */ var zod__rspack_import_3 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js");
|
|
@@ -10996,7 +11404,7 @@ if (process.env.NODE_ENV === 'production') {
|
|
|
10996
11404
|
|
|
10997
11405
|
// Hosts and the CLI print thrown error text (and stack), and a fetch or proxy failure can echo
|
|
10998
11406
|
// a credential. Rewrap with a redacted message; keep `name` and own fields such as `reason`,
|
|
10999
|
-
// `delivery`, `mode`, and
|
|
11407
|
+
// `delivery`, `mode`, and correlation ids so outcome documents still classify the failure.
|
|
11000
11408
|
const withRedactedErrors = async (run)=>{
|
|
11001
11409
|
try {
|
|
11002
11410
|
return await run();
|
|
@@ -11095,40 +11503,645 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
11095
11503
|
}, {
|
|
11096
11504
|
Oo: entrySchema,
|
|
11097
11505
|
rW: summarizeTarget,
|
|
11098
|
-
tX: targetSchema,
|
|
11099
11506
|
xw: transcriptEntries,
|
|
11100
11507
|
yF: withRedactedErrors
|
|
11101
11508
|
});
|
|
11102
11509
|
|
|
11103
11510
|
|
|
11104
11511
|
},
|
|
11105
|
-
"./src/mcp/grok-bot/tools/
|
|
11512
|
+
"./src/mcp/grok-bot/tools/codex_send.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
11106
11513
|
__webpack_require__.r(__webpack_exports__);
|
|
11107
11514
|
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js");
|
|
11515
|
+
/* import */ var _agent_bundle_runtime__rspack_import_5 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
11516
|
+
/* import */ var _agent_bundle_runtime__rspack_import_6 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
11517
|
+
/* import */ var agent_bundle_routes__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/routes.js");
|
|
11518
|
+
/* import */ var _core_codex_routes_js__rspack_import_2 = __webpack_require__("./src/core/codex/routes.ts");
|
|
11519
|
+
/* import */ var zod__rspack_import_4 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js");
|
|
11520
|
+
/* import */ var _core_relay_routes_js__rspack_import_3 = __webpack_require__("./src/core/relay/routes.ts");
|
|
11521
|
+
|
|
11522
|
+
|
|
11523
|
+
|
|
11524
|
+
|
|
11525
|
+
|
|
11526
|
+
|
|
11527
|
+
const inputSchema = _core_codex_routes_js__rspack_import_2/* .sendSchema.extend */.Wi.extend({
|
|
11528
|
+
whenBusy: zod__rspack_import_4/* ["enum"] */.k5n([
|
|
11529
|
+
'reject',
|
|
11530
|
+
'queue',
|
|
11531
|
+
'steer'
|
|
11532
|
+
]).optional(),
|
|
11533
|
+
replyToGrok: zod__rspack_import_4/* .string */.YjP().min(1).optional(),
|
|
11534
|
+
bindingId: zod__rspack_import_4/* .string */.YjP().min(1).optional(),
|
|
11535
|
+
requestId: zod__rspack_import_4/* .string */.YjP().min(1).max(128).optional()
|
|
11536
|
+
});
|
|
11537
|
+
const resultSchema = zod__rspack_import_4/* .union */.KCZ([
|
|
11538
|
+
_core_codex_routes_js__rspack_import_2/* .resultSchema */.FD,
|
|
11539
|
+
_core_relay_routes_js__rspack_import_3/* .relayResultSchema */.Ax
|
|
11540
|
+
]);
|
|
11541
|
+
/* export default */ const __rspack_default_export = ((0,agent_bundle_routes__rspack_import_1/* .defineTool */.uO)({
|
|
11542
|
+
description: 'Send to Codex. With replyToGrok or bindingId, managed delivery returns the terminal answer to Grok automatically. Otherwise optional wait observes completion and explicit steer requires expectedTurnId. Acceptance is not completion.',
|
|
11543
|
+
title: 'Codex send',
|
|
11544
|
+
annotations: {
|
|
11545
|
+
readOnlyHint: false
|
|
11546
|
+
},
|
|
11547
|
+
render: {
|
|
11548
|
+
maxElapsedMs: 660000
|
|
11549
|
+
},
|
|
11550
|
+
inputSchema,
|
|
11551
|
+
resultSchema,
|
|
11552
|
+
inputJsonSchema: {
|
|
11553
|
+
type: 'object',
|
|
11554
|
+
properties: {
|
|
11555
|
+
expectedCwd: {
|
|
11556
|
+
type: 'string'
|
|
11557
|
+
},
|
|
11558
|
+
threadId: {
|
|
11559
|
+
type: 'string'
|
|
11560
|
+
},
|
|
11561
|
+
timeoutMs: {
|
|
11562
|
+
type: 'number'
|
|
11563
|
+
},
|
|
11564
|
+
correlationId: {
|
|
11565
|
+
type: 'string'
|
|
11566
|
+
},
|
|
11567
|
+
envelope: {
|
|
11568
|
+
type: 'boolean'
|
|
11569
|
+
},
|
|
11570
|
+
hop: {
|
|
11571
|
+
type: 'number'
|
|
11572
|
+
},
|
|
11573
|
+
replyTo: {
|
|
11574
|
+
type: 'string'
|
|
11575
|
+
},
|
|
11576
|
+
expectedTurnId: {
|
|
11577
|
+
type: 'string'
|
|
11578
|
+
},
|
|
11579
|
+
whenBusy: {
|
|
11580
|
+
type: 'string',
|
|
11581
|
+
enum: [
|
|
11582
|
+
'reject',
|
|
11583
|
+
'queue',
|
|
11584
|
+
'steer'
|
|
11585
|
+
]
|
|
11586
|
+
},
|
|
11587
|
+
wait: {
|
|
11588
|
+
default: false,
|
|
11589
|
+
type: 'boolean'
|
|
11590
|
+
},
|
|
11591
|
+
maxOutputBytes: {
|
|
11592
|
+
type: 'number'
|
|
11593
|
+
},
|
|
11594
|
+
message: {
|
|
11595
|
+
type: 'string'
|
|
11596
|
+
},
|
|
11597
|
+
replyToGrok: {
|
|
11598
|
+
type: 'string'
|
|
11599
|
+
},
|
|
11600
|
+
bindingId: {
|
|
11601
|
+
type: 'string'
|
|
11602
|
+
},
|
|
11603
|
+
requestId: {
|
|
11604
|
+
type: 'string'
|
|
11605
|
+
}
|
|
11606
|
+
},
|
|
11607
|
+
required: [
|
|
11608
|
+
'threadId',
|
|
11609
|
+
'message'
|
|
11610
|
+
],
|
|
11611
|
+
additionalProperties: false
|
|
11612
|
+
}
|
|
11613
|
+
}, async (input)=>{
|
|
11614
|
+
const context = await (0,_agent_bundle_runtime__rspack_import_5/* .agent */.MA)();
|
|
11615
|
+
if (input.replyToGrok || input.bindingId) {
|
|
11616
|
+
const out = await (0,_core_relay_routes_js__rspack_import_3/* .codexReturnOperation */.lt)(input, context);
|
|
11617
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6/* .Agent.Result */.g6.Result, {
|
|
11618
|
+
value: out,
|
|
11619
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6/* .Agent.Text */.g6.Text, {
|
|
11620
|
+
children: `Delivery ${out.delivery}; terminal answer returns to Grok automatically.`
|
|
11621
|
+
})
|
|
11622
|
+
});
|
|
11623
|
+
}
|
|
11624
|
+
const out = await (0,_core_codex_routes_js__rspack_import_2/* .sendOperation */.UP)({
|
|
11625
|
+
...input,
|
|
11626
|
+
whenBusy: input.whenBusy ?? 'reject'
|
|
11627
|
+
}, context.signal, (message)=>context.progress.report({
|
|
11628
|
+
message
|
|
11629
|
+
}));
|
|
11630
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6/* .Agent.Result */.g6.Result, {
|
|
11631
|
+
value: out,
|
|
11632
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6/* .Agent.Text */.g6.Text, {
|
|
11633
|
+
children: (0,_core_codex_routes_js__rspack_import_2/* .resultText */.D6)(out)
|
|
11634
|
+
})
|
|
11635
|
+
});
|
|
11636
|
+
}));
|
|
11637
|
+
|
|
11638
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
11639
|
+
}, {
|
|
11640
|
+
"default": __rspack_default_export,
|
|
11641
|
+
inputSchema: inputSchema
|
|
11642
|
+
});
|
|
11643
|
+
|
|
11644
|
+
|
|
11645
|
+
},
|
|
11646
|
+
"./src/mcp/grok-bot/tools/codex_threads.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
11647
|
+
__webpack_require__.r(__webpack_exports__);
|
|
11648
|
+
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js");
|
|
11649
|
+
/* import */ var _agent_bundle_runtime__rspack_import_3 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
11108
11650
|
/* import */ var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
11109
11651
|
/* import */ var agent_bundle_routes__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/routes.js");
|
|
11110
|
-
/* import */ var
|
|
11111
|
-
/* import */ var _gbot_js__rspack_import_2 = __webpack_require__("./src/gbot.ts");
|
|
11652
|
+
/* import */ var _core_codex_routes_js__rspack_import_2 = __webpack_require__("./src/core/codex/routes.ts");
|
|
11112
11653
|
|
|
11113
11654
|
|
|
11114
11655
|
|
|
11115
11656
|
|
|
11116
11657
|
|
|
11117
|
-
const
|
|
11118
|
-
|
|
11119
|
-
|
|
11658
|
+
/* export default */ const __rspack_default_export = ((0,agent_bundle_routes__rspack_import_1/* .defineTool */.uO)({
|
|
11659
|
+
description: 'Discover a bounded page of Codex daemon threads.',
|
|
11660
|
+
title: 'Codex threads',
|
|
11661
|
+
annotations: {
|
|
11662
|
+
readOnlyHint: true
|
|
11663
|
+
},
|
|
11664
|
+
render: {
|
|
11665
|
+
maxElapsedMs: 660000
|
|
11666
|
+
},
|
|
11667
|
+
inputSchema: _core_codex_routes_js__rspack_import_2/* .threadsSchema */.P3,
|
|
11668
|
+
resultSchema: _core_codex_routes_js__rspack_import_2/* .resultSchema */.FD,
|
|
11669
|
+
inputJsonSchema: {
|
|
11670
|
+
type: 'object',
|
|
11671
|
+
additionalProperties: false,
|
|
11672
|
+
properties: {
|
|
11673
|
+
"limit": {
|
|
11674
|
+
"type": "number",
|
|
11675
|
+
"description": "Maximum threads in this page: 1-200."
|
|
11676
|
+
},
|
|
11677
|
+
"cursor": {
|
|
11678
|
+
"type": "string"
|
|
11679
|
+
}
|
|
11680
|
+
},
|
|
11681
|
+
required: []
|
|
11682
|
+
}
|
|
11683
|
+
}, async (input)=>{
|
|
11684
|
+
const context = await (0,_agent_bundle_runtime__rspack_import_3/* .agent */.MA)();
|
|
11685
|
+
const out = await (0,_core_codex_routes_js__rspack_import_2/* .threadsOperation */.$c)(input);
|
|
11686
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Result */.g6.Result, {
|
|
11687
|
+
value: out,
|
|
11688
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Text */.g6.Text, {
|
|
11689
|
+
children: (0,_core_codex_routes_js__rspack_import_2/* .resultText */.D6)(out)
|
|
11690
|
+
})
|
|
11691
|
+
});
|
|
11692
|
+
}));
|
|
11693
|
+
|
|
11694
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
11695
|
+
inputSchema: () => (/* reexport safe */ _core_codex_routes_js__rspack_import_2.P3)
|
|
11696
|
+
}, {
|
|
11697
|
+
"default": __rspack_default_export
|
|
11120
11698
|
});
|
|
11699
|
+
|
|
11700
|
+
|
|
11701
|
+
},
|
|
11702
|
+
"./src/mcp/grok-bot/tools/codex_wait.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
11703
|
+
__webpack_require__.r(__webpack_exports__);
|
|
11704
|
+
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js");
|
|
11705
|
+
/* import */ var _agent_bundle_runtime__rspack_import_3 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
11706
|
+
/* import */ var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
11707
|
+
/* import */ var agent_bundle_routes__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/routes.js");
|
|
11708
|
+
/* import */ var _core_codex_routes_js__rspack_import_2 = __webpack_require__("./src/core/codex/routes.ts");
|
|
11709
|
+
|
|
11710
|
+
|
|
11711
|
+
|
|
11712
|
+
|
|
11713
|
+
|
|
11121
11714
|
/* export default */ const __rspack_default_export = ((0,agent_bundle_routes__rspack_import_1/* .defineTool */.uO)({
|
|
11122
|
-
description: '
|
|
11715
|
+
description: 'Explicit diagnostic observation of one Codex turn; returns execution and final reply without interrupting it.',
|
|
11716
|
+
title: 'Codex wait',
|
|
11717
|
+
annotations: {
|
|
11718
|
+
readOnlyHint: true
|
|
11719
|
+
},
|
|
11720
|
+
render: {
|
|
11721
|
+
maxElapsedMs: 660000
|
|
11722
|
+
},
|
|
11723
|
+
inputSchema: _core_codex_routes_js__rspack_import_2/* .waitSchema */.jS,
|
|
11724
|
+
resultSchema: _core_codex_routes_js__rspack_import_2/* .resultSchema */.FD,
|
|
11123
11725
|
inputJsonSchema: {
|
|
11726
|
+
type: 'object',
|
|
11124
11727
|
additionalProperties: false,
|
|
11125
11728
|
properties: {
|
|
11126
|
-
|
|
11127
|
-
|
|
11729
|
+
"threadId": {
|
|
11730
|
+
"type": "string"
|
|
11731
|
+
},
|
|
11732
|
+
"expectedCwd": {
|
|
11733
|
+
"type": "string"
|
|
11734
|
+
},
|
|
11735
|
+
"timeoutMs": {
|
|
11736
|
+
"type": "number",
|
|
11737
|
+
"description": "Observation timeout: 1-600000 milliseconds."
|
|
11738
|
+
},
|
|
11739
|
+
"turnId": {
|
|
11740
|
+
"type": "string"
|
|
11741
|
+
},
|
|
11742
|
+
"messageId": {
|
|
11743
|
+
"type": "string"
|
|
11744
|
+
},
|
|
11745
|
+
"maxOutputBytes": {
|
|
11746
|
+
"type": "number",
|
|
11747
|
+
"description": "Reply budget: 1-4194304 bytes."
|
|
11748
|
+
}
|
|
11749
|
+
},
|
|
11750
|
+
required: [
|
|
11751
|
+
'threadId',
|
|
11752
|
+
'turnId'
|
|
11753
|
+
]
|
|
11754
|
+
}
|
|
11755
|
+
}, async (input)=>{
|
|
11756
|
+
const context = await (0,_agent_bundle_runtime__rspack_import_3/* .agent */.MA)();
|
|
11757
|
+
const out = await (0,_core_codex_routes_js__rspack_import_2/* .observeOperation */.gT)('wait', input, context.signal, (message)=>context.progress.report({
|
|
11758
|
+
message
|
|
11759
|
+
}));
|
|
11760
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Result */.g6.Result, {
|
|
11761
|
+
value: out,
|
|
11762
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Text */.g6.Text, {
|
|
11763
|
+
children: (0,_core_codex_routes_js__rspack_import_2/* .resultText */.D6)(out)
|
|
11764
|
+
})
|
|
11765
|
+
});
|
|
11766
|
+
}));
|
|
11767
|
+
|
|
11768
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
11769
|
+
inputSchema: () => (/* reexport safe */ _core_codex_routes_js__rspack_import_2.jS)
|
|
11770
|
+
}, {
|
|
11771
|
+
"default": __rspack_default_export
|
|
11772
|
+
});
|
|
11773
|
+
|
|
11774
|
+
|
|
11775
|
+
},
|
|
11776
|
+
"./src/mcp/grok-bot/tools/codex_watch.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
11777
|
+
__webpack_require__.r(__webpack_exports__);
|
|
11778
|
+
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js");
|
|
11779
|
+
/* import */ var _agent_bundle_runtime__rspack_import_3 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
11780
|
+
/* import */ var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
11781
|
+
/* import */ var agent_bundle_routes__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/routes.js");
|
|
11782
|
+
/* import */ var _core_codex_routes_js__rspack_import_2 = __webpack_require__("./src/core/codex/routes.ts");
|
|
11783
|
+
|
|
11784
|
+
|
|
11785
|
+
|
|
11786
|
+
|
|
11787
|
+
|
|
11788
|
+
/* export default */ const __rspack_default_export = ((0,agent_bundle_routes__rspack_import_1/* .defineTool */.uO)({
|
|
11789
|
+
description: 'Watch bounded Codex thread events for diagnostics without answering approvals.',
|
|
11790
|
+
title: 'Codex watch',
|
|
11791
|
+
annotations: {
|
|
11792
|
+
readOnlyHint: true
|
|
11793
|
+
},
|
|
11794
|
+
render: {
|
|
11795
|
+
maxElapsedMs: 660000
|
|
11796
|
+
},
|
|
11797
|
+
inputSchema: _core_codex_routes_js__rspack_import_2/* .watchSchema */.R9,
|
|
11798
|
+
resultSchema: _core_codex_routes_js__rspack_import_2/* .resultSchema */.FD,
|
|
11799
|
+
inputJsonSchema: {
|
|
11800
|
+
type: 'object',
|
|
11801
|
+
additionalProperties: false,
|
|
11802
|
+
properties: {
|
|
11803
|
+
"threadId": {
|
|
11804
|
+
"type": "string"
|
|
11805
|
+
},
|
|
11806
|
+
"expectedCwd": {
|
|
11807
|
+
"type": "string"
|
|
11808
|
+
},
|
|
11809
|
+
"timeoutMs": {
|
|
11810
|
+
"type": "number",
|
|
11811
|
+
"description": "Observation timeout: 1-600000 milliseconds."
|
|
11812
|
+
},
|
|
11813
|
+
"maxEvents": {
|
|
11814
|
+
"type": "number",
|
|
11815
|
+
"description": "Maximum observed events: 1-500."
|
|
11816
|
+
}
|
|
11817
|
+
},
|
|
11818
|
+
required: [
|
|
11819
|
+
'threadId'
|
|
11820
|
+
]
|
|
11821
|
+
}
|
|
11822
|
+
}, async (input)=>{
|
|
11823
|
+
const context = await (0,_agent_bundle_runtime__rspack_import_3/* .agent */.MA)();
|
|
11824
|
+
const out = await (0,_core_codex_routes_js__rspack_import_2/* .observeOperation */.gT)('watch', input, context.signal, (message)=>context.progress.report({
|
|
11825
|
+
message
|
|
11826
|
+
}));
|
|
11827
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Result */.g6.Result, {
|
|
11828
|
+
value: out,
|
|
11829
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Text */.g6.Text, {
|
|
11830
|
+
children: (0,_core_codex_routes_js__rspack_import_2/* .resultText */.D6)(out)
|
|
11831
|
+
})
|
|
11832
|
+
});
|
|
11833
|
+
}));
|
|
11834
|
+
|
|
11835
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
11836
|
+
inputSchema: () => (/* reexport safe */ _core_codex_routes_js__rspack_import_2.R9)
|
|
11837
|
+
}, {
|
|
11838
|
+
"default": __rspack_default_export
|
|
11839
|
+
});
|
|
11840
|
+
|
|
11841
|
+
|
|
11842
|
+
},
|
|
11843
|
+
"./src/mcp/grok-bot/tools/gbot_bridge_start.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
11844
|
+
__webpack_require__.r(__webpack_exports__);
|
|
11845
|
+
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js");
|
|
11846
|
+
/* import */ var _agent_bundle_runtime__rspack_import_3 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
11847
|
+
/* import */ var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
11848
|
+
/* import */ var agent_bundle_routes__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/routes.js");
|
|
11849
|
+
/* import */ var _core_relay_routes_js__rspack_import_2 = __webpack_require__("./src/core/relay/routes.ts");
|
|
11850
|
+
|
|
11851
|
+
|
|
11852
|
+
|
|
11853
|
+
|
|
11854
|
+
|
|
11855
|
+
/* export default */ const __rspack_default_export = ((0,agent_bundle_routes__rspack_import_1/* .defineTool */.uO)({
|
|
11856
|
+
description: 'Link a Grok conversation to Codex once. New visible Grok messages arrive automatically and Codex final answers return to Grok.',
|
|
11857
|
+
title: 'gbot_bridge_start',
|
|
11858
|
+
annotations: {
|
|
11859
|
+
readOnlyHint: false
|
|
11860
|
+
},
|
|
11861
|
+
inputSchema: _core_relay_routes_js__rspack_import_2/* .bridgeStartSchema */.xD,
|
|
11862
|
+
resultSchema: _core_relay_routes_js__rspack_import_2/* .relayResultSchema */.Ax,
|
|
11863
|
+
inputJsonSchema: {
|
|
11864
|
+
type: 'object',
|
|
11865
|
+
properties: {
|
|
11866
|
+
grokTarget: {
|
|
11867
|
+
type: 'string'
|
|
11868
|
+
},
|
|
11869
|
+
codexThreadId: {
|
|
11870
|
+
type: 'string'
|
|
11871
|
+
},
|
|
11872
|
+
expectedCwd: {
|
|
11873
|
+
type: 'string'
|
|
11874
|
+
},
|
|
11875
|
+
busyPolicy: {
|
|
11876
|
+
type: 'string',
|
|
11877
|
+
enum: [
|
|
11878
|
+
'steer',
|
|
11879
|
+
'reject'
|
|
11880
|
+
]
|
|
11881
|
+
},
|
|
11882
|
+
requestId: {
|
|
11883
|
+
type: 'string'
|
|
11884
|
+
}
|
|
11885
|
+
},
|
|
11886
|
+
required: [
|
|
11887
|
+
'grokTarget'
|
|
11888
|
+
],
|
|
11889
|
+
additionalProperties: false
|
|
11890
|
+
}
|
|
11891
|
+
}, async (input)=>{
|
|
11892
|
+
const out = await (0,_core_relay_routes_js__rspack_import_2/* .bridgeOperation */.n1)('startBinding', input, await (0,_agent_bundle_runtime__rspack_import_3/* .agent */.MA)());
|
|
11893
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Result */.g6.Result, {
|
|
11894
|
+
value: out,
|
|
11895
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Text */.g6.Text, {
|
|
11896
|
+
children: JSON.stringify(out)
|
|
11897
|
+
})
|
|
11898
|
+
});
|
|
11899
|
+
}));
|
|
11900
|
+
|
|
11901
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
11902
|
+
inputSchema: () => (/* reexport safe */ _core_relay_routes_js__rspack_import_2.xD)
|
|
11903
|
+
}, {
|
|
11904
|
+
"default": __rspack_default_export
|
|
11905
|
+
});
|
|
11906
|
+
|
|
11907
|
+
|
|
11908
|
+
},
|
|
11909
|
+
"./src/mcp/grok-bot/tools/gbot_bridge_status.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
11910
|
+
__webpack_require__.r(__webpack_exports__);
|
|
11911
|
+
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js");
|
|
11912
|
+
/* import */ var _agent_bundle_runtime__rspack_import_3 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
11913
|
+
/* import */ var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
11914
|
+
/* import */ var agent_bundle_routes__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/routes.js");
|
|
11915
|
+
/* import */ var _core_relay_routes_js__rspack_import_2 = __webpack_require__("./src/core/relay/routes.ts");
|
|
11916
|
+
|
|
11917
|
+
|
|
11918
|
+
|
|
11919
|
+
|
|
11920
|
+
|
|
11921
|
+
/* export default */ const __rspack_default_export = ((0,agent_bundle_routes__rspack_import_1/* .defineTool */.uO)({
|
|
11922
|
+
description: 'Inspect worker health, route coverage, bounded receipts and scoped pending operator interactions.',
|
|
11923
|
+
title: 'gbot_bridge_status',
|
|
11924
|
+
annotations: {
|
|
11925
|
+
readOnlyHint: true
|
|
11926
|
+
},
|
|
11927
|
+
inputSchema: _core_relay_routes_js__rspack_import_2/* .bridgeStatusSchema */.np,
|
|
11928
|
+
resultSchema: _core_relay_routes_js__rspack_import_2/* .relayResultSchema */.Ax,
|
|
11929
|
+
inputJsonSchema: {
|
|
11930
|
+
type: 'object',
|
|
11931
|
+
properties: {
|
|
11932
|
+
bindingId: {
|
|
11933
|
+
type: 'string'
|
|
11934
|
+
},
|
|
11935
|
+
limit: {
|
|
11936
|
+
type: 'number'
|
|
11937
|
+
}
|
|
11938
|
+
},
|
|
11939
|
+
additionalProperties: false
|
|
11940
|
+
}
|
|
11941
|
+
}, async (input)=>{
|
|
11942
|
+
const out = await (0,_core_relay_routes_js__rspack_import_2/* .bridgeOperation */.n1)('status', input, await (0,_agent_bundle_runtime__rspack_import_3/* .agent */.MA)());
|
|
11943
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Result */.g6.Result, {
|
|
11944
|
+
value: out,
|
|
11945
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Text */.g6.Text, {
|
|
11946
|
+
children: JSON.stringify(out)
|
|
11947
|
+
})
|
|
11948
|
+
});
|
|
11949
|
+
}));
|
|
11950
|
+
|
|
11951
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
11952
|
+
inputSchema: () => (/* reexport safe */ _core_relay_routes_js__rspack_import_2.np)
|
|
11953
|
+
}, {
|
|
11954
|
+
"default": __rspack_default_export
|
|
11955
|
+
});
|
|
11956
|
+
|
|
11957
|
+
|
|
11958
|
+
},
|
|
11959
|
+
"./src/mcp/grok-bot/tools/gbot_bridge_stop.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
11960
|
+
__webpack_require__.r(__webpack_exports__);
|
|
11961
|
+
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js");
|
|
11962
|
+
/* import */ var _agent_bundle_runtime__rspack_import_3 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
11963
|
+
/* import */ var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
11964
|
+
/* import */ var agent_bundle_routes__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/routes.js");
|
|
11965
|
+
/* import */ var _core_relay_routes_js__rspack_import_2 = __webpack_require__("./src/core/relay/routes.ts");
|
|
11966
|
+
|
|
11967
|
+
|
|
11968
|
+
|
|
11969
|
+
|
|
11970
|
+
|
|
11971
|
+
/* export default */ const __rspack_default_export = ((0,agent_bundle_routes__rspack_import_1/* .defineTool */.uO)({
|
|
11972
|
+
description: 'Stop a binding without deleting receipts or interrupting Codex. all stops all bindings; worker explicitly shuts down the worker.',
|
|
11973
|
+
title: 'gbot_bridge_stop',
|
|
11974
|
+
annotations: {
|
|
11975
|
+
readOnlyHint: false
|
|
11976
|
+
},
|
|
11977
|
+
inputSchema: _core_relay_routes_js__rspack_import_2/* .bridgeStopSchema */.d5,
|
|
11978
|
+
resultSchema: _core_relay_routes_js__rspack_import_2/* .relayResultSchema */.Ax,
|
|
11979
|
+
inputJsonSchema: {
|
|
11980
|
+
type: 'object',
|
|
11981
|
+
properties: {
|
|
11982
|
+
bindingId: {
|
|
11983
|
+
type: 'string'
|
|
11984
|
+
},
|
|
11985
|
+
all: {
|
|
11986
|
+
type: 'boolean'
|
|
11987
|
+
},
|
|
11988
|
+
worker: {
|
|
11989
|
+
type: 'boolean'
|
|
11990
|
+
}
|
|
11991
|
+
},
|
|
11992
|
+
additionalProperties: false
|
|
11993
|
+
}
|
|
11994
|
+
}, async (input)=>{
|
|
11995
|
+
const out = await (0,_core_relay_routes_js__rspack_import_2/* .bridgeOperation */.n1)('stop', input, await (0,_agent_bundle_runtime__rspack_import_3/* .agent */.MA)());
|
|
11996
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Result */.g6.Result, {
|
|
11997
|
+
value: out,
|
|
11998
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Text */.g6.Text, {
|
|
11999
|
+
children: JSON.stringify(out)
|
|
12000
|
+
})
|
|
12001
|
+
});
|
|
12002
|
+
}));
|
|
12003
|
+
|
|
12004
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
12005
|
+
inputSchema: () => (/* reexport safe */ _core_relay_routes_js__rspack_import_2.d5)
|
|
12006
|
+
}, {
|
|
12007
|
+
"default": __rspack_default_export
|
|
12008
|
+
});
|
|
12009
|
+
|
|
12010
|
+
|
|
12011
|
+
},
|
|
12012
|
+
"./src/mcp/grok-bot/tools/gbot_codex_respond.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
12013
|
+
__webpack_require__.r(__webpack_exports__);
|
|
12014
|
+
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js");
|
|
12015
|
+
/* import */ var _agent_bundle_runtime__rspack_import_3 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
12016
|
+
/* import */ var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
12017
|
+
/* import */ var agent_bundle_routes__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/routes.js");
|
|
12018
|
+
/* import */ var _core_relay_routes_js__rspack_import_2 = __webpack_require__("./src/core/relay/routes.ts");
|
|
12019
|
+
|
|
12020
|
+
|
|
12021
|
+
|
|
12022
|
+
|
|
12023
|
+
|
|
12024
|
+
/* export default */ const __rspack_default_export = ((0,agent_bundle_routes__rspack_import_1/* .defineTool */.uO)({
|
|
12025
|
+
description: 'Explicit operator response to a current scoped Codex interaction. Supports only one-time accept/decline/cancel or exact question-ID answers. Never auto-approve.',
|
|
12026
|
+
title: 'gbot_codex_respond',
|
|
12027
|
+
annotations: {
|
|
12028
|
+
readOnlyHint: false
|
|
12029
|
+
},
|
|
12030
|
+
inputSchema: _core_relay_routes_js__rspack_import_2/* .respondSchema */.v1,
|
|
12031
|
+
resultSchema: _core_relay_routes_js__rspack_import_2/* .relayResultSchema */.Ax,
|
|
12032
|
+
inputJsonSchema: {
|
|
12033
|
+
type: 'object',
|
|
12034
|
+
properties: {
|
|
12035
|
+
interactionId: {
|
|
12036
|
+
type: 'string'
|
|
12037
|
+
},
|
|
12038
|
+
generation: {
|
|
12039
|
+
type: 'string'
|
|
12040
|
+
},
|
|
12041
|
+
threadId: {
|
|
12042
|
+
type: 'string'
|
|
12043
|
+
},
|
|
12044
|
+
turnId: {
|
|
12045
|
+
type: 'string'
|
|
12046
|
+
},
|
|
12047
|
+
bindingId: {
|
|
12048
|
+
type: 'string'
|
|
12049
|
+
},
|
|
12050
|
+
exchangeId: {
|
|
12051
|
+
type: 'string'
|
|
12052
|
+
},
|
|
12053
|
+
decision: {
|
|
12054
|
+
type: 'string',
|
|
12055
|
+
enum: [
|
|
12056
|
+
'accept',
|
|
12057
|
+
'decline',
|
|
12058
|
+
'cancel'
|
|
12059
|
+
]
|
|
12060
|
+
},
|
|
12061
|
+
answersJson: {
|
|
12062
|
+
type: 'string',
|
|
12063
|
+
description: 'JSON object mapping each advertised question ID to {"answers":["answer"]}; exact IDs required.'
|
|
12064
|
+
}
|
|
12065
|
+
},
|
|
12066
|
+
required: [
|
|
12067
|
+
'interactionId',
|
|
12068
|
+
'generation',
|
|
12069
|
+
'threadId',
|
|
12070
|
+
'turnId'
|
|
12071
|
+
],
|
|
12072
|
+
additionalProperties: false
|
|
12073
|
+
}
|
|
12074
|
+
}, async (input)=>{
|
|
12075
|
+
const out = await (0,_core_relay_routes_js__rspack_import_2/* .bridgeOperation */.n1)('respond', input, await (0,_agent_bundle_runtime__rspack_import_3/* .agent */.MA)());
|
|
12076
|
+
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Result */.g6.Result, {
|
|
12077
|
+
value: out,
|
|
12078
|
+
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Text */.g6.Text, {
|
|
12079
|
+
children: JSON.stringify(out)
|
|
12080
|
+
})
|
|
12081
|
+
});
|
|
12082
|
+
}));
|
|
12083
|
+
|
|
12084
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
12085
|
+
inputSchema: () => (/* reexport safe */ _core_relay_routes_js__rspack_import_2.v1)
|
|
12086
|
+
}, {
|
|
12087
|
+
"default": __rspack_default_export
|
|
12088
|
+
});
|
|
12089
|
+
|
|
12090
|
+
|
|
12091
|
+
},
|
|
12092
|
+
"./src/mcp/grok-bot/tools/gbot_send.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
12093
|
+
__webpack_require__.r(__webpack_exports__);
|
|
12094
|
+
/* import */ var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js");
|
|
12095
|
+
/* import */ var _agent_bundle_runtime__rspack_import_3 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js");
|
|
12096
|
+
/* import */ var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js");
|
|
12097
|
+
/* import */ var agent_bundle_routes__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/routes.js");
|
|
12098
|
+
/* import */ var _core_relay_routes_js__rspack_import_2 = __webpack_require__("./src/core/relay/routes.ts");
|
|
12099
|
+
|
|
12100
|
+
|
|
12101
|
+
|
|
12102
|
+
|
|
12103
|
+
|
|
12104
|
+
/* export default */ const __rspack_default_export = ((0,agent_bundle_routes__rspack_import_1/* .defineTool */.uO)({
|
|
12105
|
+
description: 'Send to Grok Bot. Native Codex calls automatically receive replies in their originating thread; send once and continue work. Without a native source, supply codexThreadId or use manual gbot_thread reading.',
|
|
12106
|
+
title: 'Send a message to Grok Bot',
|
|
12107
|
+
annotations: {
|
|
12108
|
+
readOnlyHint: false
|
|
12109
|
+
},
|
|
12110
|
+
inputSchema: _core_relay_routes_js__rspack_import_2/* .grokSendSchema */.bw,
|
|
12111
|
+
resultSchema: _core_relay_routes_js__rspack_import_2/* .relayResultSchema */.Ax,
|
|
12112
|
+
inputJsonSchema: {
|
|
12113
|
+
type: 'object',
|
|
12114
|
+
properties: {
|
|
12115
|
+
hop: {
|
|
12116
|
+
type: 'number',
|
|
12117
|
+
description: 'Explicit chain hop count, refused at the configured bound.'
|
|
12118
|
+
},
|
|
12119
|
+
correlationId: {
|
|
11128
12120
|
type: 'string'
|
|
11129
12121
|
},
|
|
11130
12122
|
target: {
|
|
11131
|
-
|
|
12123
|
+
type: 'string'
|
|
12124
|
+
},
|
|
12125
|
+
message: {
|
|
12126
|
+
type: 'string'
|
|
12127
|
+
},
|
|
12128
|
+
replyMode: {
|
|
12129
|
+
type: 'string',
|
|
12130
|
+
enum: [
|
|
12131
|
+
'auto',
|
|
12132
|
+
'manual'
|
|
12133
|
+
]
|
|
12134
|
+
},
|
|
12135
|
+
codexThreadId: {
|
|
12136
|
+
type: 'string'
|
|
12137
|
+
},
|
|
12138
|
+
expectedCwd: {
|
|
12139
|
+
type: 'string'
|
|
12140
|
+
},
|
|
12141
|
+
bindingId: {
|
|
12142
|
+
type: 'string'
|
|
12143
|
+
},
|
|
12144
|
+
requestId: {
|
|
11132
12145
|
type: 'string'
|
|
11133
12146
|
}
|
|
11134
12147
|
},
|
|
@@ -11136,44 +12149,22 @@ const inputSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
|
11136
12149
|
'target',
|
|
11137
12150
|
'message'
|
|
11138
12151
|
],
|
|
11139
|
-
|
|
11140
|
-
}
|
|
11141
|
-
|
|
11142
|
-
|
|
11143
|
-
result: zod__rspack_import_3/* .record */.g1P(zod__rspack_import_3/* .string */.YjP(), zod__rspack_import_3/* .json */.Pq9()),
|
|
11144
|
-
target: _gbot_js__rspack_import_2/* .targetSchema */.tX,
|
|
11145
|
-
delivery: zod__rspack_import_3/* ["enum"] */.k5n([
|
|
11146
|
-
'accepted',
|
|
11147
|
-
'unknown'
|
|
11148
|
-
]),
|
|
11149
|
-
messageId: zod__rspack_import_3/* .string */.YjP().optional()
|
|
11150
|
-
}),
|
|
11151
|
-
title: 'Send a message to Grok Bot'
|
|
11152
|
-
}, async ({ message, target })=>{
|
|
11153
|
-
const sent = await (0,_gbot_js__rspack_import_2/* .withRedactedErrors */.yF)(async ()=>(0,_gbot_js__rspack_import_2/* .sendPrompt */.LV)(await (0,_gbot_js__rspack_import_2/* .connectGateway */.Vq)(), target, message));
|
|
11154
|
-
// Never claim acceptance the gateway didn't confirm; no-receipt sends stay unknown.
|
|
11155
|
-
const delivery = sent.delivery === 'accepted' ? 'accepted' : 'unknown';
|
|
11156
|
-
const messageId = delivery === 'accepted' && typeof sent.messageId === 'string' ? sent.messageId : undefined;
|
|
11157
|
-
const value = {
|
|
11158
|
-
result: sent.result,
|
|
11159
|
-
target: (0,_gbot_js__rspack_import_2/* .summarizeTarget */.rW)(sent.target),
|
|
11160
|
-
delivery,
|
|
11161
|
-
...messageId === undefined ? {} : {
|
|
11162
|
-
messageId
|
|
11163
|
-
}
|
|
11164
|
-
};
|
|
12152
|
+
additionalProperties: false
|
|
12153
|
+
}
|
|
12154
|
+
}, async (input)=>{
|
|
12155
|
+
const out = await (0,_core_relay_routes_js__rspack_import_2/* .grokSendOperation */.bv)(input, await (0,_agent_bundle_runtime__rspack_import_3/* .agent */.MA)());
|
|
11165
12156
|
return /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Result */.g6.Result, {
|
|
11166
|
-
value:
|
|
12157
|
+
value: out,
|
|
11167
12158
|
children: /*#__PURE__*/ (0,react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_4/* .Agent.Text */.g6.Text, {
|
|
11168
|
-
children: `
|
|
12159
|
+
children: out.replyRoute.mode === 'auto' ? `Delivery ${out.delivery}; replies will arrive in Codex thread ${out.replyRoute.threadId}. Continue work; no polling needed.` : `Delivery ${out.delivery}${out.delivery === 'unknown' ? ' (no receipt; check the thread before resending)' : ''}; read the reply with gbot_thread.`
|
|
11169
12160
|
})
|
|
11170
12161
|
});
|
|
11171
12162
|
}));
|
|
11172
12163
|
|
|
11173
12164
|
__webpack_require__.d(__webpack_exports__, {
|
|
12165
|
+
inputSchema: () => (/* reexport safe */ _core_relay_routes_js__rspack_import_2.bw)
|
|
11174
12166
|
}, {
|
|
11175
|
-
"default": __rspack_default_export
|
|
11176
|
-
inputSchema: inputSchema
|
|
12167
|
+
"default": __rspack_default_export
|
|
11177
12168
|
});
|
|
11178
12169
|
|
|
11179
12170
|
|
|
@@ -11245,7 +12236,9 @@ const inputSchema = zod__rspack_import_3/* .object */.Ikc({
|
|
|
11245
12236
|
after,
|
|
11246
12237
|
limit
|
|
11247
12238
|
});
|
|
11248
|
-
const entries = (0,_gbot_js__rspack_import_2/* .transcriptEntries */.xw)(
|
|
12239
|
+
const entries = (0,_gbot_js__rspack_import_2/* .transcriptEntries */.xw)({
|
|
12240
|
+
entries: delta.entries
|
|
12241
|
+
});
|
|
11249
12242
|
const summary = delta.gapReset ? `${delta.entryCount} entries; gap reset` : after === undefined ? `${delta.entryCount} entries` : `${delta.entryCount} new`;
|
|
11250
12243
|
const receipt = {
|
|
11251
12244
|
cursor: delta.cursor,
|
|
@@ -11316,6 +12309,12 @@ module.exports = __rspack_external_node_fs_1b05aee1;
|
|
|
11316
12309
|
module.exports = __rspack_external_node_fs_promises_3b710708;
|
|
11317
12310
|
|
|
11318
12311
|
|
|
12312
|
+
},
|
|
12313
|
+
"node:net"(module) {
|
|
12314
|
+
|
|
12315
|
+
module.exports = __rspack_external_node_net_5ed819e1;
|
|
12316
|
+
|
|
12317
|
+
|
|
11319
12318
|
},
|
|
11320
12319
|
"node:os"(module) {
|
|
11321
12320
|
|
|
@@ -11334,6 +12333,12 @@ module.exports = __rspack_external_node_path_806ed179;
|
|
|
11334
12333
|
module.exports = __rspack_external_node_process_ee535471;
|
|
11335
12334
|
|
|
11336
12335
|
|
|
12336
|
+
},
|
|
12337
|
+
"node:string_decoder"(module) {
|
|
12338
|
+
|
|
12339
|
+
module.exports = __rspack_external_node_string_decoder_69b9bd04;
|
|
12340
|
+
|
|
12341
|
+
|
|
11337
12342
|
},
|
|
11338
12343
|
"node:url"(module) {
|
|
11339
12344
|
|
|
@@ -106187,43 +107192,435 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
106187
107192
|
"./.agent-bundle-virtual/mcp-grok-bot-b8c2461e-1.mjs"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
106188
107193
|
__webpack_require__.r(__webpack_exports__);
|
|
106189
107194
|
/* import */ var node_url__rspack_import_0 = __webpack_require__("node:url");
|
|
106190
|
-
/* import */ var
|
|
107195
|
+
/* import */ var _agent_bundle_runtime__rspack_import_13 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/49.js");
|
|
106191
107196
|
/* import */ var agent_bundle_mcp_server_runtime__rspack_import_1 = __webpack_require__("./node_modules/agent-bundle/dist/mcp-server-runtime.js");
|
|
106192
|
-
/* import */ var
|
|
107197
|
+
/* import */ var _agent_bundle_runtime_lineage__rspack_import_14 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/lineage.js");
|
|
106193
107198
|
/* import */ var agent_bundle_mcp_apps__rspack_import_2 = __webpack_require__("./.agent-bundle-virtual/mcp-grok-bot-b8c2461e-0.mjs");
|
|
106194
|
-
/* import */ var
|
|
106195
|
-
/* import */ var
|
|
107199
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_send_tsx__rspack_import_3 = __webpack_require__("./src/mcp/grok-bot/tools/codex_send.tsx");
|
|
107200
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_threads_tsx__rspack_import_4 = __webpack_require__("./src/mcp/grok-bot/tools/codex_threads.tsx");
|
|
107201
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_wait_tsx__rspack_import_5 = __webpack_require__("./src/mcp/grok-bot/tools/codex_wait.tsx");
|
|
107202
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_watch_tsx__rspack_import_6 = __webpack_require__("./src/mcp/grok-bot/tools/codex_watch.tsx");
|
|
107203
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_bridge_start_tsx__rspack_import_7 = __webpack_require__("./src/mcp/grok-bot/tools/gbot_bridge_start.tsx");
|
|
107204
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_bridge_status_tsx__rspack_import_8 = __webpack_require__("./src/mcp/grok-bot/tools/gbot_bridge_status.tsx");
|
|
107205
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_bridge_stop_tsx__rspack_import_9 = __webpack_require__("./src/mcp/grok-bot/tools/gbot_bridge_stop.tsx");
|
|
107206
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_codex_respond_tsx__rspack_import_10 = __webpack_require__("./src/mcp/grok-bot/tools/gbot_codex_respond.tsx");
|
|
107207
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_send_tsx__rspack_import_11 = __webpack_require__("./src/mcp/grok-bot/tools/gbot_send.tsx");
|
|
107208
|
+
/* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_thread_tsx__rspack_import_12 = __webpack_require__("./src/mcp/grok-bot/tools/gbot_thread.tsx");
|
|
106196
107209
|
|
|
106197
107210
|
|
|
106198
107211
|
|
|
106199
107212
|
|
|
106200
107213
|
|
|
106201
107214
|
|
|
106202
|
-
const route0 = Object.assign({}, Reflect.get(
|
|
107215
|
+
const route0 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_send_tsx__rspack_import_3, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_send_tsx__rspack_import_3);
|
|
106203
107216
|
|
|
106204
|
-
const route1 = Object.assign({}, Reflect.get(
|
|
106205
|
-
|
|
106206
|
-
const
|
|
107217
|
+
const route1 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_threads_tsx__rspack_import_4, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_threads_tsx__rspack_import_4);
|
|
107218
|
+
|
|
107219
|
+
const route2 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_wait_tsx__rspack_import_5, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_wait_tsx__rspack_import_5);
|
|
107220
|
+
|
|
107221
|
+
const route3 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_watch_tsx__rspack_import_6, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_codex_watch_tsx__rspack_import_6);
|
|
107222
|
+
|
|
107223
|
+
const route4 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_bridge_start_tsx__rspack_import_7, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_bridge_start_tsx__rspack_import_7);
|
|
107224
|
+
|
|
107225
|
+
const route5 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_bridge_status_tsx__rspack_import_8, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_bridge_status_tsx__rspack_import_8);
|
|
107226
|
+
|
|
107227
|
+
const route6 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_bridge_stop_tsx__rspack_import_9, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_bridge_stop_tsx__rspack_import_9);
|
|
107228
|
+
|
|
107229
|
+
const route7 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_codex_respond_tsx__rspack_import_10, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_codex_respond_tsx__rspack_import_10);
|
|
107230
|
+
|
|
107231
|
+
const route8 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_send_tsx__rspack_import_11, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_send_tsx__rspack_import_11);
|
|
107232
|
+
|
|
107233
|
+
const route9 = Object.assign({}, Reflect.get(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_thread_tsx__rspack_import_12, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_thread_tsx__rspack_import_12);
|
|
107234
|
+
const ARTIFACT_EPOCH = "gbot@0.6.0";
|
|
107235
|
+
const pluginRoot = (0,_agent_bundle_runtime__rspack_import_13/* .resolvePluginRoot */.E7)({
|
|
106207
107236
|
fallback: (0,node_url__rspack_import_0.fileURLToPath)(new URL('..', import.meta.url)),
|
|
106208
107237
|
stateAnchor: 'user-data'
|
|
106209
107238
|
});
|
|
106210
107239
|
const openLineage = async ()=>({
|
|
106211
107240
|
dispose: async ()=>undefined,
|
|
106212
|
-
registry: (0,
|
|
107241
|
+
registry: (0,_agent_bundle_runtime_lineage__rspack_import_14/* .createAgentLineageRegistry */.Q5)()
|
|
106213
107242
|
});
|
|
106214
107243
|
const routes = Object.freeze({
|
|
107244
|
+
"tool:grok-bot/codex_send": Object.freeze({
|
|
107245
|
+
config: {
|
|
107246
|
+
"annotations": {
|
|
107247
|
+
"readOnlyHint": false
|
|
107248
|
+
},
|
|
107249
|
+
"description": "Send to Codex. With replyToGrok or bindingId, managed delivery returns the terminal answer to Grok automatically. Otherwise optional wait observes completion and explicit steer requires expectedTurnId. Acceptance is not completion.",
|
|
107250
|
+
"inputJsonSchema": {
|
|
107251
|
+
"additionalProperties": false,
|
|
107252
|
+
"properties": {
|
|
107253
|
+
"bindingId": {
|
|
107254
|
+
"type": "string"
|
|
107255
|
+
},
|
|
107256
|
+
"correlationId": {
|
|
107257
|
+
"type": "string"
|
|
107258
|
+
},
|
|
107259
|
+
"envelope": {
|
|
107260
|
+
"type": "boolean"
|
|
107261
|
+
},
|
|
107262
|
+
"expectedCwd": {
|
|
107263
|
+
"type": "string"
|
|
107264
|
+
},
|
|
107265
|
+
"expectedTurnId": {
|
|
107266
|
+
"type": "string"
|
|
107267
|
+
},
|
|
107268
|
+
"hop": {
|
|
107269
|
+
"type": "number"
|
|
107270
|
+
},
|
|
107271
|
+
"maxOutputBytes": {
|
|
107272
|
+
"type": "number"
|
|
107273
|
+
},
|
|
107274
|
+
"message": {
|
|
107275
|
+
"type": "string"
|
|
107276
|
+
},
|
|
107277
|
+
"replyTo": {
|
|
107278
|
+
"type": "string"
|
|
107279
|
+
},
|
|
107280
|
+
"replyToGrok": {
|
|
107281
|
+
"type": "string"
|
|
107282
|
+
},
|
|
107283
|
+
"requestId": {
|
|
107284
|
+
"type": "string"
|
|
107285
|
+
},
|
|
107286
|
+
"threadId": {
|
|
107287
|
+
"type": "string"
|
|
107288
|
+
},
|
|
107289
|
+
"timeoutMs": {
|
|
107290
|
+
"type": "number"
|
|
107291
|
+
},
|
|
107292
|
+
"wait": {
|
|
107293
|
+
"default": false,
|
|
107294
|
+
"type": "boolean"
|
|
107295
|
+
},
|
|
107296
|
+
"whenBusy": {
|
|
107297
|
+
"enum": [
|
|
107298
|
+
"reject",
|
|
107299
|
+
"queue",
|
|
107300
|
+
"steer"
|
|
107301
|
+
],
|
|
107302
|
+
"type": "string"
|
|
107303
|
+
}
|
|
107304
|
+
},
|
|
107305
|
+
"required": [
|
|
107306
|
+
"threadId",
|
|
107307
|
+
"message"
|
|
107308
|
+
],
|
|
107309
|
+
"type": "object"
|
|
107310
|
+
},
|
|
107311
|
+
"render": {
|
|
107312
|
+
"maxElapsedMs": 660000
|
|
107313
|
+
},
|
|
107314
|
+
"title": "Codex send"
|
|
107315
|
+
},
|
|
107316
|
+
id: "tool:grok-bot/codex_send",
|
|
107317
|
+
kind: "tool",
|
|
107318
|
+
module: route0,
|
|
107319
|
+
name: "codex_send"
|
|
107320
|
+
}),
|
|
107321
|
+
"tool:grok-bot/codex_threads": Object.freeze({
|
|
107322
|
+
config: {
|
|
107323
|
+
"annotations": {
|
|
107324
|
+
"readOnlyHint": true
|
|
107325
|
+
},
|
|
107326
|
+
"description": "Discover a bounded page of Codex daemon threads.",
|
|
107327
|
+
"inputJsonSchema": {
|
|
107328
|
+
"additionalProperties": false,
|
|
107329
|
+
"properties": {
|
|
107330
|
+
"cursor": {
|
|
107331
|
+
"type": "string"
|
|
107332
|
+
},
|
|
107333
|
+
"limit": {
|
|
107334
|
+
"description": "Maximum threads in this page: 1-200.",
|
|
107335
|
+
"type": "number"
|
|
107336
|
+
}
|
|
107337
|
+
},
|
|
107338
|
+
"required": [],
|
|
107339
|
+
"type": "object"
|
|
107340
|
+
},
|
|
107341
|
+
"render": {
|
|
107342
|
+
"maxElapsedMs": 660000
|
|
107343
|
+
},
|
|
107344
|
+
"title": "Codex threads"
|
|
107345
|
+
},
|
|
107346
|
+
id: "tool:grok-bot/codex_threads",
|
|
107347
|
+
kind: "tool",
|
|
107348
|
+
module: route1,
|
|
107349
|
+
name: "codex_threads"
|
|
107350
|
+
}),
|
|
107351
|
+
"tool:grok-bot/codex_wait": Object.freeze({
|
|
107352
|
+
config: {
|
|
107353
|
+
"annotations": {
|
|
107354
|
+
"readOnlyHint": true
|
|
107355
|
+
},
|
|
107356
|
+
"description": "Explicit diagnostic observation of one Codex turn; returns execution and final reply without interrupting it.",
|
|
107357
|
+
"inputJsonSchema": {
|
|
107358
|
+
"additionalProperties": false,
|
|
107359
|
+
"properties": {
|
|
107360
|
+
"expectedCwd": {
|
|
107361
|
+
"type": "string"
|
|
107362
|
+
},
|
|
107363
|
+
"maxOutputBytes": {
|
|
107364
|
+
"description": "Reply budget: 1-4194304 bytes.",
|
|
107365
|
+
"type": "number"
|
|
107366
|
+
},
|
|
107367
|
+
"messageId": {
|
|
107368
|
+
"type": "string"
|
|
107369
|
+
},
|
|
107370
|
+
"threadId": {
|
|
107371
|
+
"type": "string"
|
|
107372
|
+
},
|
|
107373
|
+
"timeoutMs": {
|
|
107374
|
+
"description": "Observation timeout: 1-600000 milliseconds.",
|
|
107375
|
+
"type": "number"
|
|
107376
|
+
},
|
|
107377
|
+
"turnId": {
|
|
107378
|
+
"type": "string"
|
|
107379
|
+
}
|
|
107380
|
+
},
|
|
107381
|
+
"required": [
|
|
107382
|
+
"threadId",
|
|
107383
|
+
"turnId"
|
|
107384
|
+
],
|
|
107385
|
+
"type": "object"
|
|
107386
|
+
},
|
|
107387
|
+
"render": {
|
|
107388
|
+
"maxElapsedMs": 660000
|
|
107389
|
+
},
|
|
107390
|
+
"title": "Codex wait"
|
|
107391
|
+
},
|
|
107392
|
+
id: "tool:grok-bot/codex_wait",
|
|
107393
|
+
kind: "tool",
|
|
107394
|
+
module: route2,
|
|
107395
|
+
name: "codex_wait"
|
|
107396
|
+
}),
|
|
107397
|
+
"tool:grok-bot/codex_watch": Object.freeze({
|
|
107398
|
+
config: {
|
|
107399
|
+
"annotations": {
|
|
107400
|
+
"readOnlyHint": true
|
|
107401
|
+
},
|
|
107402
|
+
"description": "Watch bounded Codex thread events for diagnostics without answering approvals.",
|
|
107403
|
+
"inputJsonSchema": {
|
|
107404
|
+
"additionalProperties": false,
|
|
107405
|
+
"properties": {
|
|
107406
|
+
"expectedCwd": {
|
|
107407
|
+
"type": "string"
|
|
107408
|
+
},
|
|
107409
|
+
"maxEvents": {
|
|
107410
|
+
"description": "Maximum observed events: 1-500.",
|
|
107411
|
+
"type": "number"
|
|
107412
|
+
},
|
|
107413
|
+
"threadId": {
|
|
107414
|
+
"type": "string"
|
|
107415
|
+
},
|
|
107416
|
+
"timeoutMs": {
|
|
107417
|
+
"description": "Observation timeout: 1-600000 milliseconds.",
|
|
107418
|
+
"type": "number"
|
|
107419
|
+
}
|
|
107420
|
+
},
|
|
107421
|
+
"required": [
|
|
107422
|
+
"threadId"
|
|
107423
|
+
],
|
|
107424
|
+
"type": "object"
|
|
107425
|
+
},
|
|
107426
|
+
"render": {
|
|
107427
|
+
"maxElapsedMs": 660000
|
|
107428
|
+
},
|
|
107429
|
+
"title": "Codex watch"
|
|
107430
|
+
},
|
|
107431
|
+
id: "tool:grok-bot/codex_watch",
|
|
107432
|
+
kind: "tool",
|
|
107433
|
+
module: route3,
|
|
107434
|
+
name: "codex_watch"
|
|
107435
|
+
}),
|
|
107436
|
+
"tool:grok-bot/gbot_bridge_start": Object.freeze({
|
|
107437
|
+
config: {
|
|
107438
|
+
"annotations": {
|
|
107439
|
+
"readOnlyHint": false
|
|
107440
|
+
},
|
|
107441
|
+
"description": "Link a Grok conversation to Codex once. New visible Grok messages arrive automatically and Codex final answers return to Grok.",
|
|
107442
|
+
"inputJsonSchema": {
|
|
107443
|
+
"additionalProperties": false,
|
|
107444
|
+
"properties": {
|
|
107445
|
+
"busyPolicy": {
|
|
107446
|
+
"enum": [
|
|
107447
|
+
"steer",
|
|
107448
|
+
"reject"
|
|
107449
|
+
],
|
|
107450
|
+
"type": "string"
|
|
107451
|
+
},
|
|
107452
|
+
"codexThreadId": {
|
|
107453
|
+
"type": "string"
|
|
107454
|
+
},
|
|
107455
|
+
"expectedCwd": {
|
|
107456
|
+
"type": "string"
|
|
107457
|
+
},
|
|
107458
|
+
"grokTarget": {
|
|
107459
|
+
"type": "string"
|
|
107460
|
+
},
|
|
107461
|
+
"requestId": {
|
|
107462
|
+
"type": "string"
|
|
107463
|
+
}
|
|
107464
|
+
},
|
|
107465
|
+
"required": [
|
|
107466
|
+
"grokTarget"
|
|
107467
|
+
],
|
|
107468
|
+
"type": "object"
|
|
107469
|
+
},
|
|
107470
|
+
"title": "gbot_bridge_start"
|
|
107471
|
+
},
|
|
107472
|
+
id: "tool:grok-bot/gbot_bridge_start",
|
|
107473
|
+
kind: "tool",
|
|
107474
|
+
module: route4,
|
|
107475
|
+
name: "gbot_bridge_start"
|
|
107476
|
+
}),
|
|
107477
|
+
"tool:grok-bot/gbot_bridge_status": Object.freeze({
|
|
107478
|
+
config: {
|
|
107479
|
+
"annotations": {
|
|
107480
|
+
"readOnlyHint": true
|
|
107481
|
+
},
|
|
107482
|
+
"description": "Inspect worker health, route coverage, bounded receipts and scoped pending operator interactions.",
|
|
107483
|
+
"inputJsonSchema": {
|
|
107484
|
+
"additionalProperties": false,
|
|
107485
|
+
"properties": {
|
|
107486
|
+
"bindingId": {
|
|
107487
|
+
"type": "string"
|
|
107488
|
+
},
|
|
107489
|
+
"limit": {
|
|
107490
|
+
"type": "number"
|
|
107491
|
+
}
|
|
107492
|
+
},
|
|
107493
|
+
"type": "object"
|
|
107494
|
+
},
|
|
107495
|
+
"title": "gbot_bridge_status"
|
|
107496
|
+
},
|
|
107497
|
+
id: "tool:grok-bot/gbot_bridge_status",
|
|
107498
|
+
kind: "tool",
|
|
107499
|
+
module: route5,
|
|
107500
|
+
name: "gbot_bridge_status"
|
|
107501
|
+
}),
|
|
107502
|
+
"tool:grok-bot/gbot_bridge_stop": Object.freeze({
|
|
107503
|
+
config: {
|
|
107504
|
+
"annotations": {
|
|
107505
|
+
"readOnlyHint": false
|
|
107506
|
+
},
|
|
107507
|
+
"description": "Stop a binding without deleting receipts or interrupting Codex. all stops all bindings; worker explicitly shuts down the worker.",
|
|
107508
|
+
"inputJsonSchema": {
|
|
107509
|
+
"additionalProperties": false,
|
|
107510
|
+
"properties": {
|
|
107511
|
+
"all": {
|
|
107512
|
+
"type": "boolean"
|
|
107513
|
+
},
|
|
107514
|
+
"bindingId": {
|
|
107515
|
+
"type": "string"
|
|
107516
|
+
},
|
|
107517
|
+
"worker": {
|
|
107518
|
+
"type": "boolean"
|
|
107519
|
+
}
|
|
107520
|
+
},
|
|
107521
|
+
"type": "object"
|
|
107522
|
+
},
|
|
107523
|
+
"title": "gbot_bridge_stop"
|
|
107524
|
+
},
|
|
107525
|
+
id: "tool:grok-bot/gbot_bridge_stop",
|
|
107526
|
+
kind: "tool",
|
|
107527
|
+
module: route6,
|
|
107528
|
+
name: "gbot_bridge_stop"
|
|
107529
|
+
}),
|
|
107530
|
+
"tool:grok-bot/gbot_codex_respond": Object.freeze({
|
|
107531
|
+
config: {
|
|
107532
|
+
"annotations": {
|
|
107533
|
+
"readOnlyHint": false
|
|
107534
|
+
},
|
|
107535
|
+
"description": "Explicit operator response to a current scoped Codex interaction. Supports only one-time accept/decline/cancel or exact question-ID answers. Never auto-approve.",
|
|
107536
|
+
"inputJsonSchema": {
|
|
107537
|
+
"additionalProperties": false,
|
|
107538
|
+
"properties": {
|
|
107539
|
+
"answersJson": {
|
|
107540
|
+
"description": "JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.",
|
|
107541
|
+
"type": "string"
|
|
107542
|
+
},
|
|
107543
|
+
"bindingId": {
|
|
107544
|
+
"type": "string"
|
|
107545
|
+
},
|
|
107546
|
+
"decision": {
|
|
107547
|
+
"enum": [
|
|
107548
|
+
"accept",
|
|
107549
|
+
"decline",
|
|
107550
|
+
"cancel"
|
|
107551
|
+
],
|
|
107552
|
+
"type": "string"
|
|
107553
|
+
},
|
|
107554
|
+
"exchangeId": {
|
|
107555
|
+
"type": "string"
|
|
107556
|
+
},
|
|
107557
|
+
"generation": {
|
|
107558
|
+
"type": "string"
|
|
107559
|
+
},
|
|
107560
|
+
"interactionId": {
|
|
107561
|
+
"type": "string"
|
|
107562
|
+
},
|
|
107563
|
+
"threadId": {
|
|
107564
|
+
"type": "string"
|
|
107565
|
+
},
|
|
107566
|
+
"turnId": {
|
|
107567
|
+
"type": "string"
|
|
107568
|
+
}
|
|
107569
|
+
},
|
|
107570
|
+
"required": [
|
|
107571
|
+
"interactionId",
|
|
107572
|
+
"generation",
|
|
107573
|
+
"threadId",
|
|
107574
|
+
"turnId"
|
|
107575
|
+
],
|
|
107576
|
+
"type": "object"
|
|
107577
|
+
},
|
|
107578
|
+
"title": "gbot_codex_respond"
|
|
107579
|
+
},
|
|
107580
|
+
id: "tool:grok-bot/gbot_codex_respond",
|
|
107581
|
+
kind: "tool",
|
|
107582
|
+
module: route7,
|
|
107583
|
+
name: "gbot_codex_respond"
|
|
107584
|
+
}),
|
|
106215
107585
|
"tool:grok-bot/gbot_send": Object.freeze({
|
|
106216
107586
|
config: {
|
|
106217
|
-
"
|
|
107587
|
+
"annotations": {
|
|
107588
|
+
"readOnlyHint": false
|
|
107589
|
+
},
|
|
107590
|
+
"description": "Send to Grok Bot. Native Codex calls automatically receive replies in their originating thread; send once and continue work. Without a native source, supply codexThreadId or use manual gbot_thread reading.",
|
|
106218
107591
|
"inputJsonSchema": {
|
|
106219
107592
|
"additionalProperties": false,
|
|
106220
107593
|
"properties": {
|
|
107594
|
+
"bindingId": {
|
|
107595
|
+
"type": "string"
|
|
107596
|
+
},
|
|
107597
|
+
"codexThreadId": {
|
|
107598
|
+
"type": "string"
|
|
107599
|
+
},
|
|
107600
|
+
"correlationId": {
|
|
107601
|
+
"type": "string"
|
|
107602
|
+
},
|
|
107603
|
+
"expectedCwd": {
|
|
107604
|
+
"type": "string"
|
|
107605
|
+
},
|
|
107606
|
+
"hop": {
|
|
107607
|
+
"description": "Explicit chain hop count, refused at the configured bound.",
|
|
107608
|
+
"type": "number"
|
|
107609
|
+
},
|
|
106221
107610
|
"message": {
|
|
106222
|
-
"
|
|
107611
|
+
"type": "string"
|
|
107612
|
+
},
|
|
107613
|
+
"replyMode": {
|
|
107614
|
+
"enum": [
|
|
107615
|
+
"auto",
|
|
107616
|
+
"manual"
|
|
107617
|
+
],
|
|
107618
|
+
"type": "string"
|
|
107619
|
+
},
|
|
107620
|
+
"requestId": {
|
|
106223
107621
|
"type": "string"
|
|
106224
107622
|
},
|
|
106225
107623
|
"target": {
|
|
106226
|
-
"description": "Bot or group name or id, for example \"General\".",
|
|
106227
107624
|
"type": "string"
|
|
106228
107625
|
}
|
|
106229
107626
|
},
|
|
@@ -106237,7 +107634,7 @@ const routes = Object.freeze({
|
|
|
106237
107634
|
},
|
|
106238
107635
|
id: "tool:grok-bot/gbot_send",
|
|
106239
107636
|
kind: "tool",
|
|
106240
|
-
module:
|
|
107637
|
+
module: route8,
|
|
106241
107638
|
name: "gbot_send"
|
|
106242
107639
|
}),
|
|
106243
107640
|
"tool:grok-bot/gbot_thread": Object.freeze({
|
|
@@ -106277,7 +107674,7 @@ const routes = Object.freeze({
|
|
|
106277
107674
|
},
|
|
106278
107675
|
id: "tool:grok-bot/gbot_thread",
|
|
106279
107676
|
kind: "tool",
|
|
106280
|
-
module:
|
|
107677
|
+
module: route9,
|
|
106281
107678
|
name: "gbot_thread"
|
|
106282
107679
|
})
|
|
106283
107680
|
});
|
|
@@ -106291,7 +107688,7 @@ const routes = Object.freeze({
|
|
|
106291
107688
|
lineage: lineage.registry,
|
|
106292
107689
|
plugin: {
|
|
106293
107690
|
"name": "gbot",
|
|
106294
|
-
"version": "0.
|
|
107691
|
+
"version": "0.6.0"
|
|
106295
107692
|
},
|
|
106296
107693
|
pluginRoot: pluginRoot.identity,
|
|
106297
107694
|
routes
|
|
@@ -106544,10 +107941,2511 @@ function inspectGrokBotGatewaySession(options = {}) {
|
|
|
106544
107941
|
}
|
|
106545
107942
|
|
|
106546
107943
|
__webpack_require__.d(__webpack_exports__, {
|
|
106547
|
-
Z2: () => (loadGrokBotGatewaySession)
|
|
107944
|
+
Z2: () => (loadGrokBotGatewaySession),
|
|
107945
|
+
dQ: () => (grokBotGatewayDescriptorPath)
|
|
107946
|
+
});
|
|
107947
|
+
|
|
107948
|
+
|
|
107949
|
+
},
|
|
107950
|
+
"./src/core/codex-bridge.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
107951
|
+
/* import */ var node_crypto__rspack_import_0 = __webpack_require__("node:crypto");
|
|
107952
|
+
/* import */ var node_fs__rspack_import_1 = __webpack_require__("node:fs");
|
|
107953
|
+
/* import */ var node_net__rspack_import_2 = __webpack_require__("node:net");
|
|
107954
|
+
/* import */ var node_os__rspack_import_3 = __webpack_require__("node:os");
|
|
107955
|
+
/* import */ var node_path__rspack_import_4 = __webpack_require__("node:path");
|
|
107956
|
+
/* import */ var node_child_process__rspack_import_5 = __webpack_require__("node:child_process");
|
|
107957
|
+
/* import */ var _package_json__rspack_import_6 = __webpack_require__("./package.json");
|
|
107958
|
+
/* import */ var _codex_contract_js__rspack_import_7 = __webpack_require__("./src/core/codex/contract.js");
|
|
107959
|
+
/* import */ var _desktop_shim_js__rspack_import_8 = __webpack_require__("./src/core/desktop-shim.js");
|
|
107960
|
+
|
|
107961
|
+
|
|
107962
|
+
|
|
107963
|
+
|
|
107964
|
+
|
|
107965
|
+
|
|
107966
|
+
|
|
107967
|
+
|
|
107968
|
+
|
|
107969
|
+
// Method and param names below come from `codex app-server generate-json-schema`
|
|
107970
|
+
// of this Codex release. Newer daemons usually keep them; `gbot codex status`
|
|
107971
|
+
// reports the running daemon's version next to this one.
|
|
107972
|
+
const PINNED_CODEX_VERSION = "0.154.0";
|
|
107973
|
+
const UPSTREAM_DESKTOP_ISSUES = [
|
|
107974
|
+
"https://github.com/openai/codex/issues/41014",
|
|
107975
|
+
"https://github.com/openai/codex/issues/41112"
|
|
107976
|
+
];
|
|
107977
|
+
const WS_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
|
107978
|
+
// Transport budgets: fail fast instead of buffering unbounded attacker-controlled bytes.
|
|
107979
|
+
// ponytail: raise these only with streaming/pagination support; the app-server sends small JSON-RPC frames.
|
|
107980
|
+
const WS_MAX_HEADER_BYTES = 16 * 1024;
|
|
107981
|
+
const WS_MAX_MESSAGE_BYTES = 4 * 1024 * 1024;
|
|
107982
|
+
const WS_MAX_BUFFER_BYTES = 8 * 1024 * 1024;
|
|
107983
|
+
const WS_MAX_WRITE_BYTES = 8 * 1024 * 1024;
|
|
107984
|
+
const CODEX_MAX_REQUESTS = 128;
|
|
107985
|
+
const CODEX_MAX_LISTENERS = 128;
|
|
107986
|
+
const textDecoder = new TextDecoder("utf-8", {
|
|
107987
|
+
fatal: true
|
|
107988
|
+
});
|
|
107989
|
+
function codexSocketPath(env = process.env) {
|
|
107990
|
+
// Explicit socket wins so status/send/queue agree with a shim-installed or
|
|
107991
|
+
// operator-exported CODEX_APP_SERVER_SOCK; otherwise derive from CODEX_HOME.
|
|
107992
|
+
if (env.CODEX_APP_SERVER_SOCK) return env.CODEX_APP_SERVER_SOCK;
|
|
107993
|
+
const home = env.CODEX_HOME || (0,node_path__rspack_import_4.join)((0,node_os__rspack_import_3.homedir)(), ".codex");
|
|
107994
|
+
return (0,node_path__rspack_import_4.join)(home, "app-server-control", "app-server-control.sock");
|
|
107995
|
+
}
|
|
107996
|
+
/** `socket` | `absent` | `permission-denied` | `not-a-socket`; permission failures are not absence. */ function socketState(path) {
|
|
107997
|
+
try {
|
|
107998
|
+
return (0,node_fs__rspack_import_1.statSync)(path).isSocket() ? "socket" : "not-a-socket";
|
|
107999
|
+
} catch (err) {
|
|
108000
|
+
return err && (err.code === "EACCES" || err.code === "EPERM") ? "permission-denied" : "absent";
|
|
108001
|
+
}
|
|
108002
|
+
}
|
|
108003
|
+
/** Strip ANSI/OSC sequences and C0/C1 controls (tab and newline stay) from server-supplied text. */ function stripTerminalControls(text) {
|
|
108004
|
+
return String(text).replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, "").replace(/\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)/g, "").replace(/\u001b./g, "").replace(/[\u0000-\u0008\u000B-\u001F\u007F-\u009F]/g, "");
|
|
108005
|
+
}
|
|
108006
|
+
/** Single-line fields (ids, names, paths, cursors, header tokens): no line breaks or tabs survive. */ function singleLine(text) {
|
|
108007
|
+
return stripTerminalControls(text).replace(/[\t\n\r\u2028\u2029]+/g, " ");
|
|
108008
|
+
}
|
|
108009
|
+
function unreachableMessage(path, desktopAttached = "unknown") {
|
|
108010
|
+
if (desktopAttached === "private-stdio") {
|
|
108011
|
+
return [
|
|
108012
|
+
"ChatGPT Desktop is running its private stdio app-server, which external clients cannot reach",
|
|
108013
|
+
"(" + UPSTREAM_DESKTOP_ISSUES.join(", ") + ").",
|
|
108014
|
+
"No Codex app-server control socket at " + path + ": start a managed standalone daemon with `codex app-server daemon start`.",
|
|
108015
|
+
"gbot codex targets daemon-managed threads only."
|
|
108016
|
+
].join("\n");
|
|
108017
|
+
}
|
|
108018
|
+
return [
|
|
108019
|
+
"No Codex app-server control socket at " + path + ".",
|
|
108020
|
+
"Either no daemon is running (start one with `codex app-server daemon start`),",
|
|
108021
|
+
"or ChatGPT Desktop is running a private stdio app-server that external clients cannot reach",
|
|
108022
|
+
"(" + UPSTREAM_DESKTOP_ISSUES.join(", ") + ").",
|
|
108023
|
+
"gbot codex targets daemon-managed threads only."
|
|
108024
|
+
].join("\n");
|
|
108025
|
+
}
|
|
108026
|
+
function windowsUnsupportedMessage() {
|
|
108027
|
+
return [
|
|
108028
|
+
"gbot codex does not support native Windows yet.",
|
|
108029
|
+
"Codex's control socket is AF_UNIX; this CLI's Node client only dials Unix domain sockets.",
|
|
108030
|
+
"Use WSL, Linux, or macOS (or a future stdio proxy path)."
|
|
108031
|
+
].join("\n");
|
|
108032
|
+
}
|
|
108033
|
+
function encodeFrame(opcode, payload, mask) {
|
|
108034
|
+
const len = payload.length;
|
|
108035
|
+
const head = Buffer.alloc(len < 126 ? 2 : len < 65536 ? 4 : 10);
|
|
108036
|
+
head[0] = 0x80 | opcode;
|
|
108037
|
+
if (len < 126) head[1] = len;
|
|
108038
|
+
else if (len < 65536) {
|
|
108039
|
+
head[1] = 126;
|
|
108040
|
+
head.writeUInt16BE(len, 2);
|
|
108041
|
+
} else {
|
|
108042
|
+
head[1] = 127;
|
|
108043
|
+
head.writeBigUInt64BE(BigInt(len), 2);
|
|
108044
|
+
}
|
|
108045
|
+
if (!mask) return Buffer.concat([
|
|
108046
|
+
head,
|
|
108047
|
+
payload
|
|
108048
|
+
]);
|
|
108049
|
+
head[1] |= 0x80;
|
|
108050
|
+
const body = Buffer.from(payload);
|
|
108051
|
+
for(let i = 0; i < body.length; i++)body[i] ^= mask[i & 3];
|
|
108052
|
+
return Buffer.concat([
|
|
108053
|
+
head,
|
|
108054
|
+
mask,
|
|
108055
|
+
body
|
|
108056
|
+
]);
|
|
108057
|
+
}
|
|
108058
|
+
function decodeFrame(buf) {
|
|
108059
|
+
if (buf.length < 2) return null;
|
|
108060
|
+
const fin = (buf[0] & 0x80) !== 0;
|
|
108061
|
+
const opcode = buf[0] & 0x0f;
|
|
108062
|
+
const masked = (buf[1] & 0x80) !== 0;
|
|
108063
|
+
let len = buf[1] & 0x7f;
|
|
108064
|
+
let offset = 2;
|
|
108065
|
+
if (len === 126) {
|
|
108066
|
+
if (buf.length < 4) return null;
|
|
108067
|
+
len = buf.readUInt16BE(2);
|
|
108068
|
+
offset = 4;
|
|
108069
|
+
} else if (len === 127) {
|
|
108070
|
+
if (buf.length < 10) return null;
|
|
108071
|
+
len = Number(buf.readBigUInt64BE(2));
|
|
108072
|
+
offset = 10;
|
|
108073
|
+
}
|
|
108074
|
+
const mask = masked ? buf.subarray(offset, offset + 4) : null;
|
|
108075
|
+
if (masked) offset += 4;
|
|
108076
|
+
if (buf.length < offset + len) return null;
|
|
108077
|
+
const payload = Buffer.from(buf.subarray(offset, offset + len));
|
|
108078
|
+
if (mask) for(let i = 0; i < payload.length; i++)payload[i] ^= mask[i & 3];
|
|
108079
|
+
return {
|
|
108080
|
+
fin,
|
|
108081
|
+
opcode,
|
|
108082
|
+
masked,
|
|
108083
|
+
payload,
|
|
108084
|
+
rest: buf.subarray(offset + len)
|
|
108085
|
+
};
|
|
108086
|
+
}
|
|
108087
|
+
/** Claimed frame length without consuming; null when the length prefix is incomplete. */ function peekFrameLength(buf) {
|
|
108088
|
+
if (buf.length < 2) return null;
|
|
108089
|
+
const marker = buf[1] & 0x7f;
|
|
108090
|
+
if (marker < 126) return marker;
|
|
108091
|
+
if (marker === 126) {
|
|
108092
|
+
if (buf.length < 4) return null;
|
|
108093
|
+
return buf.readUInt16BE(2);
|
|
108094
|
+
}
|
|
108095
|
+
if (buf.length < 10) return null;
|
|
108096
|
+
const big = buf.readBigUInt64BE(2);
|
|
108097
|
+
return big > BigInt(Number.MAX_SAFE_INTEGER) ? Infinity : Number(big);
|
|
108098
|
+
}
|
|
108099
|
+
function validateUpgradeHead(head, key) {
|
|
108100
|
+
const lines = head.split("\r\n");
|
|
108101
|
+
if (!/^HTTP\/1\.1 101/.test(lines[0])) return false;
|
|
108102
|
+
const headers = new Map();
|
|
108103
|
+
for (const line of lines.slice(1)){
|
|
108104
|
+
const i = line.indexOf(":");
|
|
108105
|
+
if (i === -1) return false;
|
|
108106
|
+
headers.set(line.slice(0, i).trim().toLowerCase(), line.slice(i + 1).trim());
|
|
108107
|
+
}
|
|
108108
|
+
return headers.get("sec-websocket-accept") === websocketAccept(key) && (headers.get("upgrade") || "").toLowerCase() === "websocket" && (headers.get("connection") || "").toLowerCase().includes("upgrade");
|
|
108109
|
+
}
|
|
108110
|
+
function upgradeRequest(key) {
|
|
108111
|
+
return "GET / HTTP/1.1\r\nHost: localhost\r\nUpgrade: websocket\r\nConnection: Upgrade\r\n" + "Sec-WebSocket-Key: " + key + "\r\nSec-WebSocket-Version: 13\r\n\r\n";
|
|
108112
|
+
}
|
|
108113
|
+
function websocketAccept(key) {
|
|
108114
|
+
return (0,node_crypto__rspack_import_0.createHash)("sha1").update(key + WS_GUID).digest("base64");
|
|
108115
|
+
}
|
|
108116
|
+
class CodexRpcError extends Error {
|
|
108117
|
+
constructor(method, error){
|
|
108118
|
+
super("Codex app-server rejected " + method + ": " + (error && error.message ? error.message : JSON.stringify(error)));
|
|
108119
|
+
this.name = "CodexRpcError";
|
|
108120
|
+
this.method = method;
|
|
108121
|
+
this.rpc = error;
|
|
108122
|
+
}
|
|
108123
|
+
}
|
|
108124
|
+
class CodexSendError extends Error {
|
|
108125
|
+
constructor(message, { correlationId, delivery, hop, messageId, reason, refused, threadId, turnId } = {}){
|
|
108126
|
+
super(message);
|
|
108127
|
+
this.name = "CodexSendError";
|
|
108128
|
+
this.delivery = delivery;
|
|
108129
|
+
if (correlationId !== undefined) this.correlationId = correlationId;
|
|
108130
|
+
if (hop !== undefined) this.hop = hop;
|
|
108131
|
+
if (messageId !== undefined) this.messageId = messageId;
|
|
108132
|
+
if (reason !== undefined) this.reason = reason;
|
|
108133
|
+
if (refused !== undefined) this.refused = refused;
|
|
108134
|
+
if (threadId !== undefined) this.threadId = threadId;
|
|
108135
|
+
if (turnId !== undefined) this.turnId = turnId;
|
|
108136
|
+
}
|
|
108137
|
+
}
|
|
108138
|
+
function attachEnvelope(error, envelope) {
|
|
108139
|
+
if (!error || typeof error !== "object") return;
|
|
108140
|
+
for (const key of [
|
|
108141
|
+
"messageId",
|
|
108142
|
+
"correlationId",
|
|
108143
|
+
"hop"
|
|
108144
|
+
]){
|
|
108145
|
+
if (envelope?.[key] !== undefined) error[key] = envelope[key];
|
|
108146
|
+
}
|
|
108147
|
+
}
|
|
108148
|
+
/** The route to the app-server is unavailable; `mode` is a stable machine-readable state. */ class CodexRouteError extends Error {
|
|
108149
|
+
constructor(message, mode){
|
|
108150
|
+
super(message);
|
|
108151
|
+
this.name = "CodexRouteError";
|
|
108152
|
+
this.mode = mode;
|
|
108153
|
+
this.delivery = "rejected";
|
|
108154
|
+
this.reason = mode;
|
|
108155
|
+
}
|
|
108156
|
+
}
|
|
108157
|
+
/** The app-server answered with a shape this pinned schema does not describe. */ class CodexProtocolError extends Error {
|
|
108158
|
+
constructor(method, detail){
|
|
108159
|
+
super("Codex app-server returned an unexpected " + method + " response: " + detail + ". gbot is pinned to app-server schema " + PINNED_CODEX_VERSION + "; run `gbot codex status --json` to compare versions.");
|
|
108160
|
+
this.name = "CodexProtocolError";
|
|
108161
|
+
this.method = method;
|
|
108162
|
+
this.mode = "bad-response";
|
|
108163
|
+
this.reason = "bad-response";
|
|
108164
|
+
}
|
|
108165
|
+
}
|
|
108166
|
+
function isObject(value) {
|
|
108167
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
108168
|
+
}
|
|
108169
|
+
/** Failures before the WebSocket upgrade completes: the socket is present but unusable. */ function connectError(err, path) {
|
|
108170
|
+
const code = err && err.cause && err.cause.code ? err.cause.code : err && err.code;
|
|
108171
|
+
const message = err && err.message ? err.message : String(err);
|
|
108172
|
+
if (code === "EACCES" || code === "EPERM" || /\bEACCES\b|\bEPERM\b/.test(message)) {
|
|
108173
|
+
return new CodexRouteError("Codex app-server control socket at " + path + " refused the connection for this user (" + code + "). " + "gbot runs as the user who owns CODEX_HOME; check the socket's owner and mode.", "permission-denied");
|
|
108174
|
+
}
|
|
108175
|
+
if (/refused the WebSocket upgrade|violated the WebSocket protocol|handshake headers exceed/.test(message)) {
|
|
108176
|
+
return new CodexRouteError(message, "handshake-failed");
|
|
108177
|
+
}
|
|
108178
|
+
return new CodexRouteError(message + " (socket present at " + path + ", but no app-server completed the connection).", "connect-failed");
|
|
108179
|
+
}
|
|
108180
|
+
/** Failures while initializing an upgraded connection: reachable transport, unusable session. */ function handshakeError(err) {
|
|
108181
|
+
if (err instanceof CodexProtocolError) return err;
|
|
108182
|
+
const message = err && err.message ? err.message : String(err);
|
|
108183
|
+
return new CodexRouteError("Codex app-server accepted the connection but initialize failed: " + message, "handshake-failed");
|
|
108184
|
+
}
|
|
108185
|
+
/** Failures after a session exists: the request may or may not have been processed. */ function transportError(err) {
|
|
108186
|
+
if (err instanceof CodexRpcError || err instanceof CodexProtocolError || err instanceof CodexSendError || err instanceof CodexRouteError) return err;
|
|
108187
|
+
if (err && typeof err === "object" && err.reason === undefined) err.reason = "transport";
|
|
108188
|
+
return err;
|
|
108189
|
+
}
|
|
108190
|
+
/**
|
|
108191
|
+
* Open a JSON-RPC session to the app-server over its Unix socket (WebSocket framing).
|
|
108192
|
+
* Server requests are observed without answering by default. Legacy one-shot
|
|
108193
|
+
* callers arm ownership-scoped refusals; persistent sessions respond explicitly.
|
|
108194
|
+
*/ function connectCodexAppServer(path, { timeoutMs = 15000, signal, onNotification, onServerRequest, onClose } = {}) {
|
|
108195
|
+
return new Promise((resolve, reject)=>{
|
|
108196
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2147483647) {
|
|
108197
|
+
throw new RangeError("timeoutMs must be an integer 1-2147483647");
|
|
108198
|
+
}
|
|
108199
|
+
for (const listener of [
|
|
108200
|
+
onNotification,
|
|
108201
|
+
onServerRequest,
|
|
108202
|
+
onClose
|
|
108203
|
+
]){
|
|
108204
|
+
if (listener !== undefined && typeof listener !== "function") throw new TypeError("Event listener must be a function");
|
|
108205
|
+
}
|
|
108206
|
+
if (signal !== undefined && !(signal instanceof AbortSignal)) throw new TypeError("signal must be an AbortSignal");
|
|
108207
|
+
if (signal?.aborted) throw new Error("Codex connection aborted", {
|
|
108208
|
+
cause: signal.reason
|
|
108209
|
+
});
|
|
108210
|
+
const socket = (0,node_net__rspack_import_2.createConnection)({
|
|
108211
|
+
path
|
|
108212
|
+
});
|
|
108213
|
+
const key = (0,node_crypto__rspack_import_0.randomBytes)(16).toString("base64");
|
|
108214
|
+
const pending = new Map();
|
|
108215
|
+
const refused = [];
|
|
108216
|
+
const serverRequests = new Map();
|
|
108217
|
+
const listeners = {
|
|
108218
|
+
notification: new Set(onNotification ? [
|
|
108219
|
+
onNotification
|
|
108220
|
+
] : []),
|
|
108221
|
+
serverRequest: new Set(onServerRequest ? [
|
|
108222
|
+
onServerRequest
|
|
108223
|
+
] : []),
|
|
108224
|
+
close: new Set(onClose ? [
|
|
108225
|
+
onClose
|
|
108226
|
+
] : [])
|
|
108227
|
+
};
|
|
108228
|
+
let closeError;
|
|
108229
|
+
let writeTimer;
|
|
108230
|
+
let nextId = 1;
|
|
108231
|
+
let buf = Buffer.alloc(0);
|
|
108232
|
+
let upgraded = false;
|
|
108233
|
+
let closed = false;
|
|
108234
|
+
let fragOpcode = null;
|
|
108235
|
+
let fragParts = [];
|
|
108236
|
+
let fragBytes = 0;
|
|
108237
|
+
// Absolute handshake deadline: socket timeouts reset on any bytes, so trickled
|
|
108238
|
+
// headers must not extend this. Per-request timers stay absolute after upgrade.
|
|
108239
|
+
const handshakeTimer = setTimeout(()=>failAll(new Error("Timed out connecting to Codex app-server at " + path)), timeoutMs);
|
|
108240
|
+
if (typeof handshakeTimer.unref === "function") handshakeTimer.unref();
|
|
108241
|
+
const failAll = (err)=>{
|
|
108242
|
+
if (closed) return;
|
|
108243
|
+
closed = true;
|
|
108244
|
+
closeError = err;
|
|
108245
|
+
clearTimeout(handshakeTimer);
|
|
108246
|
+
clearTimeout(writeTimer);
|
|
108247
|
+
signal?.removeEventListener("abort", abort);
|
|
108248
|
+
if (err && err.delivery == null) err.delivery = pending.size ? "unknown" : "rejected";
|
|
108249
|
+
for (const { reject: rej } of pending.values())rej(err);
|
|
108250
|
+
pending.clear();
|
|
108251
|
+
serverRequests.clear();
|
|
108252
|
+
client.deferred.length = 0;
|
|
108253
|
+
buf = Buffer.alloc(0);
|
|
108254
|
+
fragParts = [];
|
|
108255
|
+
fragBytes = 0;
|
|
108256
|
+
const closeListeners = [
|
|
108257
|
+
...listeners.close
|
|
108258
|
+
];
|
|
108259
|
+
for (const group of Object.values(listeners))group.clear();
|
|
108260
|
+
try {
|
|
108261
|
+
socket.destroy();
|
|
108262
|
+
} catch {}
|
|
108263
|
+
reject(err);
|
|
108264
|
+
for (const listener of closeListeners)invoke(listener, err, true);
|
|
108265
|
+
};
|
|
108266
|
+
// Observers execute synchronously to preserve order, but failures never escape
|
|
108267
|
+
// the socket callback. Rejected async callbacks use the same cleanup path.
|
|
108268
|
+
const invoke = (listener, message, closing = false)=>{
|
|
108269
|
+
const failed = (cause)=>{
|
|
108270
|
+
if (!closing) failAll(new Error("Codex event listener failed", {
|
|
108271
|
+
cause
|
|
108272
|
+
}));
|
|
108273
|
+
};
|
|
108274
|
+
try {
|
|
108275
|
+
const result = listener(message);
|
|
108276
|
+
if (result && typeof result.then === "function") Promise.resolve(result).catch(failed);
|
|
108277
|
+
} catch (err) {
|
|
108278
|
+
failed(err);
|
|
108279
|
+
}
|
|
108280
|
+
};
|
|
108281
|
+
const dispatch = (kind, message)=>{
|
|
108282
|
+
for (const listener of [
|
|
108283
|
+
...listeners[kind]
|
|
108284
|
+
]){
|
|
108285
|
+
if (closed) break;
|
|
108286
|
+
if (listeners[kind].has(listener)) invoke(listener, message);
|
|
108287
|
+
}
|
|
108288
|
+
};
|
|
108289
|
+
const subscribe = (kind, listener)=>{
|
|
108290
|
+
if (typeof listener !== "function") throw new TypeError("Event listener must be a function");
|
|
108291
|
+
if (closed) {
|
|
108292
|
+
if (kind === "close") invoke(listener, closeError, true);
|
|
108293
|
+
return ()=>{};
|
|
108294
|
+
}
|
|
108295
|
+
const group = listeners[kind];
|
|
108296
|
+
if (!group.has(listener) && group.size >= CODEX_MAX_LISTENERS) {
|
|
108297
|
+
const err = new Error("Codex listener limit exceeds " + CODEX_MAX_LISTENERS);
|
|
108298
|
+
failAll(err);
|
|
108299
|
+
throw err;
|
|
108300
|
+
}
|
|
108301
|
+
group.add(listener);
|
|
108302
|
+
return ()=>group.delete(listener);
|
|
108303
|
+
};
|
|
108304
|
+
const abort = ()=>failAll(new Error("Codex connection aborted", {
|
|
108305
|
+
cause: signal.reason
|
|
108306
|
+
}));
|
|
108307
|
+
const failProtocol = (detail)=>failAll(new Error("Codex app-server violated the WebSocket protocol: " + detail));
|
|
108308
|
+
const write = (opcode, payload)=>{
|
|
108309
|
+
if (closed) throw closeError;
|
|
108310
|
+
const encodedBytes = payload.length + (payload.length < 126 ? 6 : payload.length < 65536 ? 8 : 14);
|
|
108311
|
+
if (socket.destroyed || encodedBytes + socket.writableLength > WS_MAX_WRITE_BYTES) {
|
|
108312
|
+
const err = new Error(socket.destroyed ? "Codex socket closed" : "Codex outbound write budget exceeds " + WS_MAX_WRITE_BYTES + " bytes");
|
|
108313
|
+
failAll(err);
|
|
108314
|
+
throw err;
|
|
108315
|
+
}
|
|
108316
|
+
try {
|
|
108317
|
+
if (!socket.write(encodeFrame(opcode, payload, (0,node_crypto__rspack_import_0.randomBytes)(4))) && !writeTimer) {
|
|
108318
|
+
// One absolute deadline for the whole backpressured interval: more
|
|
108319
|
+
// writes must not keep an unread socket alive indefinitely.
|
|
108320
|
+
writeTimer = setTimeout(()=>failAll(new Error("Codex outbound write did not drain within " + timeoutMs + "ms")), timeoutMs);
|
|
108321
|
+
writeTimer.unref();
|
|
108322
|
+
}
|
|
108323
|
+
} catch (err) {
|
|
108324
|
+
failAll(err);
|
|
108325
|
+
throw err;
|
|
108326
|
+
}
|
|
108327
|
+
};
|
|
108328
|
+
const sendJson = (obj)=>write(0x1, Buffer.from(JSON.stringify(obj)));
|
|
108329
|
+
const respondToRequest = (id, payload)=>{
|
|
108330
|
+
if (closed) throw closeError;
|
|
108331
|
+
if (!serverRequests.has(id)) throw new Error("Unknown or resolved server request: " + id);
|
|
108332
|
+
// Consume ownership before JSON.stringify can invoke caller-owned getters
|
|
108333
|
+
// or toJSON hooks. A failed serialization closes rather than restoring it.
|
|
108334
|
+
serverRequests.delete(id);
|
|
108335
|
+
client.deferred = client.deferred.filter((entry)=>entry.id !== id);
|
|
108336
|
+
try {
|
|
108337
|
+
sendJson({
|
|
108338
|
+
jsonrpc: "2.0",
|
|
108339
|
+
id,
|
|
108340
|
+
...payload
|
|
108341
|
+
});
|
|
108342
|
+
} catch (cause) {
|
|
108343
|
+
if (closed) throw closeError;
|
|
108344
|
+
const err = new Error("Codex server response serialization failed", {
|
|
108345
|
+
cause
|
|
108346
|
+
});
|
|
108347
|
+
failAll(err);
|
|
108348
|
+
throw err;
|
|
108349
|
+
}
|
|
108350
|
+
};
|
|
108351
|
+
const client = {
|
|
108352
|
+
refused,
|
|
108353
|
+
get closed () {
|
|
108354
|
+
return closed;
|
|
108355
|
+
},
|
|
108356
|
+
onNotification: (listener)=>subscribe("notification", listener),
|
|
108357
|
+
onServerRequest: (listener)=>subscribe("serverRequest", listener),
|
|
108358
|
+
onClose: (listener)=>subscribe("close", listener),
|
|
108359
|
+
respond: (id, result)=>respondToRequest(id, {
|
|
108360
|
+
result
|
|
108361
|
+
}),
|
|
108362
|
+
rejectRequest: (id, error)=>respondToRequest(id, {
|
|
108363
|
+
error
|
|
108364
|
+
}),
|
|
108365
|
+
// Server-initiated requests are only *answered* once our own turn/start
|
|
108366
|
+
// is in flight, and then only when they name our own thread/turn:
|
|
108367
|
+
// anything earlier — or naming another thread or Desktop turn — belongs
|
|
108368
|
+
// to another client and must never be rejected on their behalf. Early
|
|
108369
|
+
// and foreign requests are still recorded; the connection closes right
|
|
108370
|
+
// after, so a pending request simply dies with it instead of denying
|
|
108371
|
+
// someone's approval.
|
|
108372
|
+
answerServerRequests: false,
|
|
108373
|
+
expectedThreadId: null,
|
|
108374
|
+
expectedTurnId: null,
|
|
108375
|
+
// Approvals that name a turn while our own turn id is still unknown
|
|
108376
|
+
// (arriving before — or in the same socket batch as — the turn/start
|
|
108377
|
+
// acknowledgment) wait here instead of being classified foreign: once
|
|
108378
|
+
// the acknowledgment supplies the turn id, matching ones are answered
|
|
108379
|
+
// and the rest stay silent.
|
|
108380
|
+
deferred: [],
|
|
108381
|
+
// Adopt the acknowledged turn id, answering deferred requests that
|
|
108382
|
+
// prove to be ours. Runs inside the connection closure so it can send.
|
|
108383
|
+
_adoptTurn (turnId) {
|
|
108384
|
+
client.expectedTurnId = turnId;
|
|
108385
|
+
for (const entry of client.deferred.splice(0)){
|
|
108386
|
+
const params = entry.params && typeof entry.params === "object" && !Array.isArray(entry.params) ? entry.params : null;
|
|
108387
|
+
const threadId = params ? params.threadId ?? params.thread_id : null;
|
|
108388
|
+
const namedTurnId = params ? params.turnId ?? params.turn_id ?? (params.turn && params.turn.id) : null;
|
|
108389
|
+
if (threadId === client.expectedThreadId && namedTurnId === turnId && serverRequests.get(entry.id) === entry) {
|
|
108390
|
+
client.rejectRequest(entry.id, {
|
|
108391
|
+
code: -32601,
|
|
108392
|
+
message: "gbot codex does not answer " + entry.method + "; configure approval_policy on the daemon"
|
|
108393
|
+
});
|
|
108394
|
+
entry.answered = true;
|
|
108395
|
+
}
|
|
108396
|
+
}
|
|
108397
|
+
},
|
|
108398
|
+
request (method, params) {
|
|
108399
|
+
return new Promise((res, rej)=>{
|
|
108400
|
+
if (closed) return rej(closeError);
|
|
108401
|
+
if (pending.size >= CODEX_MAX_REQUESTS) {
|
|
108402
|
+
const err = new Error("Codex pending request limit exceeds " + CODEX_MAX_REQUESTS);
|
|
108403
|
+
failAll(err);
|
|
108404
|
+
return rej(err);
|
|
108405
|
+
}
|
|
108406
|
+
const id = nextId++;
|
|
108407
|
+
const timer = setTimeout(()=>{
|
|
108408
|
+
pending.delete(id);
|
|
108409
|
+
rej(new Error("Codex app-server did not answer " + method + " within " + timeoutMs + "ms"));
|
|
108410
|
+
}, timeoutMs);
|
|
108411
|
+
pending.set(id, {
|
|
108412
|
+
method,
|
|
108413
|
+
resolve: (v)=>{
|
|
108414
|
+
clearTimeout(timer);
|
|
108415
|
+
res(v);
|
|
108416
|
+
},
|
|
108417
|
+
reject: (e)=>{
|
|
108418
|
+
clearTimeout(timer);
|
|
108419
|
+
rej(e);
|
|
108420
|
+
}
|
|
108421
|
+
});
|
|
108422
|
+
try {
|
|
108423
|
+
sendJson({
|
|
108424
|
+
jsonrpc: "2.0",
|
|
108425
|
+
id,
|
|
108426
|
+
method,
|
|
108427
|
+
params
|
|
108428
|
+
});
|
|
108429
|
+
} catch (err) {
|
|
108430
|
+
const entry = pending.get(id);
|
|
108431
|
+
pending.delete(id);
|
|
108432
|
+
entry?.reject(err);
|
|
108433
|
+
}
|
|
108434
|
+
});
|
|
108435
|
+
},
|
|
108436
|
+
notify (method, params) {
|
|
108437
|
+
sendJson({
|
|
108438
|
+
jsonrpc: "2.0",
|
|
108439
|
+
method,
|
|
108440
|
+
params
|
|
108441
|
+
});
|
|
108442
|
+
},
|
|
108443
|
+
close () {
|
|
108444
|
+
if (closed) return;
|
|
108445
|
+
// Best effort protocol close; cleanup never depends on the peer reading it.
|
|
108446
|
+
try {
|
|
108447
|
+
if (upgraded) write(0x8, Buffer.from([
|
|
108448
|
+
0x03,
|
|
108449
|
+
0xe8
|
|
108450
|
+
]));
|
|
108451
|
+
} catch {}
|
|
108452
|
+
failAll(new Error("Codex client closed"));
|
|
108453
|
+
}
|
|
108454
|
+
};
|
|
108455
|
+
signal?.addEventListener("abort", abort, {
|
|
108456
|
+
once: true
|
|
108457
|
+
});
|
|
108458
|
+
const onMessage = (msg)=>{
|
|
108459
|
+
if (msg.id != null && msg.method) {
|
|
108460
|
+
if (serverRequests.has(msg.id)) return failProtocol("duplicate pending server request id");
|
|
108461
|
+
if (serverRequests.size >= CODEX_MAX_REQUESTS || refused.length >= CODEX_MAX_REQUESTS || client.deferred.length >= CODEX_MAX_REQUESTS) {
|
|
108462
|
+
return failAll(new Error("Codex remembered server request limit exceeds " + CODEX_MAX_REQUESTS));
|
|
108463
|
+
}
|
|
108464
|
+
const entry = {
|
|
108465
|
+
id: msg.id,
|
|
108466
|
+
method: msg.method,
|
|
108467
|
+
params: msg.params,
|
|
108468
|
+
answered: false
|
|
108469
|
+
};
|
|
108470
|
+
serverRequests.set(msg.id, entry);
|
|
108471
|
+
dispatch("serverRequest", msg);
|
|
108472
|
+
if (closed) return;
|
|
108473
|
+
let answered = client.answerServerRequests;
|
|
108474
|
+
let defer = false;
|
|
108475
|
+
// Approval ownership: only answer requests for the turn gbot itself
|
|
108476
|
+
// started. A request naming another thread — or naming a turn that is
|
|
108477
|
+
// not ours — is recorded foreign-silent, never rejected. A request
|
|
108478
|
+
// naming a turn while our turn id is still unknown is deferred, not
|
|
108479
|
+
// classified: the turn/start acknowledgment decides it.
|
|
108480
|
+
if (answered) {
|
|
108481
|
+
const params = msg.params && typeof msg.params === "object" && !Array.isArray(msg.params) ? msg.params : null;
|
|
108482
|
+
if (params) {
|
|
108483
|
+
const threadId = params.threadId ?? params.thread_id;
|
|
108484
|
+
const turnId = params.turnId ?? params.turn_id ?? (params.turn && params.turn.id);
|
|
108485
|
+
if (threadId !== client.expectedThreadId || turnId == null) answered = false;
|
|
108486
|
+
else if (client.expectedTurnId == null) {
|
|
108487
|
+
answered = false;
|
|
108488
|
+
defer = true;
|
|
108489
|
+
} else if (turnId !== client.expectedTurnId) answered = false;
|
|
108490
|
+
} else answered = false;
|
|
108491
|
+
}
|
|
108492
|
+
answered = answered && serverRequests.has(msg.id);
|
|
108493
|
+
defer = defer && serverRequests.has(msg.id);
|
|
108494
|
+
entry.answered = answered;
|
|
108495
|
+
refused.push(entry);
|
|
108496
|
+
if (defer) {
|
|
108497
|
+
client.deferred.push(entry);
|
|
108498
|
+
return;
|
|
108499
|
+
}
|
|
108500
|
+
if (!answered) return;
|
|
108501
|
+
client.rejectRequest(msg.id, {
|
|
108502
|
+
code: -32601,
|
|
108503
|
+
message: "gbot codex does not answer " + msg.method + "; configure approval_policy on the daemon"
|
|
108504
|
+
});
|
|
108505
|
+
return;
|
|
108506
|
+
}
|
|
108507
|
+
if (msg.id == null && msg.method) {
|
|
108508
|
+
if (msg.method === "serverRequest/resolved") {
|
|
108509
|
+
const id = msg.params?.requestId;
|
|
108510
|
+
serverRequests.delete(id);
|
|
108511
|
+
client.deferred = client.deferred.filter((entry)=>entry.id !== id);
|
|
108512
|
+
}
|
|
108513
|
+
dispatch("notification", msg);
|
|
108514
|
+
return;
|
|
108515
|
+
}
|
|
108516
|
+
if (msg.id == null || !pending.has(msg.id)) return;
|
|
108517
|
+
const entry = pending.get(msg.id);
|
|
108518
|
+
pending.delete(msg.id);
|
|
108519
|
+
if (msg.error) entry.reject(new CodexRpcError(entry.method, msg.error));
|
|
108520
|
+
else entry.resolve(msg.result);
|
|
108521
|
+
};
|
|
108522
|
+
const onText = (payload)=>{
|
|
108523
|
+
let text;
|
|
108524
|
+
try {
|
|
108525
|
+
text = textDecoder.decode(payload);
|
|
108526
|
+
} catch {
|
|
108527
|
+
failAll(new Error("Codex app-server sent a non-UTF-8 text message"));
|
|
108528
|
+
return;
|
|
108529
|
+
}
|
|
108530
|
+
let msg;
|
|
108531
|
+
try {
|
|
108532
|
+
msg = JSON.parse(text);
|
|
108533
|
+
} catch (err) {
|
|
108534
|
+
failAll(new Error("Codex app-server sent an unreadable message: " + err.message));
|
|
108535
|
+
return;
|
|
108536
|
+
}
|
|
108537
|
+
if (!msg || typeof msg !== "object" || Array.isArray(msg)) {
|
|
108538
|
+
failAll(new Error("Codex app-server sent a malformed message"));
|
|
108539
|
+
return;
|
|
108540
|
+
}
|
|
108541
|
+
try {
|
|
108542
|
+
onMessage(msg);
|
|
108543
|
+
} catch (err) {
|
|
108544
|
+
failAll(err);
|
|
108545
|
+
}
|
|
108546
|
+
};
|
|
108547
|
+
socket.on("drain", ()=>{
|
|
108548
|
+
clearTimeout(writeTimer);
|
|
108549
|
+
writeTimer = undefined;
|
|
108550
|
+
});
|
|
108551
|
+
socket.once("error", (err)=>failAll(new Error("Could not connect to Codex app-server at " + path + ": " + err.message)));
|
|
108552
|
+
socket.once("close", ()=>failAll(new Error("Codex app-server closed the connection")));
|
|
108553
|
+
socket.once("connect", ()=>socket.write(upgradeRequest(key)));
|
|
108554
|
+
socket.on("data", (chunk)=>{
|
|
108555
|
+
if (closed) return;
|
|
108556
|
+
buf = Buffer.concat([
|
|
108557
|
+
buf,
|
|
108558
|
+
chunk
|
|
108559
|
+
]);
|
|
108560
|
+
if (!upgraded) {
|
|
108561
|
+
const end = buf.indexOf("\r\n\r\n");
|
|
108562
|
+
if (end === -1) {
|
|
108563
|
+
if (buf.length > WS_MAX_HEADER_BYTES) failAll(new Error("Codex app-server handshake headers exceed " + WS_MAX_HEADER_BYTES + " bytes"));
|
|
108564
|
+
return;
|
|
108565
|
+
}
|
|
108566
|
+
// Terminated headers hit the cap too; size is checked before any decoding.
|
|
108567
|
+
if (end > WS_MAX_HEADER_BYTES) return failAll(new Error("Codex app-server handshake headers exceed " + WS_MAX_HEADER_BYTES + " bytes"));
|
|
108568
|
+
const head = buf.subarray(0, end).toString();
|
|
108569
|
+
buf = buf.subarray(end + 4);
|
|
108570
|
+
if (!validateUpgradeHead(head, key)) return failAll(new Error("Codex app-server refused the WebSocket upgrade: " + head.split("\r\n")[0]));
|
|
108571
|
+
upgraded = true;
|
|
108572
|
+
clearTimeout(handshakeTimer);
|
|
108573
|
+
resolve(client);
|
|
108574
|
+
}
|
|
108575
|
+
while(!closed){
|
|
108576
|
+
const frame = decodeFrame(buf);
|
|
108577
|
+
if (!frame) {
|
|
108578
|
+
const claimed = peekFrameLength(buf);
|
|
108579
|
+
if (claimed != null && claimed > WS_MAX_MESSAGE_BYTES) {
|
|
108580
|
+
failAll(new Error("Codex app-server frame exceeds " + WS_MAX_MESSAGE_BYTES + " bytes"));
|
|
108581
|
+
} else if (buf.length > WS_MAX_BUFFER_BYTES) {
|
|
108582
|
+
failAll(new Error("Codex app-server buffer exceeds " + WS_MAX_BUFFER_BYTES + " bytes"));
|
|
108583
|
+
}
|
|
108584
|
+
return;
|
|
108585
|
+
}
|
|
108586
|
+
buf = frame.rest;
|
|
108587
|
+
if (frame.payload.length > WS_MAX_MESSAGE_BYTES) return failAll(new Error("Codex app-server frame exceeds " + WS_MAX_MESSAGE_BYTES + " bytes"));
|
|
108588
|
+
if (frame.masked) return failProtocol("server frames must not be masked");
|
|
108589
|
+
if (frame.opcode >= 0x8) {
|
|
108590
|
+
if (!frame.fin || frame.payload.length > 125) return failProtocol("bad control frame");
|
|
108591
|
+
if (frame.opcode === 0x9) {
|
|
108592
|
+
try {
|
|
108593
|
+
write(0xa, frame.payload);
|
|
108594
|
+
} catch {
|
|
108595
|
+
return;
|
|
108596
|
+
}
|
|
108597
|
+
} else if (frame.opcode === 0x8) {
|
|
108598
|
+
try {
|
|
108599
|
+
write(0x8, frame.payload);
|
|
108600
|
+
} catch {
|
|
108601
|
+
return;
|
|
108602
|
+
}
|
|
108603
|
+
failAll(new Error("Codex app-server closed the connection"));
|
|
108604
|
+
}
|
|
108605
|
+
continue; // pong and other control frames carry nothing for us
|
|
108606
|
+
}
|
|
108607
|
+
if (frame.opcode === 0x0) {
|
|
108608
|
+
if (fragOpcode == null) return failProtocol("continuation with nothing to continue");
|
|
108609
|
+
fragParts.push(frame.payload);
|
|
108610
|
+
fragBytes += frame.payload.length;
|
|
108611
|
+
if (fragBytes > WS_MAX_MESSAGE_BYTES) return failAll(new Error("Codex app-server message exceeds " + WS_MAX_MESSAGE_BYTES + " bytes"));
|
|
108612
|
+
if (!frame.fin) continue;
|
|
108613
|
+
const whole = Buffer.concat(fragParts, fragBytes);
|
|
108614
|
+
const opcode = fragOpcode;
|
|
108615
|
+
fragOpcode = null;
|
|
108616
|
+
fragParts = [];
|
|
108617
|
+
fragBytes = 0;
|
|
108618
|
+
// ponytail: binary frames are unused by the app-server; only text is delivered.
|
|
108619
|
+
if (opcode === 0x1) onText(whole);
|
|
108620
|
+
continue;
|
|
108621
|
+
}
|
|
108622
|
+
if (frame.opcode === 0x1 || frame.opcode === 0x2) {
|
|
108623
|
+
if (fragOpcode != null) return failProtocol("new message before finishing fragments");
|
|
108624
|
+
if (!frame.fin) {
|
|
108625
|
+
fragOpcode = frame.opcode;
|
|
108626
|
+
fragParts = [
|
|
108627
|
+
frame.payload
|
|
108628
|
+
];
|
|
108629
|
+
fragBytes = frame.payload.length;
|
|
108630
|
+
continue;
|
|
108631
|
+
}
|
|
108632
|
+
// ponytail: binary frames are unused by the app-server; only text is delivered.
|
|
108633
|
+
if (frame.opcode === 0x1) onText(frame.payload);
|
|
108634
|
+
continue;
|
|
108635
|
+
}
|
|
108636
|
+
return failProtocol("unknown opcode " + frame.opcode);
|
|
108637
|
+
}
|
|
108638
|
+
});
|
|
108639
|
+
});
|
|
108640
|
+
}
|
|
108641
|
+
function appServerVersion(initResult) {
|
|
108642
|
+
const ua = initResult && typeof initResult.userAgent === "string" ? initResult.userAgent : "";
|
|
108643
|
+
const m = /^[^/\s]+\/(\S+)/.exec(ua);
|
|
108644
|
+
return m ? m[1] : null;
|
|
108645
|
+
}
|
|
108646
|
+
/** Throws CodexRouteError when the operator's socket cannot be used; the path comes only from CODEX_HOME. */ function assertRoute(path) {
|
|
108647
|
+
if (process.platform === "win32") throw new CodexRouteError(windowsUnsupportedMessage(), "windows-unsupported");
|
|
108648
|
+
const state = socketState(path);
|
|
108649
|
+
if (state === "socket") return;
|
|
108650
|
+
if (state === "permission-denied") {
|
|
108651
|
+
throw new CodexRouteError("Codex app-server control socket at " + path + " exists but this user may not access it. " + "gbot runs as the user who owns CODEX_HOME; check the socket's owner and mode.", "permission-denied");
|
|
108652
|
+
}
|
|
108653
|
+
if (state === "not-a-socket") {
|
|
108654
|
+
throw new CodexRouteError(path + " exists but is not a Unix socket; remove the stale file and restart the daemon.", "not-a-socket");
|
|
108655
|
+
}
|
|
108656
|
+
throw new CodexRouteError(unreachableMessage(path), "socket-absent");
|
|
108657
|
+
}
|
|
108658
|
+
async function openCodexSession(env = process.env, { experimental = false, ...options } = {}) {
|
|
108659
|
+
const path = codexSocketPath(env);
|
|
108660
|
+
assertRoute(path);
|
|
108661
|
+
let client;
|
|
108662
|
+
try {
|
|
108663
|
+
client = await connectCodexAppServer(path, options);
|
|
108664
|
+
} catch (err) {
|
|
108665
|
+
throw connectError(err, path);
|
|
108666
|
+
}
|
|
108667
|
+
let init;
|
|
108668
|
+
try {
|
|
108669
|
+
init = await client.request("initialize", {
|
|
108670
|
+
clientInfo: {
|
|
108671
|
+
name: "gbot",
|
|
108672
|
+
version: _package_json__rspack_import_6/* .version */.rE
|
|
108673
|
+
},
|
|
108674
|
+
...experimental ? {
|
|
108675
|
+
capabilities: {
|
|
108676
|
+
experimentalApi: true
|
|
108677
|
+
}
|
|
108678
|
+
} : {}
|
|
108679
|
+
});
|
|
108680
|
+
} catch (err) {
|
|
108681
|
+
client.close();
|
|
108682
|
+
throw handshakeError(err);
|
|
108683
|
+
}
|
|
108684
|
+
if (!isObject(init)) {
|
|
108685
|
+
client.close();
|
|
108686
|
+
throw new CodexProtocolError("initialize", "result is not an object");
|
|
108687
|
+
}
|
|
108688
|
+
try {
|
|
108689
|
+
client.notify("initialized");
|
|
108690
|
+
} catch (err) {
|
|
108691
|
+
client.close();
|
|
108692
|
+
throw handshakeError(err);
|
|
108693
|
+
}
|
|
108694
|
+
return {
|
|
108695
|
+
client,
|
|
108696
|
+
path,
|
|
108697
|
+
init
|
|
108698
|
+
};
|
|
108699
|
+
}
|
|
108700
|
+
const openSession = openCodexSession;
|
|
108701
|
+
const CODEX_VERSION_PROBE_TIMEOUT_MS = 3000;
|
|
108702
|
+
/** Bounded `codex --version` probe: `{ version, probe }` where probe is ok | missing | timeout | error. */ function probeLocalCodexVersion(timeoutMs = CODEX_VERSION_PROBE_TIMEOUT_MS) {
|
|
108703
|
+
const out = spawnSync("codex", [
|
|
108704
|
+
"--version"
|
|
108705
|
+
], {
|
|
108706
|
+
encoding: "utf8",
|
|
108707
|
+
timeout: timeoutMs
|
|
108708
|
+
});
|
|
108709
|
+
if (out.error) {
|
|
108710
|
+
if (out.error.code === "ENOENT") return {
|
|
108711
|
+
version: null,
|
|
108712
|
+
probe: "missing"
|
|
108713
|
+
};
|
|
108714
|
+
if (out.error.code === "ETIMEDOUT") return {
|
|
108715
|
+
version: null,
|
|
108716
|
+
probe: "timeout"
|
|
108717
|
+
};
|
|
108718
|
+
return {
|
|
108719
|
+
version: null,
|
|
108720
|
+
probe: "error"
|
|
108721
|
+
};
|
|
108722
|
+
}
|
|
108723
|
+
const m = out.status === 0 ? /(\d+\.\d+\.\d+\S*)/.exec(out.stdout) : null;
|
|
108724
|
+
return m ? {
|
|
108725
|
+
version: m[1],
|
|
108726
|
+
probe: "ok"
|
|
108727
|
+
} : {
|
|
108728
|
+
version: null,
|
|
108729
|
+
probe: "error"
|
|
108730
|
+
};
|
|
108731
|
+
}
|
|
108732
|
+
/** Bounded `ps` snapshot for Desktop detection: process names only, never pipes or sockets. */ const DESKTOP_PROCESS_LIST_TIMEOUT_MS = 3000;
|
|
108733
|
+
function listDesktopProcesses(timeoutMs = DESKTOP_PROCESS_LIST_TIMEOUT_MS) {
|
|
108734
|
+
if (process.platform === "win32") return "";
|
|
108735
|
+
try {
|
|
108736
|
+
const out = spawnSync("ps", [
|
|
108737
|
+
"-eo",
|
|
108738
|
+
"args"
|
|
108739
|
+
], {
|
|
108740
|
+
encoding: "utf8",
|
|
108741
|
+
timeout: timeoutMs
|
|
108742
|
+
});
|
|
108743
|
+
if (out.error || out.status !== 0 || typeof out.stdout !== "string") return "";
|
|
108744
|
+
return out.stdout;
|
|
108745
|
+
} catch {
|
|
108746
|
+
return "";
|
|
108747
|
+
}
|
|
108748
|
+
}
|
|
108749
|
+
/**
|
|
108750
|
+
* Pure Desktop private-stdio detector. Returns `"private-stdio"` when the process list
|
|
108751
|
+
* shows Desktop's bundled `.../ChatGPT.app/.../Resources/codex` running `app-server`
|
|
108752
|
+
* (the `codex_app` override corroborates, the Resources path alone suffices); `"unknown"`
|
|
108753
|
+
* otherwise. Never `"detached"`: absence of a match means "not observed", not "not running".
|
|
108754
|
+
* Windows stays `"unknown"` (unsupported route, unchanged).
|
|
108755
|
+
*
|
|
108756
|
+
* @param {{ platform?: string, listProcesses?: string | string[] | null }} [opts]
|
|
108757
|
+
*/ function detectDesktopPrivateAppServer({ platform = process.platform, listProcesses = "" } = {}) {
|
|
108758
|
+
if (platform === "win32") return "unknown";
|
|
108759
|
+
const lines = Array.isArray(listProcesses) ? listProcesses : String(listProcesses ?? "").split(/\r?\n/);
|
|
108760
|
+
for (const line of lines){
|
|
108761
|
+
if (!/app-server/.test(line)) continue;
|
|
108762
|
+
// Desktop's bundled binary, Mac or Windows-style separators with optional .exe.
|
|
108763
|
+
if (/ChatGPT\.app[\\/].*Resources[\\/]codex(\.exe)?(["'\s]|$)/.test(line)) return "private-stdio";
|
|
108764
|
+
// Same app-server line owned by ChatGPT.app carrying the app-tools override.
|
|
108765
|
+
if (/ChatGPT\.app/.test(line) && /(codex_app|mcp_servers\.codex_app|codex-app-tools)/.test(line)) return "private-stdio";
|
|
108766
|
+
}
|
|
108767
|
+
return "unknown";
|
|
108768
|
+
}
|
|
108769
|
+
/**
|
|
108770
|
+
* Status contract: `reachable` is endpoint reachability only. `schema.compatibility` is
|
|
108771
|
+
* `exact` when the daemon reports the pinned version, otherwise `unverified` (methods
|
|
108772
|
+
* usually survive upgrades) or `unknown`. `desktopShimConfigured` records an installed
|
|
108773
|
+
* wrapper selected by Desktop-facing CODEX_CLI_PATH (the GUI domain on Darwin).
|
|
108774
|
+
* Configuration does not prove a running Desktop inherited it or connected.
|
|
108775
|
+
* `desktopAttached` is `"private-stdio"` when a Desktop-bundled app-server process
|
|
108776
|
+
* is visible, otherwise `"unknown"`. Managed attachment is not observable here.
|
|
108777
|
+
*
|
|
108778
|
+
* @param {NodeJS.ProcessEnv} [env]
|
|
108779
|
+
* @param {{ listProcesses?: string | string[], shim?: { installed?: boolean, wrapperPointsAtShim?: boolean } | null }} [opts]
|
|
108780
|
+
* injected process list and shim state for tests; defaults to a live `ps` snapshot and
|
|
108781
|
+
* `desktopShimStatus`. Never reads pipes or connects to Desktop.
|
|
108782
|
+
*/ async function codexStatus(env = process.env, { listProcesses, shim } = {}) {
|
|
108783
|
+
const path = codexSocketPath(env);
|
|
108784
|
+
const cli = probeLocalCodexVersion();
|
|
108785
|
+
let desktopShimConfigured = Boolean(shim && shim.installed && shim.wrapperPointsAtShim);
|
|
108786
|
+
if (shim === undefined) {
|
|
108787
|
+
try {
|
|
108788
|
+
const live = desktopShimStatus({
|
|
108789
|
+
env
|
|
108790
|
+
});
|
|
108791
|
+
desktopShimConfigured = Boolean(live.installed && live.wrapperPointsAtShim);
|
|
108792
|
+
} catch {
|
|
108793
|
+
desktopShimConfigured = false;
|
|
108794
|
+
}
|
|
108795
|
+
}
|
|
108796
|
+
const desktopAttached = detectDesktopPrivateAppServer({
|
|
108797
|
+
platform: process.platform,
|
|
108798
|
+
listProcesses: listProcesses ?? listDesktopProcesses()
|
|
108799
|
+
});
|
|
108800
|
+
const base = {
|
|
108801
|
+
socketPath: path,
|
|
108802
|
+
socketState: socketState(path),
|
|
108803
|
+
pinnedVersion: PINNED_CODEX_VERSION,
|
|
108804
|
+
cliVersion: cli.version,
|
|
108805
|
+
cliVersionProbe: cli.probe,
|
|
108806
|
+
desktopAttached,
|
|
108807
|
+
desktopShimConfigured
|
|
108808
|
+
};
|
|
108809
|
+
let session;
|
|
108810
|
+
try {
|
|
108811
|
+
session = await openSession(env);
|
|
108812
|
+
} catch (err) {
|
|
108813
|
+
if (err instanceof CodexRouteError) {
|
|
108814
|
+
// Name the private-stdio case explicitly: Desktop is up but unreachable, so the
|
|
108815
|
+
// operator needs a managed standalone daemon, not a Desktop reconnect.
|
|
108816
|
+
const message = err.mode === "socket-absent" ? unreachableMessage(path, desktopAttached) : err.message;
|
|
108817
|
+
return withStatusExitCode({
|
|
108818
|
+
...base,
|
|
108819
|
+
reachable: false,
|
|
108820
|
+
mode: err.mode,
|
|
108821
|
+
message
|
|
108822
|
+
});
|
|
108823
|
+
}
|
|
108824
|
+
// The endpoint answered; what it said does not match the pinned schema.
|
|
108825
|
+
if (err instanceof CodexProtocolError) return withStatusExitCode({
|
|
108826
|
+
...base,
|
|
108827
|
+
reachable: true,
|
|
108828
|
+
mode: err.mode,
|
|
108829
|
+
message: err.message
|
|
108830
|
+
});
|
|
108831
|
+
throw err;
|
|
108832
|
+
}
|
|
108833
|
+
session.client.close();
|
|
108834
|
+
const daemonVersion = appServerVersion(session.init);
|
|
108835
|
+
return withStatusExitCode({
|
|
108836
|
+
...base,
|
|
108837
|
+
reachable: true,
|
|
108838
|
+
mode: "daemon",
|
|
108839
|
+
daemonVersion,
|
|
108840
|
+
codexHome: typeof session.init.codexHome === "string" ? session.init.codexHome : null,
|
|
108841
|
+
schema: {
|
|
108842
|
+
pinned: PINNED_CODEX_VERSION,
|
|
108843
|
+
daemon: daemonVersion,
|
|
108844
|
+
compatibility: daemonVersion == null ? "unknown" : daemonVersion === PINNED_CODEX_VERSION ? "exact" : "unverified"
|
|
108845
|
+
},
|
|
108846
|
+
versionMismatch: Boolean(base.cliVersion && daemonVersion && base.cliVersion !== daemonVersion)
|
|
108847
|
+
});
|
|
108848
|
+
}
|
|
108849
|
+
const THREAD_STATUSES = new Set([
|
|
108850
|
+
"notLoaded",
|
|
108851
|
+
"idle",
|
|
108852
|
+
"active",
|
|
108853
|
+
"systemError"
|
|
108854
|
+
]);
|
|
108855
|
+
function lineField(value) {
|
|
108856
|
+
return value == null ? null : singleLine(value);
|
|
108857
|
+
}
|
|
108858
|
+
/** Server text fields are sanitized; structured values (Codex's `source: { custom }`) pass through untouched. */ function sourceField(value) {
|
|
108859
|
+
if (value == null) return null;
|
|
108860
|
+
return typeof value === "string" ? singleLine(value) : value;
|
|
108861
|
+
}
|
|
108862
|
+
function summarizeThread(t) {
|
|
108863
|
+
if (!isObject(t) || typeof t.id !== "string" || !t.id) throw new CodexProtocolError("thread/list", "entry without a string `id`");
|
|
108864
|
+
const type = isObject(t.status) && typeof t.status.type === "string" ? t.status.type : "unknown";
|
|
108865
|
+
return {
|
|
108866
|
+
id: singleLine(t.id),
|
|
108867
|
+
status: THREAD_STATUSES.has(type) ? type : "unknown",
|
|
108868
|
+
activeFlags: isObject(t.status) && Array.isArray(t.status.activeFlags) ? t.status.activeFlags.map((f)=>singleLine(f)) : [],
|
|
108869
|
+
name: lineField(t.name),
|
|
108870
|
+
preview: typeof t.preview === "string" ? stripTerminalControls(t.preview) : "",
|
|
108871
|
+
cwd: lineField(t.cwd),
|
|
108872
|
+
source: sourceField(t.source),
|
|
108873
|
+
updatedAt: typeof t.updatedAt === "number" ? t.updatedAt : null
|
|
108874
|
+
};
|
|
108875
|
+
}
|
|
108876
|
+
const THREAD_LIST_MAX_LIMIT = 200;
|
|
108877
|
+
/**
|
|
108878
|
+
* @param {{ limit?: number, cursor?: string, env?: NodeJS.ProcessEnv }} [opts]
|
|
108879
|
+
*/ async function listCodexThreads({ limit = 20, cursor, env = process.env } = {}) {
|
|
108880
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > THREAD_LIST_MAX_LIMIT) {
|
|
108881
|
+
throw new RangeError("--limit must be an integer 1-" + THREAD_LIST_MAX_LIMIT);
|
|
108882
|
+
}
|
|
108883
|
+
if (cursor !== undefined && (typeof cursor !== "string" || !cursor)) throw new RangeError("--cursor must be a non-empty string");
|
|
108884
|
+
const { client } = await openSession(env);
|
|
108885
|
+
try {
|
|
108886
|
+
// The default listing rescans every rollout file to repair metadata (26 s on a busy machine);
|
|
108887
|
+
// the state DB already holds what we print.
|
|
108888
|
+
const params = {
|
|
108889
|
+
limit,
|
|
108890
|
+
useStateDbOnly: true,
|
|
108891
|
+
...cursor !== undefined ? {
|
|
108892
|
+
cursor
|
|
108893
|
+
} : {}
|
|
108894
|
+
};
|
|
108895
|
+
let out;
|
|
108896
|
+
try {
|
|
108897
|
+
out = await client.request("thread/list", params);
|
|
108898
|
+
} catch (err) {
|
|
108899
|
+
throw transportError(err);
|
|
108900
|
+
}
|
|
108901
|
+
if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array");
|
|
108902
|
+
if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string");
|
|
108903
|
+
const threads = out.data.map(summarizeThread);
|
|
108904
|
+
return {
|
|
108905
|
+
threads,
|
|
108906
|
+
nextCursor: out.nextCursor ?? null,
|
|
108907
|
+
limit
|
|
108908
|
+
};
|
|
108909
|
+
} finally{
|
|
108910
|
+
client.close();
|
|
108911
|
+
}
|
|
108912
|
+
}
|
|
108913
|
+
function explainSendError(err, threadId) {
|
|
108914
|
+
if (!(err instanceof CodexRpcError)) return err;
|
|
108915
|
+
const msg = String(err.rpc && err.rpc.message || "");
|
|
108916
|
+
if (/no rollout found|thread not found/i.test(msg)) {
|
|
108917
|
+
return new Error("Unknown Codex thread " + threadId + ". Run `gbot codex list-threads` to see reachable threads.");
|
|
108918
|
+
}
|
|
108919
|
+
if (/active writer/i.test(msg)) {
|
|
108920
|
+
return new Error("Codex thread " + threadId + " is open in another client (VS Code, TUI, or Desktop), which owns its turns. Close it there first.");
|
|
108921
|
+
}
|
|
108922
|
+
return err;
|
|
108923
|
+
}
|
|
108924
|
+
const DEFAULT_MAX_HOPS = 4;
|
|
108925
|
+
const ID_PATTERN = /^[A-Za-z0-9_.:-]{1,128}$/;
|
|
108926
|
+
/**
|
|
108927
|
+
* Delivery envelope: `messageId` names this send, `correlationId` names the conversation it
|
|
108928
|
+
* belongs to, `replyTo` names the message it answers, `hop` counts agent-to-agent forwards.
|
|
108929
|
+
* `maxHops` (GROK_BOT_MAX_HOPS) bounds relays: a reply must carry hop = incoming hop + 1, and a
|
|
108930
|
+
* send at or past the bound is refused, so two agents cannot ack each other forever.
|
|
108931
|
+
* The textual header is caller-authored provenance for the reader, not authentication.
|
|
108932
|
+
* @param {{ correlationId?: string, replyTo?: string, hop?: number, envelope?: boolean, env?: NodeJS.ProcessEnv }} [opts]
|
|
108933
|
+
*/ function buildEnvelope({ correlationId, replyTo, hop, envelope = false, env = process.env } = {}) {
|
|
108934
|
+
const maxHops = Number.parseInt(env.GROK_BOT_MAX_HOPS ?? "", 10);
|
|
108935
|
+
const bound = Number.isInteger(maxHops) && maxHops >= 0 ? maxHops : DEFAULT_MAX_HOPS;
|
|
108936
|
+
for (const [name, value] of [
|
|
108937
|
+
[
|
|
108938
|
+
"--correlation-id",
|
|
108939
|
+
correlationId
|
|
108940
|
+
],
|
|
108941
|
+
[
|
|
108942
|
+
"--reply-to",
|
|
108943
|
+
replyTo
|
|
108944
|
+
]
|
|
108945
|
+
]){
|
|
108946
|
+
if (value !== undefined && !ID_PATTERN.test(value)) throw new RangeError(name + " must be 1-128 characters of [A-Za-z0-9_.:-]");
|
|
108947
|
+
}
|
|
108948
|
+
const hopCount = hop === undefined ? 0 : hop;
|
|
108949
|
+
if (!Number.isInteger(hopCount) || hopCount < 0) throw new RangeError("--hop must be a non-negative integer");
|
|
108950
|
+
if (replyTo !== undefined && correlationId === undefined) {
|
|
108951
|
+
throw new RangeError("--reply-to needs the original --correlation-id so the reply stays in its conversation");
|
|
108952
|
+
}
|
|
108953
|
+
const messageId = (0,node_crypto__rspack_import_0.randomUUID)();
|
|
108954
|
+
const out = {
|
|
108955
|
+
messageId,
|
|
108956
|
+
correlationId: correlationId ?? messageId,
|
|
108957
|
+
hop: hopCount,
|
|
108958
|
+
maxHops: bound,
|
|
108959
|
+
header: envelope || replyTo !== undefined || hop !== undefined || correlationId !== undefined
|
|
108960
|
+
};
|
|
108961
|
+
if (replyTo !== undefined) out.replyTo = replyTo;
|
|
108962
|
+
if (hopCount >= bound) {
|
|
108963
|
+
throw new CodexSendError("Refusing to send: hop " + hopCount + " reaches the relay bound " + bound + " (GROK_BOT_MAX_HOPS). " + "This message is an agent-to-agent relay that has already been forwarded too many times.", {
|
|
108964
|
+
delivery: "rejected",
|
|
108965
|
+
reason: "hop-limit",
|
|
108966
|
+
...out
|
|
108967
|
+
});
|
|
108968
|
+
}
|
|
108969
|
+
return out;
|
|
108970
|
+
}
|
|
108971
|
+
/** One-line header a receiving agent can read to reply with `--reply-to` and `--hop N+1`. */ const identityToken = (value)=>String(value ?? "").replace(/[^A-Za-z0-9_.:-]/g, "").slice(0, 64) || "unknown";
|
|
108972
|
+
function envelopeHeader(envelope, env = process.env) {
|
|
108973
|
+
const from = identityToken(env.USER || env.USERNAME) + "@" + hostnameSafe();
|
|
108974
|
+
const parts = [
|
|
108975
|
+
"msg=" + envelope.messageId,
|
|
108976
|
+
"corr=" + envelope.correlationId
|
|
108977
|
+
];
|
|
108978
|
+
if (envelope.replyTo) parts.push("reply-to=" + envelope.replyTo);
|
|
108979
|
+
parts.push("hop=" + envelope.hop, "from=" + from);
|
|
108980
|
+
return "[gbot " + parts.join(" ") + "]";
|
|
108981
|
+
}
|
|
108982
|
+
function hostnameSafe() {
|
|
108983
|
+
try {
|
|
108984
|
+
return identityToken((0,node_os__rspack_import_3.hostname)());
|
|
108985
|
+
} catch {
|
|
108986
|
+
return "unknown";
|
|
108987
|
+
}
|
|
108988
|
+
}
|
|
108989
|
+
function withEnvelopeHeader(text, envelope, env = process.env) {
|
|
108990
|
+
return envelope.header ? envelopeHeader(envelope, env) + "\n" + text : text;
|
|
108991
|
+
}
|
|
108992
|
+
/** Operator-controlled destinations: GROK_BOT_CODEX_THREADS="id,id" restricts `codex send`. */ function assertThreadAllowed(threadId, env = process.env) {
|
|
108993
|
+
const raw = env.GROK_BOT_CODEX_THREADS;
|
|
108994
|
+
if (raw == null || raw.trim() === "") return;
|
|
108995
|
+
const allowed = raw.split(",").map((s)=>s.trim()).filter(Boolean);
|
|
108996
|
+
if (!allowed.includes(threadId)) {
|
|
108997
|
+
throw new CodexSendError("Codex thread " + threadId + " is not in GROK_BOT_CODEX_THREADS; the operator allows only: " + allowed.join(", "), {
|
|
108998
|
+
delivery: "rejected",
|
|
108999
|
+
reason: "route-not-allowed",
|
|
109000
|
+
threadId
|
|
109001
|
+
});
|
|
109002
|
+
}
|
|
109003
|
+
}
|
|
109004
|
+
/**
|
|
109005
|
+
* Busy destinations. In app-server 0.154.0 `turn/start` on a thread with an active turn steers
|
|
109006
|
+
* that turn instead of queueing (TurnStartParams.turnTrigger: "Ignored when this request steers
|
|
109007
|
+
* an already-active turn"). gbot never steers or interrupts human work: an `active` thread is
|
|
109008
|
+
* refused with a `busy` receipt, or, with `whenBusy: "queue"`, handed to the daemon's own queue
|
|
109009
|
+
* through the experimental `thread/queue/add`. See docs/codex-busy-threads.md.
|
|
109010
|
+
*/ function threadState(resumed, threadId) {
|
|
109011
|
+
const status = resumed.thread.status;
|
|
109012
|
+
const type = isObject(status) && typeof status.type === "string" ? status.type : "unknown";
|
|
109013
|
+
if (type === "idle" || type === "notLoaded") return {
|
|
109014
|
+
type,
|
|
109015
|
+
busy: false
|
|
109016
|
+
};
|
|
109017
|
+
if (type === "active") {
|
|
109018
|
+
const flags = Array.isArray(status.activeFlags) ? status.activeFlags.map((f)=>singleLine(f)) : [];
|
|
109019
|
+
return {
|
|
109020
|
+
type,
|
|
109021
|
+
busy: true,
|
|
109022
|
+
flags
|
|
109023
|
+
};
|
|
109024
|
+
}
|
|
109025
|
+
if (type === "systemError") {
|
|
109026
|
+
throw new CodexSendError("Codex thread " + threadId + " is in systemError state; open it in a Codex client first.", {
|
|
109027
|
+
delivery: "rejected",
|
|
109028
|
+
reason: "thread-error",
|
|
109029
|
+
threadId
|
|
109030
|
+
});
|
|
109031
|
+
}
|
|
109032
|
+
throw new CodexSendError("Codex thread " + threadId + " reports status " + JSON.stringify(type) + ", which this gbot (pinned to app-server " + PINNED_CODEX_VERSION + ") does not know; not sending.", {
|
|
109033
|
+
delivery: "rejected",
|
|
109034
|
+
reason: "unknown-status",
|
|
109035
|
+
threadId
|
|
109036
|
+
});
|
|
109037
|
+
}
|
|
109038
|
+
function experimentalEnabled(env = process.env) {
|
|
109039
|
+
return /^(1|true|on)$/i.test(env.GROK_BOT_CODEX_EXPERIMENTAL || "");
|
|
109040
|
+
}
|
|
109041
|
+
function requireExperimental(env, what) {
|
|
109042
|
+
if (experimentalEnabled(env)) return;
|
|
109043
|
+
throw new CodexSendError(what + " uses Codex's experimental app-server API (thread/queue/*), which is off by default. " + "Set GROK_BOT_CODEX_EXPERIMENTAL=1 to opt in; method names are pinned to Codex " + PINNED_CODEX_VERSION + ".", {
|
|
109044
|
+
delivery: "rejected",
|
|
109045
|
+
reason: "experimental-disabled"
|
|
109046
|
+
});
|
|
109047
|
+
}
|
|
109048
|
+
function unsupportedOrRpc(err, method, threadId, envelope, turnId) {
|
|
109049
|
+
const guarded = method === "turn/steer";
|
|
109050
|
+
if (err instanceof CodexRpcError && err.rpc && err.rpc.code === -32601) {
|
|
109051
|
+
return new CodexSendError("Codex app-server does not offer " + method + " (daemon predates it, or experimentalApi was not granted). " + (guarded ? "Upgrade Codex before retrying guarded steering." : "Upgrade Codex or send without --when-busy queue."), {
|
|
109052
|
+
delivery: "rejected",
|
|
109053
|
+
reason: "unsupported",
|
|
109054
|
+
threadId,
|
|
109055
|
+
turnId,
|
|
109056
|
+
...envelope
|
|
109057
|
+
});
|
|
109058
|
+
}
|
|
109059
|
+
if (err instanceof CodexRpcError) return new CodexSendError(err.message, {
|
|
109060
|
+
delivery: "rejected",
|
|
109061
|
+
reason: "rejected",
|
|
109062
|
+
threadId,
|
|
109063
|
+
turnId,
|
|
109064
|
+
...envelope
|
|
109065
|
+
});
|
|
109066
|
+
return new CodexSendError("Lost the Codex " + method + " response for thread " + threadId + ": " + (err && err.message || err) + (guarded ? ". Delivery is unknown; check thread " + threadId + " turn " + turnId + " before resending." : ". Delivery is unknown; list the queue before resending."), {
|
|
109067
|
+
delivery: err && err.delivery || "unknown",
|
|
109068
|
+
reason: "transport",
|
|
109069
|
+
threadId,
|
|
109070
|
+
turnId,
|
|
109071
|
+
...envelope
|
|
109072
|
+
});
|
|
109073
|
+
}
|
|
109074
|
+
/** Read the daemon's queue for one thread (experimental `thread/queue/list`). */ async function listCodexQueue(threadId, { env = process.env, limit = 50, cursor } = {}) {
|
|
109075
|
+
requireExperimental(env, "gbot codex queue");
|
|
109076
|
+
const { client } = await openSession(env, {
|
|
109077
|
+
experimental: true
|
|
109078
|
+
});
|
|
109079
|
+
try {
|
|
109080
|
+
let out;
|
|
109081
|
+
try {
|
|
109082
|
+
out = await client.request("thread/queue/list", {
|
|
109083
|
+
threadId,
|
|
109084
|
+
limit,
|
|
109085
|
+
...cursor !== undefined ? {
|
|
109086
|
+
cursor
|
|
109087
|
+
} : {}
|
|
109088
|
+
});
|
|
109089
|
+
} catch (err) {
|
|
109090
|
+
throw unsupportedOrRpc(err, "thread/queue/list", threadId);
|
|
109091
|
+
}
|
|
109092
|
+
if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/queue/list", "missing `data` array");
|
|
109093
|
+
return {
|
|
109094
|
+
threadId,
|
|
109095
|
+
queued: out.data.map((q)=>({
|
|
109096
|
+
id: isObject(q) && typeof q.id === "string" ? singleLine(q.id) : null,
|
|
109097
|
+
clientUserMessageId: isObject(q) && typeof q.clientUserMessageId === "string" ? singleLine(q.clientUserMessageId) : null,
|
|
109098
|
+
text: isObject(q) && Array.isArray(q.input) ? q.input.map((part)=>isObject(part) && typeof part.text === "string" ? part.text : "").filter(Boolean).join("\n") : ""
|
|
109099
|
+
})),
|
|
109100
|
+
nextCursor: typeof out.nextCursor === "string" ? out.nextCursor : null
|
|
109101
|
+
};
|
|
109102
|
+
} finally{
|
|
109103
|
+
client.close();
|
|
109104
|
+
}
|
|
109105
|
+
}
|
|
109106
|
+
/**
|
|
109107
|
+
* @param {string} threadId
|
|
109108
|
+
* @param {string} text
|
|
109109
|
+
* @param {{ env?: NodeJS.ProcessEnv, envelope?: object, whenBusy?: "reject"|"queue"|"steer", session?: object, expectedTurnId?: string, expectedCwd?: string, signal?: AbortSignal }} [opts]
|
|
109110
|
+
*/ async function sendToCodexThread(threadId, text, { env = process.env, envelope = buildEnvelope({
|
|
109111
|
+
env
|
|
109112
|
+
}), whenBusy = "reject", session, expectedTurnId, expectedCwd, signal } = {}) {
|
|
109113
|
+
try {
|
|
109114
|
+
const receipt = await sendToCodexThreadInner(threadId, text, {
|
|
109115
|
+
env,
|
|
109116
|
+
envelope,
|
|
109117
|
+
whenBusy,
|
|
109118
|
+
session,
|
|
109119
|
+
expectedTurnId,
|
|
109120
|
+
expectedCwd,
|
|
109121
|
+
signal
|
|
109122
|
+
});
|
|
109123
|
+
return (0,_codex_contract_js__rspack_import_7/* .outcomeFromReceipt */.Dz)(receipt);
|
|
109124
|
+
} catch (err) {
|
|
109125
|
+
// Every receipt names the message, including refusals that never reached the daemon.
|
|
109126
|
+
if (err && typeof err === "object") {
|
|
109127
|
+
attachEnvelope(err, envelope);
|
|
109128
|
+
if (err.threadId === undefined) err.threadId = threadId;
|
|
109129
|
+
}
|
|
109130
|
+
return (0,_codex_contract_js__rspack_import_7/* .outcomeFromError */.DG)(err);
|
|
109131
|
+
}
|
|
109132
|
+
}
|
|
109133
|
+
async function sendToCodexThreadInner(threadId, text, { env, envelope, whenBusy, session, expectedTurnId, expectedCwd, signal }) {
|
|
109134
|
+
if (![
|
|
109135
|
+
"reject",
|
|
109136
|
+
"queue",
|
|
109137
|
+
...session ? [
|
|
109138
|
+
"steer"
|
|
109139
|
+
] : []
|
|
109140
|
+
].includes(whenBusy)) throw new RangeError("--when-busy must be reject, queue, or persistent steer");
|
|
109141
|
+
if (whenBusy === "steer" && (typeof expectedTurnId !== "string" || !ID_PATTERN.test(expectedTurnId))) throw new RangeError("steer requires expectedTurnId");
|
|
109142
|
+
if (typeof threadId !== "string" || !ID_PATTERN.test(threadId)) throw new RangeError("Invalid threadId");
|
|
109143
|
+
if (typeof text !== "string" || !text.trim() || Buffer.byteLength(text) > WS_MAX_MESSAGE_BYTES) throw new RangeError("Message must contain text within 4 MiB");
|
|
109144
|
+
if (!envelope || typeof envelope.messageId !== "string" || !ID_PATTERN.test(envelope.messageId)) throw new RangeError("Invalid envelope messageId");
|
|
109145
|
+
const validated = buildEnvelope({
|
|
109146
|
+
correlationId: envelope.correlationId,
|
|
109147
|
+
replyTo: envelope.replyTo,
|
|
109148
|
+
hop: envelope.hop,
|
|
109149
|
+
env
|
|
109150
|
+
});
|
|
109151
|
+
envelope = {
|
|
109152
|
+
...validated,
|
|
109153
|
+
messageId: envelope.messageId,
|
|
109154
|
+
header: Boolean(envelope.header)
|
|
109155
|
+
};
|
|
109156
|
+
assertThreadAllowed(threadId, env);
|
|
109157
|
+
if (whenBusy === "queue") requireExperimental(env, "--when-busy queue");
|
|
109158
|
+
if (signal !== undefined && !(signal instanceof AbortSignal)) throw new TypeError("signal must be an AbortSignal");
|
|
109159
|
+
const assertNotCancelled = ()=>{
|
|
109160
|
+
if (signal?.aborted) throw new CodexSendError("Codex submission cancelled before delivery", {
|
|
109161
|
+
delivery: "rejected",
|
|
109162
|
+
reason: "cancelled",
|
|
109163
|
+
threadId,
|
|
109164
|
+
turnId: whenBusy === "steer" ? expectedTurnId : undefined,
|
|
109165
|
+
...envelope
|
|
109166
|
+
});
|
|
109167
|
+
};
|
|
109168
|
+
assertNotCancelled();
|
|
109169
|
+
const body = withEnvelopeHeader(text, envelope, env);
|
|
109170
|
+
const { client } = session ?? await openSession(env, {
|
|
109171
|
+
experimental: whenBusy === "queue",
|
|
109172
|
+
signal
|
|
109173
|
+
});
|
|
109174
|
+
try {
|
|
109175
|
+
let resumed;
|
|
109176
|
+
try {
|
|
109177
|
+
resumed = await client.request("thread/resume", {
|
|
109178
|
+
threadId,
|
|
109179
|
+
excludeTurns: true
|
|
109180
|
+
});
|
|
109181
|
+
} catch (err) {
|
|
109182
|
+
assertNotCancelled();
|
|
109183
|
+
if (err instanceof CodexSendError) throw err;
|
|
109184
|
+
throw new CodexSendError(explainSendError(err, threadId).message, {
|
|
109185
|
+
delivery: err instanceof CodexRpcError ? "rejected" : err && err.delivery || "unknown",
|
|
109186
|
+
reason: err instanceof CodexRpcError ? /no rollout found|thread not found/i.test(String(err.rpc && err.rpc.message)) ? "unknown-thread" : /active writer/i.test(String(err.rpc && err.rpc.message)) ? "external-owner" : "rejected" : "transport",
|
|
109187
|
+
threadId,
|
|
109188
|
+
...envelope
|
|
109189
|
+
});
|
|
109190
|
+
}
|
|
109191
|
+
// A shared session stays connected when this conversation is cancelled.
|
|
109192
|
+
// Recheck after the last awaited preflight, before any submission request.
|
|
109193
|
+
assertNotCancelled();
|
|
109194
|
+
if (!isObject(resumed) || !isObject(resumed.thread) || typeof resumed.thread.id !== "string") {
|
|
109195
|
+
throw new CodexProtocolError("thread/resume", "missing `thread.id`");
|
|
109196
|
+
}
|
|
109197
|
+
if (resumed.thread.id !== threadId) throw new CodexSendError("thread/resume returned a different thread ID", {
|
|
109198
|
+
delivery: "rejected",
|
|
109199
|
+
reason: "bad-response",
|
|
109200
|
+
threadId,
|
|
109201
|
+
...envelope
|
|
109202
|
+
});
|
|
109203
|
+
if (expectedCwd !== undefined && (0,node_fs__rspack_import_1.realpathSync)(resumed.cwd ?? resumed.thread.cwd) !== (0,node_fs__rspack_import_1.realpathSync)(expectedCwd)) throw new CodexSendError("Codex thread cwd does not match expectedCwd", {
|
|
109204
|
+
delivery: "rejected",
|
|
109205
|
+
reason: "cwd-mismatch",
|
|
109206
|
+
threadId,
|
|
109207
|
+
...envelope
|
|
109208
|
+
});
|
|
109209
|
+
const state = threadState(resumed, threadId);
|
|
109210
|
+
const receiptBase = {
|
|
109211
|
+
threadId: resumed.thread.id,
|
|
109212
|
+
threadStatus: state.type,
|
|
109213
|
+
model: resumed.model,
|
|
109214
|
+
cwd: resumed.cwd,
|
|
109215
|
+
approvalPolicy: resumed.approvalPolicy,
|
|
109216
|
+
messageId: envelope.messageId,
|
|
109217
|
+
correlationId: envelope.correlationId,
|
|
109218
|
+
...envelope.replyTo ? {
|
|
109219
|
+
replyTo: envelope.replyTo
|
|
109220
|
+
} : {},
|
|
109221
|
+
hop: envelope.hop,
|
|
109222
|
+
maxHops: envelope.maxHops
|
|
109223
|
+
};
|
|
109224
|
+
if (state.busy && whenBusy === "reject") {
|
|
109225
|
+
const flags = state.flags.length ? " (" + state.flags.join(", ") + ")" : "";
|
|
109226
|
+
throw new CodexSendError("Codex thread " + threadId + " has an active turn" + flags + "; sending now would steer that turn. " + "Wait for it to go idle (`gbot codex list-threads`) and resend, or pass --when-busy queue.", {
|
|
109227
|
+
delivery: "rejected",
|
|
109228
|
+
reason: "busy",
|
|
109229
|
+
threadId,
|
|
109230
|
+
...envelope
|
|
109231
|
+
});
|
|
109232
|
+
}
|
|
109233
|
+
if (whenBusy === "steer") {
|
|
109234
|
+
let steered;
|
|
109235
|
+
try {
|
|
109236
|
+
steered = await client.request("turn/steer", {
|
|
109237
|
+
threadId,
|
|
109238
|
+
expectedTurnId,
|
|
109239
|
+
clientUserMessageId: envelope.messageId,
|
|
109240
|
+
input: [
|
|
109241
|
+
{
|
|
109242
|
+
type: "text",
|
|
109243
|
+
text: body
|
|
109244
|
+
}
|
|
109245
|
+
]
|
|
109246
|
+
});
|
|
109247
|
+
} catch (err) {
|
|
109248
|
+
throw unsupportedOrRpc(err, "turn/steer", threadId, envelope, expectedTurnId);
|
|
109249
|
+
}
|
|
109250
|
+
if (typeof steered?.turnId !== "string" || steered.turnId !== expectedTurnId) {
|
|
109251
|
+
throw new CodexSendError("Malformed turn/steer acknowledgment", {
|
|
109252
|
+
delivery: "unknown",
|
|
109253
|
+
reason: "bad-response",
|
|
109254
|
+
threadId,
|
|
109255
|
+
turnId: expectedTurnId,
|
|
109256
|
+
...envelope
|
|
109257
|
+
});
|
|
109258
|
+
}
|
|
109259
|
+
return {
|
|
109260
|
+
delivery: "accepted",
|
|
109261
|
+
...receiptBase,
|
|
109262
|
+
turnId: steered.turnId
|
|
109263
|
+
};
|
|
109264
|
+
}
|
|
109265
|
+
if (state.busy) {
|
|
109266
|
+
let queued;
|
|
109267
|
+
try {
|
|
109268
|
+
queued = await client.request("thread/queue/add", {
|
|
109269
|
+
threadId,
|
|
109270
|
+
clientUserMessageId: envelope.messageId,
|
|
109271
|
+
input: [
|
|
109272
|
+
{
|
|
109273
|
+
type: "text",
|
|
109274
|
+
text: body
|
|
109275
|
+
}
|
|
109276
|
+
]
|
|
109277
|
+
});
|
|
109278
|
+
} catch (err) {
|
|
109279
|
+
throw unsupportedOrRpc(err, "thread/queue/add", threadId, envelope);
|
|
109280
|
+
}
|
|
109281
|
+
const submission = isObject(queued) && isObject(queued.queuedSubmission) && typeof queued.queuedSubmission.id === "string" ? queued.queuedSubmission : null;
|
|
109282
|
+
if (!submission) {
|
|
109283
|
+
throw new CodexSendError("Codex app-server sent a malformed thread/queue/add acknowledgment for thread " + threadId + ". Delivery is unknown; list the queue before resending.", {
|
|
109284
|
+
delivery: "unknown",
|
|
109285
|
+
reason: "bad-response",
|
|
109286
|
+
threadId,
|
|
109287
|
+
...envelope
|
|
109288
|
+
});
|
|
109289
|
+
}
|
|
109290
|
+
return {
|
|
109291
|
+
delivery: "queued",
|
|
109292
|
+
...receiptBase,
|
|
109293
|
+
queuedSubmissionId: submission.id,
|
|
109294
|
+
activeFlags: state.flags
|
|
109295
|
+
};
|
|
109296
|
+
}
|
|
109297
|
+
// ponytail: idle-at-resume then turn/start is a small race with a human starting a turn first;
|
|
109298
|
+
// the daemon exposes no compare-and-start request. Upgrade path: thread/queue/add + thread/queue/start once stable.
|
|
109299
|
+
// Scope refusals to this turn: server requests from earlier calls belong to another context.
|
|
109300
|
+
const seenRefused = client.refused.length;
|
|
109301
|
+
// Arm refusal replies only now that our own turn/start is in flight, scoped
|
|
109302
|
+
// to our own thread/turn: anything recorded earlier (resume, busy reject,
|
|
109303
|
+
// queue) — or naming another thread or Desktop turn — stays unanswered so
|
|
109304
|
+
// gbot never rejects another client's approval. Requests naming a turn
|
|
109305
|
+
// that arrives before the acknowledgment supplies our turn id wait in
|
|
109306
|
+
// client.deferred and are adopted only on a match. Requests missing
|
|
109307
|
+
// thread or turn IDs remain unanswered because ownership is unknown.
|
|
109308
|
+
if (!session) {
|
|
109309
|
+
client.expectedThreadId = threadId;
|
|
109310
|
+
client.expectedTurnId = null;
|
|
109311
|
+
client.answerServerRequests = true;
|
|
109312
|
+
}
|
|
109313
|
+
let turn;
|
|
109314
|
+
try {
|
|
109315
|
+
turn = await client.request("turn/start", {
|
|
109316
|
+
threadId,
|
|
109317
|
+
input: [
|
|
109318
|
+
{
|
|
109319
|
+
type: "text",
|
|
109320
|
+
text: body
|
|
109321
|
+
}
|
|
109322
|
+
],
|
|
109323
|
+
clientUserMessageId: envelope.messageId,
|
|
109324
|
+
turnTrigger: "gbot"
|
|
109325
|
+
});
|
|
109326
|
+
} catch (err) {
|
|
109327
|
+
if (err instanceof CodexSendError) throw err;
|
|
109328
|
+
const delivery = err instanceof CodexRpcError ? "rejected" : err && err.delivery || "unknown";
|
|
109329
|
+
const detail = err instanceof CodexRpcError ? err.message : "Lost the Codex turn/start response for thread " + threadId + ": " + (err && err.message || err) + ". Delivery is unknown; check the thread before resending.";
|
|
109330
|
+
// No blind retry: the receipt carries messageId so the caller can look for it before resending.
|
|
109331
|
+
throw new CodexSendError(detail, {
|
|
109332
|
+
delivery,
|
|
109333
|
+
reason: delivery === "rejected" ? "rejected" : "transport",
|
|
109334
|
+
threadId,
|
|
109335
|
+
...envelope
|
|
109336
|
+
});
|
|
109337
|
+
}
|
|
109338
|
+
const turnId = turn && turn.turn && typeof turn.turn.id === "string" && turn.turn.id ? turn.turn.id : null;
|
|
109339
|
+
if (!turnId) {
|
|
109340
|
+
throw new CodexSendError("Codex app-server sent a malformed turn/start acknowledgment for thread " + threadId + ". Delivery is unknown; check the thread before resending.", {
|
|
109341
|
+
delivery: "unknown",
|
|
109342
|
+
reason: "bad-response",
|
|
109343
|
+
threadId,
|
|
109344
|
+
...envelope
|
|
109345
|
+
});
|
|
109346
|
+
}
|
|
109347
|
+
if (!session) client._adoptTurn(turnId);
|
|
109348
|
+
const freshRefused = client.refused.slice(seenRefused).filter((r)=>{
|
|
109349
|
+
if (!r.answered) return false;
|
|
109350
|
+
const params = r.params && typeof r.params === "object" && !Array.isArray(r.params) ? r.params : null;
|
|
109351
|
+
if (!params) return true;
|
|
109352
|
+
const refusedThreadId = params.threadId ?? params.thread_id;
|
|
109353
|
+
const refusedTurnId = params.turnId ?? params.turn_id ?? (params.turn && params.turn.id);
|
|
109354
|
+
if (refusedThreadId != null && refusedThreadId !== threadId) return false;
|
|
109355
|
+
if (refusedTurnId != null && refusedTurnId !== turnId) return false;
|
|
109356
|
+
return true;
|
|
109357
|
+
});
|
|
109358
|
+
if (freshRefused.length) {
|
|
109359
|
+
const methods = freshRefused.map((r)=>r.method).join(", ");
|
|
109360
|
+
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.", {
|
|
109361
|
+
delivery: "accepted",
|
|
109362
|
+
reason: "approval-refused",
|
|
109363
|
+
threadId,
|
|
109364
|
+
turnId,
|
|
109365
|
+
refused: freshRefused.map((r)=>r.method),
|
|
109366
|
+
...envelope
|
|
109367
|
+
});
|
|
109368
|
+
}
|
|
109369
|
+
return {
|
|
109370
|
+
delivery: "accepted",
|
|
109371
|
+
...receiptBase,
|
|
109372
|
+
turnId,
|
|
109373
|
+
turnStatus: turn.turn.status
|
|
109374
|
+
};
|
|
109375
|
+
} finally{
|
|
109376
|
+
if (!session) client.close();
|
|
109377
|
+
}
|
|
109378
|
+
}
|
|
109379
|
+
|
|
109380
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
109381
|
+
$3: () => (assertThreadAllowed),
|
|
109382
|
+
Mr: () => (withEnvelopeHeader),
|
|
109383
|
+
X$: () => (listCodexThreads),
|
|
109384
|
+
ZS: () => (sendToCodexThread),
|
|
109385
|
+
e0: () => (experimentalEnabled),
|
|
109386
|
+
eC: () => (openCodexSession),
|
|
109387
|
+
nq: () => (buildEnvelope),
|
|
109388
|
+
ql: () => (codexSocketPath)
|
|
109389
|
+
});
|
|
109390
|
+
|
|
109391
|
+
|
|
109392
|
+
},
|
|
109393
|
+
"./src/core/codex/contract.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
109394
|
+
/* import */ var _url_policy_js__rspack_import_0 = __webpack_require__("./src/core/url-policy.js");
|
|
109395
|
+
/**
|
|
109396
|
+
* #46 Codex contract documents and exit-code derivation.
|
|
109397
|
+
* The bridge and the CLI routes flatten through these helpers so reason/delivery
|
|
109398
|
+
* spelling stays one owner. No process I/O here.
|
|
109399
|
+
*/
|
|
109400
|
+
/** @typedef {'accepted' | 'queued' | 'rejected' | 'unknown'} CodexDelivery */ /**
|
|
109401
|
+
* @typedef {{
|
|
109402
|
+
* delivery: CodexDelivery,
|
|
109403
|
+
* exitCode: 0 | 1,
|
|
109404
|
+
* error?: string,
|
|
109405
|
+
* reason?: string,
|
|
109406
|
+
* mode?: string,
|
|
109407
|
+
* threadId?: string,
|
|
109408
|
+
* turnId?: string,
|
|
109409
|
+
* turnStatus?: string,
|
|
109410
|
+
* queuedSubmissionId?: string,
|
|
109411
|
+
* refused?: string[],
|
|
109412
|
+
* messageId?: string,
|
|
109413
|
+
* correlationId?: string,
|
|
109414
|
+
* hop?: number,
|
|
109415
|
+
* replyTo?: string,
|
|
109416
|
+
* threadStatus?: string,
|
|
109417
|
+
* model?: string,
|
|
109418
|
+
* cwd?: string,
|
|
109419
|
+
* approvalPolicy?: string,
|
|
109420
|
+
* maxHops?: number,
|
|
109421
|
+
* }} CodexSendOutcome
|
|
109422
|
+
*/ /**
|
|
109423
|
+
* Exit 0 iff the daemon is usable.
|
|
109424
|
+
* @param {{ reachable: boolean, mode: string }} status
|
|
109425
|
+
* @returns {0 | 1}
|
|
109426
|
+
*/ function statusExitCode(status) {
|
|
109427
|
+
return status.reachable && status.mode === "daemon" ? 0 : 1;
|
|
109428
|
+
}
|
|
109429
|
+
/**
|
|
109430
|
+
* Attach derived exitCode to a status document (never mutates input).
|
|
109431
|
+
* @param {Record<string, unknown>} status
|
|
109432
|
+
*/ function withStatusExitCode(status) {
|
|
109433
|
+
return {
|
|
109434
|
+
...status,
|
|
109435
|
+
exitCode: statusExitCode(/** @type {{ reachable: boolean, mode: string }} */ status)
|
|
109436
|
+
};
|
|
109437
|
+
}
|
|
109438
|
+
/**
|
|
109439
|
+
* @param {{
|
|
109440
|
+
* delivery: CodexDelivery,
|
|
109441
|
+
* reason?: string,
|
|
109442
|
+
* error?: string,
|
|
109443
|
+
* }} outcome
|
|
109444
|
+
* @returns {0 | 1}
|
|
109445
|
+
*/ function sendExitCode(outcome) {
|
|
109446
|
+
if (outcome.error !== undefined) return 1;
|
|
109447
|
+
if (outcome.delivery === "accepted" && outcome.reason === "approval-refused") return 1;
|
|
109448
|
+
if (outcome.delivery === "rejected" || outcome.delivery === "unknown") return 1;
|
|
109449
|
+
return 0;
|
|
109450
|
+
}
|
|
109451
|
+
/**
|
|
109452
|
+
* Flatten a thrown error into the #46 send/failure document (plus exitCode).
|
|
109453
|
+
*
|
|
109454
|
+
* @param {unknown} error
|
|
109455
|
+
* @param {{ isUsage?: (err: unknown) => boolean }} [opts]
|
|
109456
|
+
* @returns {CodexSendOutcome & { error: string, exitCode: 1 }}
|
|
109457
|
+
*/ function outcomeFromError(error, opts = {}) {
|
|
109458
|
+
const isUsage = opts.isUsage ?? ((err)=>err instanceof RangeError || Boolean(err && typeof err === "object" && err.name === "StoreError"));
|
|
109459
|
+
const message = (0,_url_policy_js__rspack_import_0/* .redactSecrets */.fp)(error instanceof Error ? error.message : String(error));
|
|
109460
|
+
/** @type {Record<string, unknown>} */ const out = {
|
|
109461
|
+
error: message
|
|
109462
|
+
};
|
|
109463
|
+
if (error && typeof error === "object") {
|
|
109464
|
+
for (const key of [
|
|
109465
|
+
"delivery",
|
|
109466
|
+
"reason",
|
|
109467
|
+
"mode",
|
|
109468
|
+
"threadId",
|
|
109469
|
+
"turnId",
|
|
109470
|
+
"targetId",
|
|
109471
|
+
"messageId",
|
|
109472
|
+
"correlationId",
|
|
109473
|
+
"refused",
|
|
109474
|
+
"hop"
|
|
109475
|
+
]){
|
|
109476
|
+
if (error[key] !== undefined) out[key] = error[key];
|
|
109477
|
+
}
|
|
109478
|
+
if (out.reason === undefined && isUsage(error)) out.reason = "usage";
|
|
109479
|
+
}
|
|
109480
|
+
if (out.delivery === undefined) out.delivery = "rejected";
|
|
109481
|
+
return /** @type {CodexSendOutcome & { error: string, exitCode: 1 }} */ {
|
|
109482
|
+
...out,
|
|
109483
|
+
exitCode: 1
|
|
109484
|
+
};
|
|
109485
|
+
}
|
|
109486
|
+
/**
|
|
109487
|
+
* Normalize a successful send receipt into a document with exitCode.
|
|
109488
|
+
* @param {Record<string, unknown>} receipt
|
|
109489
|
+
* @returns {CodexSendOutcome}
|
|
109490
|
+
*/ function outcomeFromReceipt(receipt) {
|
|
109491
|
+
const base = {
|
|
109492
|
+
...receipt
|
|
109493
|
+
};
|
|
109494
|
+
if (base.delivery === undefined) base.delivery = "accepted";
|
|
109495
|
+
const exitCode = sendExitCode(/** @type {{ delivery: CodexDelivery, reason?: string, error?: string }} */ base);
|
|
109496
|
+
if (exitCode === 1 && base.error === undefined && base.reason === "approval-refused") {
|
|
109497
|
+
base.error = typeof base.message === "string" ? base.message : "Codex refused one or more approvals.";
|
|
109498
|
+
}
|
|
109499
|
+
return /** @type {CodexSendOutcome} */ {
|
|
109500
|
+
...base,
|
|
109501
|
+
exitCode
|
|
109502
|
+
};
|
|
109503
|
+
}
|
|
109504
|
+
|
|
109505
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
109506
|
+
DG: () => (outcomeFromError),
|
|
109507
|
+
Dz: () => (outcomeFromReceipt)
|
|
109508
|
+
});
|
|
109509
|
+
|
|
109510
|
+
|
|
109511
|
+
},
|
|
109512
|
+
"./src/core/codex/conversation.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
109513
|
+
/* import */ var _contract_js__rspack_import_0 = __webpack_require__("./src/core/codex/contract.js");
|
|
109514
|
+
/* import */ var node_fs__rspack_import_1 = __webpack_require__("node:fs");
|
|
109515
|
+
/* import */ var _codex_bridge_js__rspack_import_2 = __webpack_require__("./src/core/codex-bridge.js");
|
|
109516
|
+
|
|
109517
|
+
|
|
109518
|
+
|
|
109519
|
+
const ID = /^[A-Za-z0-9_.:-]{1,128}$/;
|
|
109520
|
+
const BUDGET = 4 * 1024 * 1024;
|
|
109521
|
+
function conversationId(value, name = 'threadId') {
|
|
109522
|
+
if (typeof value !== 'string' || !ID.test(value)) throw new RangeError(`${name} must be 1-128 identifier characters`);
|
|
109523
|
+
return value;
|
|
109524
|
+
}
|
|
109525
|
+
function boundedInteger(value, max, name) {
|
|
109526
|
+
if (!Number.isInteger(value) || value < 1 || value > max) throw new RangeError(`${name} must be an integer 1-${max}`);
|
|
109527
|
+
return value;
|
|
109528
|
+
}
|
|
109529
|
+
const terminal = (status)=>[
|
|
109530
|
+
'completed',
|
|
109531
|
+
'failed',
|
|
109532
|
+
'interrupted'
|
|
109533
|
+
].includes(status);
|
|
109534
|
+
const namedTurn = (p)=>p?.turnId ?? p?.turn_id ?? p?.turn?.id;
|
|
109535
|
+
/** Bounded traversal; a coverage failure throws and must never be interpreted as not found. */ async function visitCodexHistory(session, threadId, method, params, visit, { signal, stopped = ()=>false } = {}) {
|
|
109536
|
+
if (![
|
|
109537
|
+
'thread/turns/list',
|
|
109538
|
+
'thread/items/list'
|
|
109539
|
+
].includes(method)) throw new RangeError('Unsupported history method');
|
|
109540
|
+
conversationId(threadId);
|
|
109541
|
+
const client = session.client;
|
|
109542
|
+
let cursor;
|
|
109543
|
+
const seen = new Set();
|
|
109544
|
+
for(let page = 0; page < 20; page++){
|
|
109545
|
+
if (stopped() || signal?.aborted) throw new Error('History coverage incomplete: observation cancelled');
|
|
109546
|
+
const result = await client.request(method, {
|
|
109547
|
+
...params,
|
|
109548
|
+
threadId,
|
|
109549
|
+
limit: 100,
|
|
109550
|
+
...cursor ? {
|
|
109551
|
+
cursor
|
|
109552
|
+
} : {}
|
|
109553
|
+
});
|
|
109554
|
+
if (stopped() || signal?.aborted) throw new Error('History coverage incomplete: observation cancelled');
|
|
109555
|
+
if (!Array.isArray(result?.data) || result.data.length > 100 || result.nextCursor != null && (typeof result.nextCursor !== 'string' || !result.nextCursor || result.nextCursor.length > 4096)) throw new Error(`Invalid ${method} page`);
|
|
109556
|
+
if (visit(result.data)) return {
|
|
109557
|
+
complete: false,
|
|
109558
|
+
reason: 'matched',
|
|
109559
|
+
pages: page + 1
|
|
109560
|
+
};
|
|
109561
|
+
if (result.nextCursor == null) return {
|
|
109562
|
+
complete: true,
|
|
109563
|
+
reason: 'exhausted',
|
|
109564
|
+
pages: page + 1
|
|
109565
|
+
};
|
|
109566
|
+
if (seen.has(result.nextCursor)) throw new Error('History coverage incomplete: repeated pagination cursor');
|
|
109567
|
+
seen.add(result.nextCursor);
|
|
109568
|
+
cursor = result.nextCursor;
|
|
109569
|
+
}
|
|
109570
|
+
throw new Error('History coverage incomplete: 20 page limit');
|
|
109571
|
+
}
|
|
109572
|
+
/** A bounded observer. Cancellation ends observation, never the daemon's turn. */ async function openCodexConversation(threadId, options = {}) {
|
|
109573
|
+
conversationId(threadId);
|
|
109574
|
+
const { env = process.env, expectedCwd, signal, onEvent } = options;
|
|
109575
|
+
(0,_codex_bridge_js__rspack_import_2/* .assertThreadAllowed */.$3)(threadId, env);
|
|
109576
|
+
if (signal !== undefined && !(signal instanceof AbortSignal)) throw new TypeError('signal must be an AbortSignal');
|
|
109577
|
+
if (onEvent !== undefined && typeof onEvent !== 'function') throw new TypeError('onEvent must be a function');
|
|
109578
|
+
if (signal?.aborted) throw new Error('Observation cancelled');
|
|
109579
|
+
const expected = expectedCwd === undefined ? undefined : (0,node_fs__rspack_import_1.realpathSync)(expectedCwd);
|
|
109580
|
+
const session = options.session ?? await (0,_codex_bridge_js__rspack_import_2/* .openCodexSession */.eC)(env, {
|
|
109581
|
+
signal,
|
|
109582
|
+
experimental: (0,_codex_bridge_js__rspack_import_2/* .experimentalEnabled */.e0)(env)
|
|
109583
|
+
});
|
|
109584
|
+
const { client } = session;
|
|
109585
|
+
const events = [];
|
|
109586
|
+
const acceptedTurns = new Set();
|
|
109587
|
+
const wake = new Set();
|
|
109588
|
+
let bytes = 0, overflow = false, disconnected = client.closed, closed = false;
|
|
109589
|
+
const record = (event)=>{
|
|
109590
|
+
const size = Buffer.byteLength(JSON.stringify(event));
|
|
109591
|
+
if (size > BUDGET) {
|
|
109592
|
+
overflow = true;
|
|
109593
|
+
} else {
|
|
109594
|
+
while(events.length >= 500 || bytes + size > BUDGET){
|
|
109595
|
+
bytes -= events.shift().bytes;
|
|
109596
|
+
overflow = true;
|
|
109597
|
+
}
|
|
109598
|
+
events.push({
|
|
109599
|
+
event,
|
|
109600
|
+
bytes: size
|
|
109601
|
+
});
|
|
109602
|
+
bytes += size;
|
|
109603
|
+
}
|
|
109604
|
+
for (const listener of [
|
|
109605
|
+
...wake
|
|
109606
|
+
])listener();
|
|
109607
|
+
return onEvent?.(event);
|
|
109608
|
+
};
|
|
109609
|
+
const observe = (kind)=>(message)=>{
|
|
109610
|
+
const p = message.params;
|
|
109611
|
+
if ((p?.threadId ?? p?.thread_id) !== threadId) return;
|
|
109612
|
+
return record({
|
|
109613
|
+
kind,
|
|
109614
|
+
...message
|
|
109615
|
+
});
|
|
109616
|
+
};
|
|
109617
|
+
const unsubs = [
|
|
109618
|
+
client.onNotification(observe('notification')),
|
|
109619
|
+
client.onServerRequest(observe('interaction')),
|
|
109620
|
+
client.onClose((error)=>{
|
|
109621
|
+
disconnected = true;
|
|
109622
|
+
return record({
|
|
109623
|
+
kind: 'disconnect',
|
|
109624
|
+
error: error?.message
|
|
109625
|
+
});
|
|
109626
|
+
})
|
|
109627
|
+
];
|
|
109628
|
+
const close = async ()=>{
|
|
109629
|
+
if (closed) return;
|
|
109630
|
+
closed = true;
|
|
109631
|
+
for (const unsubscribe of unsubs)unsubscribe();
|
|
109632
|
+
for (const listener of wake)listener();
|
|
109633
|
+
if (!options.session) client.close();
|
|
109634
|
+
};
|
|
109635
|
+
let resumed;
|
|
109636
|
+
try {
|
|
109637
|
+
resumed = await client.request('thread/resume', {
|
|
109638
|
+
threadId,
|
|
109639
|
+
excludeTurns: true
|
|
109640
|
+
});
|
|
109641
|
+
if (resumed?.thread?.id !== threadId) throw new Error('thread/resume returned a different thread ID');
|
|
109642
|
+
const cwd = resumed.cwd ?? resumed.thread.cwd;
|
|
109643
|
+
if (expected !== undefined && (typeof cwd !== 'string' || (0,node_fs__rspack_import_1.realpathSync)(cwd) !== expected)) throw new Error('Codex thread cwd does not match expectedCwd');
|
|
109644
|
+
} catch (error) {
|
|
109645
|
+
await close();
|
|
109646
|
+
throw error;
|
|
109647
|
+
}
|
|
109648
|
+
/** @param {{turnId: string, messageId?: string, afterMessageId?: string|string[], timeoutMs?: number, signal?: AbortSignal, maxOutputBytes?: number}} options */ async function wait({ turnId, messageId, afterMessageId, timeoutMs = 120000, signal: waitSignal, maxOutputBytes = 1048576 }) {
|
|
109649
|
+
conversationId(turnId, 'turnId');
|
|
109650
|
+
if (messageId !== undefined) conversationId(messageId, 'messageId');
|
|
109651
|
+
const anchors = afterMessageId === undefined ? [] : Array.isArray(afterMessageId) ? afterMessageId : [
|
|
109652
|
+
afterMessageId
|
|
109653
|
+
];
|
|
109654
|
+
if (afterMessageId !== undefined) boundedInteger(anchors.length, 200, 'afterMessageId count');
|
|
109655
|
+
for (const anchor of anchors)conversationId(anchor, 'afterMessageId');
|
|
109656
|
+
boundedInteger(timeoutMs, 600000, 'timeoutMs');
|
|
109657
|
+
boundedInteger(maxOutputBytes, BUDGET, 'maxOutputBytes');
|
|
109658
|
+
if (waitSignal !== undefined && !(waitSignal instanceof AbortSignal)) throw new TypeError('signal must be an AbortSignal');
|
|
109659
|
+
let done = false, status = acceptedTurns.has(turnId) ? 'inProgress' : undefined, error, historyError, itemBytes = 0, truncated = overflow;
|
|
109660
|
+
const items = new Map();
|
|
109661
|
+
const add = (item)=>{
|
|
109662
|
+
if (!item || typeof item.id !== 'string' || typeof item.type !== 'string') throw new Error('Invalid history item');
|
|
109663
|
+
if (item.type !== 'agentMessage' || typeof item.text !== 'string' || item.phase !== 'final_answer' && item.phase != null) return;
|
|
109664
|
+
const normalized = {
|
|
109665
|
+
id: item.id,
|
|
109666
|
+
type: item.type,
|
|
109667
|
+
phase: item.phase ?? null,
|
|
109668
|
+
text: item.text
|
|
109669
|
+
};
|
|
109670
|
+
const size = Buffer.byteLength(JSON.stringify(normalized));
|
|
109671
|
+
const prior = items.get(item.id);
|
|
109672
|
+
if (itemBytes - (prior?.bytes ?? 0) + size > BUDGET || !prior && items.size >= 2000) {
|
|
109673
|
+
truncated = true;
|
|
109674
|
+
return;
|
|
109675
|
+
}
|
|
109676
|
+
itemBytes += size - (prior?.bytes ?? 0);
|
|
109677
|
+
items.set(item.id, {
|
|
109678
|
+
item: normalized,
|
|
109679
|
+
bytes: size
|
|
109680
|
+
});
|
|
109681
|
+
};
|
|
109682
|
+
const scan = ()=>{
|
|
109683
|
+
const interactions = new Map();
|
|
109684
|
+
for (const { event } of events){
|
|
109685
|
+
const p = event.params;
|
|
109686
|
+
if (event.method === 'serverRequest/resolved') {
|
|
109687
|
+
interactions.delete(p.requestId);
|
|
109688
|
+
continue;
|
|
109689
|
+
}
|
|
109690
|
+
if (namedTurn(p) !== turnId) continue;
|
|
109691
|
+
if (event.kind === 'interaction') interactions.set(event.id, event);
|
|
109692
|
+
if (event.method === 'turn/started' && !terminal(status)) status = p.turn?.status;
|
|
109693
|
+
if (event.method === 'item/completed' && afterMessageId === undefined) add(p.item);
|
|
109694
|
+
if (event.method === 'turn/completed') {
|
|
109695
|
+
status = p.turn?.status;
|
|
109696
|
+
error = p.turn?.error;
|
|
109697
|
+
if (afterMessageId === undefined) for (const item of p.turn?.items ?? [])add(item);
|
|
109698
|
+
}
|
|
109699
|
+
}
|
|
109700
|
+
return [
|
|
109701
|
+
...interactions.values()
|
|
109702
|
+
];
|
|
109703
|
+
};
|
|
109704
|
+
const result = (state, detail)=>{
|
|
109705
|
+
const interactions = scan();
|
|
109706
|
+
const candidates = [
|
|
109707
|
+
...items.values()
|
|
109708
|
+
].map((x)=>x.item);
|
|
109709
|
+
const finals = candidates.filter((i)=>i.phase === 'final_answer');
|
|
109710
|
+
// Old app-servers omit phase; use their completed agent items only at terminal status.
|
|
109711
|
+
const selected = finals.length ? finals : terminal(state) ? candidates : [];
|
|
109712
|
+
const reply = {
|
|
109713
|
+
text: '',
|
|
109714
|
+
items: [],
|
|
109715
|
+
truncated: truncated || overflow
|
|
109716
|
+
};
|
|
109717
|
+
for (const item of selected){
|
|
109718
|
+
const text = reply.text ? `${reply.text}\n${item.text}` : item.text;
|
|
109719
|
+
if (Buffer.byteLength(JSON.stringify({
|
|
109720
|
+
text,
|
|
109721
|
+
items: [
|
|
109722
|
+
...reply.items,
|
|
109723
|
+
item
|
|
109724
|
+
]
|
|
109725
|
+
})) > maxOutputBytes) {
|
|
109726
|
+
reply.truncated = true;
|
|
109727
|
+
break;
|
|
109728
|
+
}
|
|
109729
|
+
reply.text = text;
|
|
109730
|
+
reply.items.push(item);
|
|
109731
|
+
}
|
|
109732
|
+
return {
|
|
109733
|
+
threadId,
|
|
109734
|
+
turnId,
|
|
109735
|
+
...messageId === undefined ? {} : {
|
|
109736
|
+
messageId
|
|
109737
|
+
},
|
|
109738
|
+
execution: {
|
|
109739
|
+
state,
|
|
109740
|
+
...detail ? {
|
|
109741
|
+
error: detail
|
|
109742
|
+
} : {}
|
|
109743
|
+
},
|
|
109744
|
+
reply,
|
|
109745
|
+
interactions
|
|
109746
|
+
};
|
|
109747
|
+
};
|
|
109748
|
+
let timer, notify;
|
|
109749
|
+
const abortSignals = [
|
|
109750
|
+
signal,
|
|
109751
|
+
waitSignal
|
|
109752
|
+
].filter(Boolean);
|
|
109753
|
+
const stopped = new Promise((resolve)=>{
|
|
109754
|
+
notify = ()=>{
|
|
109755
|
+
if (abortSignals.some((s)=>s.aborted) || closed) resolve([
|
|
109756
|
+
'unknown',
|
|
109757
|
+
'Observation cancelled'
|
|
109758
|
+
]);
|
|
109759
|
+
else if (disconnected) resolve([
|
|
109760
|
+
'disconnected',
|
|
109761
|
+
'Codex connection closed'
|
|
109762
|
+
]);
|
|
109763
|
+
};
|
|
109764
|
+
timer = setTimeout(()=>resolve([
|
|
109765
|
+
'timeout',
|
|
109766
|
+
'Observation deadline reached'
|
|
109767
|
+
]), timeoutMs);
|
|
109768
|
+
for (const s of abortSignals)s.addEventListener('abort', notify, {
|
|
109769
|
+
once: true
|
|
109770
|
+
});
|
|
109771
|
+
wake.add(notify);
|
|
109772
|
+
notify();
|
|
109773
|
+
});
|
|
109774
|
+
const collect = async ()=>{
|
|
109775
|
+
scan();
|
|
109776
|
+
try {
|
|
109777
|
+
let found = false, historyTerminal = false, anchorFound = afterMessageId === undefined;
|
|
109778
|
+
const missingAnchors = new Set(anchors);
|
|
109779
|
+
await visitCodexHistory(session, threadId, 'thread/turns/list', {}, (data)=>{
|
|
109780
|
+
for (const turn of data)if (!turn || typeof turn.id !== 'string' || typeof turn.status !== 'string') throw new Error('Invalid turn history');
|
|
109781
|
+
const turn = data.find((t)=>t.id === turnId);
|
|
109782
|
+
if (!turn) return false;
|
|
109783
|
+
found = true;
|
|
109784
|
+
historyTerminal = terminal(turn.status);
|
|
109785
|
+
if (!terminal(status)) {
|
|
109786
|
+
status = turn.status;
|
|
109787
|
+
error = turn.error;
|
|
109788
|
+
}
|
|
109789
|
+
return true;
|
|
109790
|
+
}, {
|
|
109791
|
+
stopped: ()=>done
|
|
109792
|
+
});
|
|
109793
|
+
// Notifications can establish completion while the history response is in flight.
|
|
109794
|
+
scan();
|
|
109795
|
+
if (!found && !status) return [
|
|
109796
|
+
'unknown',
|
|
109797
|
+
'History coverage incomplete: selected turn not found'
|
|
109798
|
+
];
|
|
109799
|
+
await visitCodexHistory(session, threadId, 'thread/items/list', {
|
|
109800
|
+
turnId,
|
|
109801
|
+
sortDirection: 'asc'
|
|
109802
|
+
}, (data)=>{
|
|
109803
|
+
for (const row of data){
|
|
109804
|
+
if (!row || row.turnId !== turnId || !row.item) throw new Error('Invalid thread/items/list wrapper');
|
|
109805
|
+
if (row.item.type === 'userMessage' && anchors.includes(row.item.clientId)) {
|
|
109806
|
+
anchorFound = true;
|
|
109807
|
+
missingAnchors.delete(row.item.clientId);
|
|
109808
|
+
}
|
|
109809
|
+
if (anchorFound) add(row.item);
|
|
109810
|
+
}
|
|
109811
|
+
return false;
|
|
109812
|
+
}, {
|
|
109813
|
+
stopped: ()=>done
|
|
109814
|
+
});
|
|
109815
|
+
if (!anchorFound || missingAnchors.size) {
|
|
109816
|
+
items.clear();
|
|
109817
|
+
return [
|
|
109818
|
+
'unknown',
|
|
109819
|
+
'History coverage incomplete: reply anchor not found'
|
|
109820
|
+
];
|
|
109821
|
+
}
|
|
109822
|
+
if (afterMessageId !== undefined && !historyTerminal) return scan().length ? [
|
|
109823
|
+
'waiting-for-input'
|
|
109824
|
+
] : [
|
|
109825
|
+
'unknown',
|
|
109826
|
+
'Anchored reply awaits terminal history'
|
|
109827
|
+
];
|
|
109828
|
+
} catch (err) {
|
|
109829
|
+
historyError = err.message;
|
|
109830
|
+
truncated = true;
|
|
109831
|
+
}
|
|
109832
|
+
if (afterMessageId !== undefined && historyError) {
|
|
109833
|
+
items.clear();
|
|
109834
|
+
return [
|
|
109835
|
+
'unknown',
|
|
109836
|
+
historyError
|
|
109837
|
+
];
|
|
109838
|
+
}
|
|
109839
|
+
while(!done){
|
|
109840
|
+
const interactions = scan();
|
|
109841
|
+
if (terminal(status)) return [
|
|
109842
|
+
status,
|
|
109843
|
+
error ?? historyError
|
|
109844
|
+
];
|
|
109845
|
+
if (historyError || overflow) return [
|
|
109846
|
+
'unknown',
|
|
109847
|
+
historyError ?? 'Notification coverage overflow'
|
|
109848
|
+
];
|
|
109849
|
+
if (interactions.length) return [
|
|
109850
|
+
'waiting-for-input'
|
|
109851
|
+
];
|
|
109852
|
+
await new Promise((resolve)=>{
|
|
109853
|
+
const listener = ()=>{
|
|
109854
|
+
wake.delete(listener);
|
|
109855
|
+
resolve();
|
|
109856
|
+
};
|
|
109857
|
+
wake.add(listener);
|
|
109858
|
+
});
|
|
109859
|
+
}
|
|
109860
|
+
return [
|
|
109861
|
+
'unknown',
|
|
109862
|
+
'Observation ended'
|
|
109863
|
+
];
|
|
109864
|
+
};
|
|
109865
|
+
try {
|
|
109866
|
+
const [state, detail] = await Promise.race([
|
|
109867
|
+
stopped,
|
|
109868
|
+
collect()
|
|
109869
|
+
]);
|
|
109870
|
+
return result(state, detail);
|
|
109871
|
+
} finally{
|
|
109872
|
+
done = true;
|
|
109873
|
+
clearTimeout(timer);
|
|
109874
|
+
wake.delete(notify);
|
|
109875
|
+
for (const s of abortSignals)s.removeEventListener('abort', notify);
|
|
109876
|
+
for (const listener of [
|
|
109877
|
+
...wake
|
|
109878
|
+
])listener();
|
|
109879
|
+
}
|
|
109880
|
+
}
|
|
109881
|
+
/** @param {{timeoutMs?: number, maxEvents?: number, signal?: AbortSignal}} [options] */ async function watch({ timeoutMs = 30000, maxEvents = 100, signal: watchSignal } = {}) {
|
|
109882
|
+
boundedInteger(timeoutMs, 600000, 'timeoutMs');
|
|
109883
|
+
boundedInteger(maxEvents, 500, 'maxEvents');
|
|
109884
|
+
if (watchSignal !== undefined && !(watchSignal instanceof AbortSignal)) throw new TypeError('signal must be an AbortSignal');
|
|
109885
|
+
const signals = [
|
|
109886
|
+
signal,
|
|
109887
|
+
watchSignal
|
|
109888
|
+
].filter(Boolean);
|
|
109889
|
+
let timer, listener;
|
|
109890
|
+
const reason = await new Promise((resolve)=>{
|
|
109891
|
+
listener = ()=>{
|
|
109892
|
+
if (signals.some((s)=>s.aborted) || closed) resolve('cancelled');
|
|
109893
|
+
else if (disconnected) resolve('disconnected');
|
|
109894
|
+
else if (events.length >= maxEvents) resolve('event-limit');
|
|
109895
|
+
};
|
|
109896
|
+
timer = setTimeout(()=>resolve('timeout'), timeoutMs);
|
|
109897
|
+
wake.add(listener);
|
|
109898
|
+
for (const s of signals)s.addEventListener('abort', listener, {
|
|
109899
|
+
once: true
|
|
109900
|
+
});
|
|
109901
|
+
listener();
|
|
109902
|
+
});
|
|
109903
|
+
clearTimeout(timer);
|
|
109904
|
+
wake.delete(listener);
|
|
109905
|
+
for (const s of signals)s.removeEventListener('abort', listener);
|
|
109906
|
+
return {
|
|
109907
|
+
threadId,
|
|
109908
|
+
events: events.slice(0, maxEvents).map((x)=>x.event),
|
|
109909
|
+
reason,
|
|
109910
|
+
truncated: overflow || events.length > maxEvents
|
|
109911
|
+
};
|
|
109912
|
+
}
|
|
109913
|
+
return {
|
|
109914
|
+
threadId,
|
|
109915
|
+
cwd: resumed.cwd ?? resumed.thread.cwd,
|
|
109916
|
+
wait,
|
|
109917
|
+
watch,
|
|
109918
|
+
close,
|
|
109919
|
+
/** @param {string} text
|
|
109920
|
+
* @param {{envelope?: object, whenBusy?: string, expectedTurnId?: string, signal?: AbortSignal}} [options] */ async send (text, { envelope = (0,_codex_bridge_js__rspack_import_2/* .buildEnvelope */.nq)({
|
|
109921
|
+
env
|
|
109922
|
+
}), whenBusy = 'reject', expectedTurnId, signal: sendSignal } = {}) {
|
|
109923
|
+
if (closed) return (0,_contract_js__rspack_import_0/* .outcomeFromError */.DG)(Object.assign(new Error('Conversation closed'), {
|
|
109924
|
+
delivery: 'rejected',
|
|
109925
|
+
reason: 'closed',
|
|
109926
|
+
threadId,
|
|
109927
|
+
envelope
|
|
109928
|
+
}));
|
|
109929
|
+
if (sendSignal !== undefined && !(sendSignal instanceof AbortSignal)) throw new TypeError('signal must be an AbortSignal');
|
|
109930
|
+
const submissionSignal = signal && sendSignal ? AbortSignal.any([
|
|
109931
|
+
signal,
|
|
109932
|
+
sendSignal
|
|
109933
|
+
]) : sendSignal ?? signal;
|
|
109934
|
+
const receipt = await (0,_codex_bridge_js__rspack_import_2/* .sendToCodexThread */.ZS)(threadId, text, {
|
|
109935
|
+
env,
|
|
109936
|
+
envelope,
|
|
109937
|
+
whenBusy,
|
|
109938
|
+
expectedTurnId,
|
|
109939
|
+
session,
|
|
109940
|
+
expectedCwd,
|
|
109941
|
+
signal: submissionSignal
|
|
109942
|
+
});
|
|
109943
|
+
if (receipt.delivery === 'accepted' && receipt.turnId) {
|
|
109944
|
+
acceptedTurns.add(receipt.turnId);
|
|
109945
|
+
if (acceptedTurns.size > 100) acceptedTurns.delete(acceptedTurns.values().next().value);
|
|
109946
|
+
}
|
|
109947
|
+
return receipt;
|
|
109948
|
+
}
|
|
109949
|
+
};
|
|
109950
|
+
}
|
|
109951
|
+
|
|
109952
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
109953
|
+
j: () => (openCodexConversation)
|
|
106548
109954
|
});
|
|
106549
109955
|
|
|
106550
109956
|
|
|
109957
|
+
},
|
|
109958
|
+
"./src/core/desktop-shim.js"(__unused_rspack___webpack_module__, __unused_rspack___webpack_exports__, __webpack_require__) {
|
|
109959
|
+
/* import */ var node_child_process__rspack_import_0 = __webpack_require__("node:child_process");
|
|
109960
|
+
/* import */ var node_fs__rspack_import_1 = __webpack_require__("node:fs");
|
|
109961
|
+
/* import */ var node_os__rspack_import_2 = __webpack_require__("node:os");
|
|
109962
|
+
/* import */ var node_path__rspack_import_3 = __webpack_require__("node:path");
|
|
109963
|
+
|
|
109964
|
+
|
|
109965
|
+
|
|
109966
|
+
|
|
109967
|
+
|
|
109968
|
+
/**
|
|
109969
|
+
* ChatGPT Desktop -> managed Codex daemon shim (CODEX_CLI_PATH bridge).
|
|
109970
|
+
*
|
|
109971
|
+
* Desktop injects `codex_app` overrides so CODEX_APP_SERVER_USE_LOCAL_DAEMON=1
|
|
109972
|
+
* alone cannot select the managed daemon, and stock `codex app-server proxy`
|
|
109973
|
+
* hangs for Desktop stdio. The winning path is a wrapper on CODEX_CLI_PATH
|
|
109974
|
+
* that rewrites Desktop's `codex ... app-server` spawn into the stdio<->WS
|
|
109975
|
+
* bridge (desktop-shim-bridge.js) onto the managed control socket.
|
|
109976
|
+
* Provenance: uploads/codex-desktop-to-daemon + codex-desktop-shared-daemon-env.sh.
|
|
109977
|
+
*
|
|
109978
|
+
* Fail-open is the hard rule: the wrapper execs the real standalone `codex`
|
|
109979
|
+
* for non-app-server spawns and whenever the bridge/python/socket side is
|
|
109980
|
+
* missing or broken. Never touches Desktop binaries, /tmp/codex-browser-use/,
|
|
109981
|
+
* or CODEX_APP_TOOLS_PIPE_PATH. No protocol change: gbot already speaks the
|
|
109982
|
+
* managed control socket.
|
|
109983
|
+
*/ const SHIM_LABEL = "com.zackjackson.codex-desktop-shared-daemon";
|
|
109984
|
+
const WRAPPER_FILENAME = "codex-desktop-to-daemon";
|
|
109985
|
+
const BRIDGE_FILENAME = "codex-stdio-to-daemon-ws.py";
|
|
109986
|
+
const ENV_SCRIPT_FILENAME = "codex-desktop-shared-daemon-env.sh";
|
|
109987
|
+
const BRIDGE_LOG_FILENAME = "codex-stdio-to-daemon-ws.log";
|
|
109988
|
+
const WRAPPER_LOG_FILENAME = "codex-desktop-to-daemon.log";
|
|
109989
|
+
const ENV_LOG_FILENAME = "codex-desktop-shared-daemon-env.log";
|
|
109990
|
+
const STANDALONE_REAL_SUFFIX = (0,node_path__rspack_import_3.join)("packages", "standalone", "current", "bin", "codex");
|
|
109991
|
+
function codexHomeDir(env = process.env) {
|
|
109992
|
+
return env.CODEX_HOME || join(env.HOME || homedir(), ".codex");
|
|
109993
|
+
}
|
|
109994
|
+
function userHomeDir(env = process.env) {
|
|
109995
|
+
return env.HOME || homedir();
|
|
109996
|
+
}
|
|
109997
|
+
function defaultPaths({ env = process.env, home = userHomeDir(env) } = {}) {
|
|
109998
|
+
const codexHome = env.CODEX_HOME || join(home, ".codex");
|
|
109999
|
+
const binDir = join(codexHome, "bin");
|
|
110000
|
+
return {
|
|
110001
|
+
binDir,
|
|
110002
|
+
bridgeLogPath: join(binDir, BRIDGE_LOG_FILENAME),
|
|
110003
|
+
bridgePath: join(binDir, BRIDGE_FILENAME),
|
|
110004
|
+
codexHome,
|
|
110005
|
+
envLogPath: join(binDir, ENV_LOG_FILENAME),
|
|
110006
|
+
envScriptPath: join(binDir, ENV_SCRIPT_FILENAME),
|
|
110007
|
+
label: SHIM_LABEL,
|
|
110008
|
+
launchAgentsDir: join(home, "Library", "LaunchAgents"),
|
|
110009
|
+
plistPath: join(home, "Library", "LaunchAgents", `${SHIM_LABEL}.plist`),
|
|
110010
|
+
realPath: join(codexHome, STANDALONE_REAL_SUFFIX),
|
|
110011
|
+
socketPath: join(codexHome, "app-server-control", "app-server-control.sock"),
|
|
110012
|
+
wrapperLogPath: join(binDir, WRAPPER_LOG_FILENAME),
|
|
110013
|
+
wrapperPath: join(binDir, WRAPPER_FILENAME)
|
|
110014
|
+
};
|
|
110015
|
+
}
|
|
110016
|
+
/**
|
|
110017
|
+
* Pure passthrough decision, mirroring the wrapper's argv scan. True only for
|
|
110018
|
+
* a bare `app-server` spawn: Desktop's private-stdio case. `daemon`, `proxy`,
|
|
110019
|
+
* and schema generations always exec the real Codex.
|
|
110020
|
+
*/ function shouldBridge(argv) {
|
|
110021
|
+
let appServer = false;
|
|
110022
|
+
let daemon = false;
|
|
110023
|
+
let proxy = false;
|
|
110024
|
+
let generate = false;
|
|
110025
|
+
for (const arg of argv ?? []){
|
|
110026
|
+
if (arg === "app-server") appServer = true;
|
|
110027
|
+
else if (arg === "daemon") daemon = true;
|
|
110028
|
+
else if (arg === "proxy") proxy = true;
|
|
110029
|
+
else if (arg === "generate-ts" || arg === "generate-json-schema") generate = true;
|
|
110030
|
+
}
|
|
110031
|
+
return appServer && !daemon && !proxy && !generate;
|
|
110032
|
+
}
|
|
110033
|
+
function renderWrapperScript({ realPath, bridgePath, wrapperLogPath, codexHome, bridgeLogPath }) {
|
|
110034
|
+
return `#!/bin/bash
|
|
110035
|
+
# Installed by \`gbot codex desktop-shim install\`. Rewrites ChatGPT Desktop's
|
|
110036
|
+
# \`codex ... app-server\` spawn into a stdio<->WebSocket bridge onto the managed
|
|
110037
|
+
# daemon's control socket. Reversible: \`gbot codex desktop-shim uninstall\`.
|
|
110038
|
+
# The daemon is kept up by the LaunchAgent login script, not here: this hot path
|
|
110039
|
+
# never starts the daemon itself, so a wedged daemon lock cannot hang
|
|
110040
|
+
# Desktop. Fail-open runs ONLY while stdio is still pristine (no stdin
|
|
110041
|
+
# consumed, no stdout written): an absent socket fails the preflight and a
|
|
110042
|
+
# pre-session bridge failure (exit 1) falls through
|
|
110043
|
+
# to the real standalone codex on pristine stdio. A mid-session bridge failure
|
|
110044
|
+
# (exit 2+) exits promptly so Desktop reconnects; the fallback never runs on
|
|
110045
|
+
# half-consumed stdin or dirty stdout. Bridge exit 0 means it served the session. Never touches
|
|
110046
|
+
# Desktop binaries or its private tool pipe.
|
|
110047
|
+
set -u
|
|
110048
|
+
REAL="\${CODEX_DESKTOP_WRAPPER_REAL:-${realPath}}"
|
|
110049
|
+
BRIDGE="\${CODEX_DESKTOP_BRIDGE:-${bridgePath}}"
|
|
110050
|
+
export CODEX_HOME="\${CODEX_HOME:-${codexHome}}"
|
|
110051
|
+
SOCK="\${CODEX_APP_SERVER_SOCK:-$CODEX_HOME/app-server-control/app-server-control.sock}"
|
|
110052
|
+
BRIDGE_LOG="\${CODEX_STDIO_BRIDGE_LOG:-${bridgeLogPath}}"
|
|
110053
|
+
LOG="\${CODEX_DESKTOP_WRAPPER_LOG:-${wrapperLogPath}}"
|
|
110054
|
+
export CODEX_APP_SERVER_SOCK="$SOCK"
|
|
110055
|
+
export CODEX_STDIO_BRIDGE_LOG="$BRIDGE_LOG"
|
|
110056
|
+
ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|
|
110057
|
+
echo "$(ts) argv: $*" >>"$LOG" 2>/dev/null || true
|
|
110058
|
+
|
|
110059
|
+
if [[ ! -x "$REAL" ]]; then
|
|
110060
|
+
FALLBACK="$(command -v codex 2>/dev/null || true)"
|
|
110061
|
+
if [[ -n "$FALLBACK" && -x "$FALLBACK" ]]; then
|
|
110062
|
+
if [[ "$FALLBACK" -ef "$0" ]] 2>/dev/null || { [[ -n "\${CODEX_CLI_PATH:-}" ]] && [[ "$FALLBACK" -ef "\${CODEX_CLI_PATH}" ]] 2>/dev/null; }; then
|
|
110063
|
+
echo "$(ts) refusing self fallback $FALLBACK" >>"$LOG" 2>/dev/null || true
|
|
110064
|
+
else
|
|
110065
|
+
REAL="$FALLBACK"
|
|
110066
|
+
fi
|
|
110067
|
+
fi
|
|
110068
|
+
fi
|
|
110069
|
+
|
|
110070
|
+
has_app_server=0; has_daemon=0; has_proxy=0; has_generate=0
|
|
110071
|
+
for a in "$@"; do
|
|
110072
|
+
case "$a" in
|
|
110073
|
+
app-server) has_app_server=1 ;;
|
|
110074
|
+
daemon) has_daemon=1 ;;
|
|
110075
|
+
proxy) has_proxy=1 ;;
|
|
110076
|
+
generate-ts|generate-json-schema) has_generate=1 ;;
|
|
110077
|
+
esac
|
|
110078
|
+
done
|
|
110079
|
+
|
|
110080
|
+
# Preflight the daemon socket with a short deadline: a refused/absent socket
|
|
110081
|
+
# means starting the bridge could never succeed, so skip straight to real codex.
|
|
110082
|
+
preflight() {
|
|
110083
|
+
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
|
|
110084
|
+
}
|
|
110085
|
+
|
|
110086
|
+
if [[ "$has_app_server" -eq 1 && "$has_daemon" -eq 0 && "$has_proxy" -eq 0 && "$has_generate" -eq 0 ]]; then
|
|
110087
|
+
if [[ -f "$BRIDGE" ]] && command -v python3 >/dev/null 2>&1; then
|
|
110088
|
+
if preflight; then
|
|
110089
|
+
echo "$(ts) rewrite -> stdio-ws bridge" >>"$LOG" 2>/dev/null || true
|
|
110090
|
+
python3 "$BRIDGE"
|
|
110091
|
+
rc=$?
|
|
110092
|
+
case "$rc" in
|
|
110093
|
+
0)
|
|
110094
|
+
echo "$(ts) bridge served session" >>"$LOG" 2>/dev/null || true
|
|
110095
|
+
exit 0
|
|
110096
|
+
;;
|
|
110097
|
+
1)
|
|
110098
|
+
echo "$(ts) bridge failed before session start, falling through to real codex" >>"$LOG" 2>/dev/null || true
|
|
110099
|
+
;;
|
|
110100
|
+
*)
|
|
110101
|
+
echo "$(ts) bridge failed mid-session (rc=$rc); exiting so Desktop reconnects" >>"$LOG" 2>/dev/null || true
|
|
110102
|
+
exit "$rc"
|
|
110103
|
+
;;
|
|
110104
|
+
esac
|
|
110105
|
+
else
|
|
110106
|
+
echo "$(ts) daemon socket unreachable, passthrough to real codex" >>"$LOG" 2>/dev/null || true
|
|
110107
|
+
fi
|
|
110108
|
+
else
|
|
110109
|
+
echo "$(ts) bridge unavailable, passthrough to real codex" >>"$LOG" 2>/dev/null || true
|
|
110110
|
+
fi
|
|
110111
|
+
fi
|
|
110112
|
+
if [[ -x "$REAL" ]]; then
|
|
110113
|
+
exec "$REAL" "$@"
|
|
110114
|
+
fi
|
|
110115
|
+
echo "codex-desktop-to-daemon: no runnable codex found" >&2
|
|
110116
|
+
exit 1
|
|
110117
|
+
`;
|
|
110118
|
+
}
|
|
110119
|
+
function renderEnvScript({ wrapperPath, realPath, envLogPath, codexHome }) {
|
|
110120
|
+
return `#!/bin/bash
|
|
110121
|
+
# Installed by \`gbot codex desktop-shim install\`. Re-applies the GUI-domain env
|
|
110122
|
+
# so ChatGPT.app inherits CODEX_CLI_PATH after login, then best-effort starts the
|
|
110123
|
+
# managed daemon (this login script — never Desktop's spawn hot path — owns
|
|
110124
|
+
# daemon upkeep). No -e: every step is best-effort so login never breaks.
|
|
110125
|
+
# Revert: \`gbot codex desktop-shim uninstall\`.
|
|
110126
|
+
set -u
|
|
110127
|
+
WRAPPER="${wrapperPath}"
|
|
110128
|
+
REAL="${realPath}"
|
|
110129
|
+
LOG="${envLogPath}"
|
|
110130
|
+
CODEX_HOME_DIR="${codexHome}"
|
|
110131
|
+
# One CODEX_HOME for the GUI domain and this script's own daemon start, so the
|
|
110132
|
+
# daemon that is kept up is the one the wrapper bridges to.
|
|
110133
|
+
export CODEX_HOME="$CODEX_HOME_DIR"
|
|
110134
|
+
ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|
|
110135
|
+
{
|
|
110136
|
+
echo "$(ts) start"
|
|
110137
|
+
if [[ ! -x "$WRAPPER" ]]; then
|
|
110138
|
+
echo "$(ts) missing wrapper: $WRAPPER"
|
|
110139
|
+
exit 0
|
|
110140
|
+
fi
|
|
110141
|
+
# GUI domain setenv so ChatGPT.app inherits CODEX_CLI_PATH after login
|
|
110142
|
+
launchctl setenv CODEX_CLI_PATH "$WRAPPER"
|
|
110143
|
+
launchctl setenv CODEX_HOME "$CODEX_HOME_DIR"
|
|
110144
|
+
launchctl setenv CODEX_APP_SERVER_USE_LOCAL_DAEMON 1
|
|
110145
|
+
launchctl unsetenv CODEX_APP_SERVER_WS_URL 2>/dev/null || true
|
|
110146
|
+
echo "$(ts) CODEX_CLI_PATH=$(launchctl getenv CODEX_CLI_PATH)"
|
|
110147
|
+
if [[ -x "$REAL" ]]; then
|
|
110148
|
+
"$REAL" app-server daemon start >/dev/null 2>&1 || true
|
|
110149
|
+
echo "$(ts) daemon start attempted"
|
|
110150
|
+
fi
|
|
110151
|
+
echo "$(ts) done"
|
|
110152
|
+
} >>"$LOG" 2>&1
|
|
110153
|
+
`;
|
|
110154
|
+
}
|
|
110155
|
+
function renderPlist({ envScriptPath, label = SHIM_LABEL }) {
|
|
110156
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
110157
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
110158
|
+
<plist version="1.0">
|
|
110159
|
+
<dict>
|
|
110160
|
+
\t<key>Label</key>
|
|
110161
|
+
\t<string>${label}</string>
|
|
110162
|
+
\t<key>ProgramArguments</key>
|
|
110163
|
+
\t<array>
|
|
110164
|
+
\t\t<string>/bin/bash</string>
|
|
110165
|
+
\t\t<string>${envScriptPath}</string>
|
|
110166
|
+
\t</array>
|
|
110167
|
+
\t<key>RunAtLoad</key>
|
|
110168
|
+
\t<true/>
|
|
110169
|
+
\t<key>LimitLoadToSessionType</key>
|
|
110170
|
+
\t<string>Aqua</string>
|
|
110171
|
+
</dict>
|
|
110172
|
+
</plist>
|
|
110173
|
+
`;
|
|
110174
|
+
}
|
|
110175
|
+
const defaultRunner = (file, args)=>{
|
|
110176
|
+
try {
|
|
110177
|
+
return spawnSync(file, args, {
|
|
110178
|
+
encoding: "utf8",
|
|
110179
|
+
timeout: 15000
|
|
110180
|
+
});
|
|
110181
|
+
} catch (error) {
|
|
110182
|
+
return {
|
|
110183
|
+
error,
|
|
110184
|
+
status: null
|
|
110185
|
+
};
|
|
110186
|
+
}
|
|
110187
|
+
};
|
|
110188
|
+
function runBestEffort(runner, warnings, what, file, args) {
|
|
110189
|
+
const out = runner(file, args);
|
|
110190
|
+
if (out && (out.error || typeof out.status === "number" && out.status !== 0)) {
|
|
110191
|
+
const detail = out.error && out.error.message || out.stderr && String(out.stderr).trim() || `exit ${out.status}`;
|
|
110192
|
+
warnings.push(`${what} failed (${detail}); continuing`);
|
|
110193
|
+
}
|
|
110194
|
+
return out;
|
|
110195
|
+
}
|
|
110196
|
+
function writeExecutable(path, content) {
|
|
110197
|
+
writeFileSync(path, content, {
|
|
110198
|
+
mode: 493
|
|
110199
|
+
});
|
|
110200
|
+
chmodSync(path, 493);
|
|
110201
|
+
}
|
|
110202
|
+
function isExecutable(path) {
|
|
110203
|
+
try {
|
|
110204
|
+
statSync(path);
|
|
110205
|
+
} catch {
|
|
110206
|
+
return false;
|
|
110207
|
+
}
|
|
110208
|
+
try {
|
|
110209
|
+
// X_OK without throwing: accessSync is clearer; stat mode bit check is sync-safe.
|
|
110210
|
+
return (statSync(path).mode & 73) !== 0;
|
|
110211
|
+
} catch {
|
|
110212
|
+
return false;
|
|
110213
|
+
}
|
|
110214
|
+
}
|
|
110215
|
+
function fileExists(path) {
|
|
110216
|
+
try {
|
|
110217
|
+
statSync(path);
|
|
110218
|
+
return true;
|
|
110219
|
+
} catch {
|
|
110220
|
+
return false;
|
|
110221
|
+
}
|
|
110222
|
+
}
|
|
110223
|
+
/**
|
|
110224
|
+
* Copy the wrapper + bridge + login env script out of the package into durable
|
|
110225
|
+
* ~/.codex paths (never a git checkout), then persist CODEX_CLI_PATH for the
|
|
110226
|
+
* macOS Aqua session via LaunchAgent. Idempotent.
|
|
110227
|
+
*/ function installDesktopShim({ env = process.env, home = userHomeDir(env), platform = process.platform, runner = defaultRunner } = {}) {
|
|
110228
|
+
const paths = defaultPaths({
|
|
110229
|
+
env,
|
|
110230
|
+
home
|
|
110231
|
+
});
|
|
110232
|
+
const warnings = [];
|
|
110233
|
+
mkdirSync(paths.binDir, {
|
|
110234
|
+
recursive: true
|
|
110235
|
+
});
|
|
110236
|
+
writeExecutable(paths.wrapperPath, renderWrapperScript(paths));
|
|
110237
|
+
writeFileSync(paths.bridgePath, BRIDGE_SOURCE.endsWith("\n") ? BRIDGE_SOURCE : `${BRIDGE_SOURCE}\n`, {
|
|
110238
|
+
mode: 420
|
|
110239
|
+
});
|
|
110240
|
+
writeExecutable(paths.envScriptPath, renderEnvScript(paths));
|
|
110241
|
+
let persisted = false;
|
|
110242
|
+
if (platform === "darwin") {
|
|
110243
|
+
mkdirSync(paths.launchAgentsDir, {
|
|
110244
|
+
recursive: true
|
|
110245
|
+
});
|
|
110246
|
+
writeFileSync(paths.plistPath, renderPlist({
|
|
110247
|
+
envScriptPath: paths.envScriptPath
|
|
110248
|
+
}), {
|
|
110249
|
+
mode: 420
|
|
110250
|
+
});
|
|
110251
|
+
const uid = typeof process.getuid === "function" ? process.getuid() : null;
|
|
110252
|
+
if (uid === null || uid === undefined) {
|
|
110253
|
+
warnings.push("could not determine uid; LaunchAgent file written but not bootstrapped — log out/in or bootstrap it manually");
|
|
110254
|
+
} else {
|
|
110255
|
+
const target = `gui/${uid}/${paths.label}`;
|
|
110256
|
+
runBestEffort(runner, warnings, "launchctl bootout (previous agent)", "launchctl", [
|
|
110257
|
+
"bootout",
|
|
110258
|
+
target
|
|
110259
|
+
]);
|
|
110260
|
+
runBestEffort(runner, warnings, "launchctl bootstrap", "launchctl", [
|
|
110261
|
+
"bootstrap",
|
|
110262
|
+
`gui/${uid}`,
|
|
110263
|
+
paths.plistPath
|
|
110264
|
+
]);
|
|
110265
|
+
}
|
|
110266
|
+
runBestEffort(runner, warnings, "launchctl setenv CODEX_CLI_PATH", "launchctl", [
|
|
110267
|
+
"setenv",
|
|
110268
|
+
"CODEX_CLI_PATH",
|
|
110269
|
+
paths.wrapperPath
|
|
110270
|
+
]);
|
|
110271
|
+
runBestEffort(runner, warnings, "launchctl setenv CODEX_APP_SERVER_USE_LOCAL_DAEMON", "launchctl", [
|
|
110272
|
+
"setenv",
|
|
110273
|
+
"CODEX_APP_SERVER_USE_LOCAL_DAEMON",
|
|
110274
|
+
"1"
|
|
110275
|
+
]);
|
|
110276
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_APP_SERVER_WS_URL", "launchctl", [
|
|
110277
|
+
"unsetenv",
|
|
110278
|
+
"CODEX_APP_SERVER_WS_URL"
|
|
110279
|
+
]);
|
|
110280
|
+
persisted = true;
|
|
110281
|
+
} else {
|
|
110282
|
+
warnings.push("LaunchAgent persistence is macOS-only; wrapper and bridge installed — export CODEX_CLI_PATH manually");
|
|
110283
|
+
}
|
|
110284
|
+
if (isExecutable(paths.realPath)) {
|
|
110285
|
+
runBestEffort(runner, warnings, "codex app-server daemon start", paths.realPath, [
|
|
110286
|
+
"app-server",
|
|
110287
|
+
"daemon",
|
|
110288
|
+
"start"
|
|
110289
|
+
]);
|
|
110290
|
+
} else {
|
|
110291
|
+
warnings.push(`managed daemon not started: no executable at ${paths.realPath}`);
|
|
110292
|
+
}
|
|
110293
|
+
return {
|
|
110294
|
+
action: "install",
|
|
110295
|
+
bridgePath: paths.bridgePath,
|
|
110296
|
+
envScriptPath: paths.envScriptPath,
|
|
110297
|
+
exitCode: 0,
|
|
110298
|
+
persisted,
|
|
110299
|
+
plistPath: platform === "darwin" ? paths.plistPath : null,
|
|
110300
|
+
realPath: paths.realPath,
|
|
110301
|
+
warnings,
|
|
110302
|
+
wrapperPath: paths.wrapperPath
|
|
110303
|
+
};
|
|
110304
|
+
}
|
|
110305
|
+
/** 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 } = {}) {
|
|
110306
|
+
const paths = defaultPaths({
|
|
110307
|
+
env,
|
|
110308
|
+
home
|
|
110309
|
+
});
|
|
110310
|
+
const warnings = [];
|
|
110311
|
+
const removed = [];
|
|
110312
|
+
for (const path of [
|
|
110313
|
+
paths.wrapperPath,
|
|
110314
|
+
paths.bridgePath,
|
|
110315
|
+
paths.envScriptPath
|
|
110316
|
+
]){
|
|
110317
|
+
const existed = fileExists(path);
|
|
110318
|
+
try {
|
|
110319
|
+
if (rmSync(path, {
|
|
110320
|
+
force: true
|
|
110321
|
+
}) === undefined && fileExists(path)) warnings.push(`could not remove ${path}`);
|
|
110322
|
+
else if (existed && !fileExists(path)) removed.push(path);
|
|
110323
|
+
} catch (error) {
|
|
110324
|
+
warnings.push(`could not remove ${path} (${error instanceof Error ? error.message : String(error)})`);
|
|
110325
|
+
}
|
|
110326
|
+
}
|
|
110327
|
+
let plistRemoved = false;
|
|
110328
|
+
if (platform === "darwin") {
|
|
110329
|
+
const uid = typeof process.getuid === "function" ? process.getuid() : null;
|
|
110330
|
+
if (uid !== null && uid !== undefined) {
|
|
110331
|
+
runBestEffort(runner, warnings, "launchctl bootout", "launchctl", [
|
|
110332
|
+
"bootout",
|
|
110333
|
+
`gui/${uid}/${paths.label}`
|
|
110334
|
+
]);
|
|
110335
|
+
}
|
|
110336
|
+
try {
|
|
110337
|
+
rmSync(paths.plistPath, {
|
|
110338
|
+
force: true
|
|
110339
|
+
});
|
|
110340
|
+
plistRemoved = !fileExists(paths.plistPath);
|
|
110341
|
+
} catch (error) {
|
|
110342
|
+
warnings.push(`could not remove ${paths.plistPath} (${error instanceof Error ? error.message : String(error)})`);
|
|
110343
|
+
}
|
|
110344
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_CLI_PATH", "launchctl", [
|
|
110345
|
+
"unsetenv",
|
|
110346
|
+
"CODEX_CLI_PATH"
|
|
110347
|
+
]);
|
|
110348
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_HOME", "launchctl", [
|
|
110349
|
+
"unsetenv",
|
|
110350
|
+
"CODEX_HOME"
|
|
110351
|
+
]);
|
|
110352
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_APP_SERVER_USE_LOCAL_DAEMON", "launchctl", [
|
|
110353
|
+
"unsetenv",
|
|
110354
|
+
"CODEX_APP_SERVER_USE_LOCAL_DAEMON"
|
|
110355
|
+
]);
|
|
110356
|
+
runBestEffort(runner, warnings, "launchctl unsetenv CODEX_APP_SERVER_WS_URL", "launchctl", [
|
|
110357
|
+
"unsetenv",
|
|
110358
|
+
"CODEX_APP_SERVER_WS_URL"
|
|
110359
|
+
]);
|
|
110360
|
+
}
|
|
110361
|
+
return {
|
|
110362
|
+
action: "uninstall",
|
|
110363
|
+
exitCode: 0,
|
|
110364
|
+
plistPath: platform === "darwin" ? paths.plistPath : null,
|
|
110365
|
+
plistRemoved,
|
|
110366
|
+
removed,
|
|
110367
|
+
warnings,
|
|
110368
|
+
wrapperPath: paths.wrapperPath
|
|
110369
|
+
};
|
|
110370
|
+
}
|
|
110371
|
+
function socketStateOf(path) {
|
|
110372
|
+
try {
|
|
110373
|
+
return statSync(path).isSocket() ? "socket" : "not-a-socket";
|
|
110374
|
+
} catch (error) {
|
|
110375
|
+
return error && (error.code === "EACCES" || error.code === "EPERM") ? "permission-denied" : "absent";
|
|
110376
|
+
}
|
|
110377
|
+
}
|
|
110378
|
+
/**
|
|
110379
|
+
* Inspect the shim without touching Desktop, pipes, or sockets beyond a stat.
|
|
110380
|
+
* On macOS the Desktop-facing CODEX_CLI_PATH lives in launchd's GUI domain,
|
|
110381
|
+
* which a shell-spawned `gbot` does not inherit — so status queries
|
|
110382
|
+
* `launchctl getenv` there (via the injectable runner) and reports the caller
|
|
110383
|
+
* environment separately. Elsewhere the process env is the whole story.
|
|
110384
|
+
*/ function desktopShimStatus({ env = process.env, home = userHomeDir(env), platform = process.platform, runner = defaultRunner } = {}) {
|
|
110385
|
+
const paths = defaultPaths({
|
|
110386
|
+
env,
|
|
110387
|
+
home
|
|
110388
|
+
});
|
|
110389
|
+
const warnings = [];
|
|
110390
|
+
const wrapperPresent = fileExists(paths.wrapperPath);
|
|
110391
|
+
const bridgePresent = fileExists(paths.bridgePath);
|
|
110392
|
+
const envScriptPresent = fileExists(paths.envScriptPath);
|
|
110393
|
+
const plistPresent = platform === "darwin" ? fileExists(paths.plistPath) : false;
|
|
110394
|
+
const cliPath = env.CODEX_CLI_PATH || null;
|
|
110395
|
+
let guiCliPath = null;
|
|
110396
|
+
if (platform === "darwin") {
|
|
110397
|
+
try {
|
|
110398
|
+
const out = runner("launchctl", [
|
|
110399
|
+
"getenv",
|
|
110400
|
+
"CODEX_CLI_PATH"
|
|
110401
|
+
]);
|
|
110402
|
+
const value = out && typeof out.stdout === "string" ? out.stdout.trim() : "";
|
|
110403
|
+
guiCliPath = value || null;
|
|
110404
|
+
if (out && (out.error || typeof out.status === "number" && out.status !== 0)) {
|
|
110405
|
+
warnings.push("launchctl getenv CODEX_CLI_PATH failed; GUI-domain state unknown");
|
|
110406
|
+
guiCliPath = null;
|
|
110407
|
+
}
|
|
110408
|
+
} catch (error) {
|
|
110409
|
+
warnings.push(`launchctl getenv CODEX_CLI_PATH failed (${error instanceof Error ? error.message : String(error)})`);
|
|
110410
|
+
guiCliPath = null;
|
|
110411
|
+
}
|
|
110412
|
+
}
|
|
110413
|
+
// Desktop-facing value: the GUI domain on macOS, the caller env elsewhere.
|
|
110414
|
+
const desktopCliPath = platform === "darwin" ? guiCliPath : cliPath;
|
|
110415
|
+
const installed = wrapperPresent && isExecutable(paths.wrapperPath) && bridgePresent;
|
|
110416
|
+
// Effective socket, resolved exactly like gbot's own client (CODEX_APP_SERVER_SOCK
|
|
110417
|
+
// wins, else the install-time CODEX_HOME) so status and send/queue/status never
|
|
110418
|
+
// disagree. Inlined here so codex-bridge can reuse desktopShimStatus without a cycle.
|
|
110419
|
+
const socketPath = env.CODEX_APP_SERVER_SOCK || join(paths.codexHome, "app-server-control", "app-server-control.sock");
|
|
110420
|
+
return {
|
|
110421
|
+
action: "status",
|
|
110422
|
+
bridgePath: paths.bridgePath,
|
|
110423
|
+
bridgePresent,
|
|
110424
|
+
cliPath,
|
|
110425
|
+
codexHome: paths.codexHome,
|
|
110426
|
+
desktopCliPath,
|
|
110427
|
+
envScriptPath: paths.envScriptPath,
|
|
110428
|
+
envScriptPresent,
|
|
110429
|
+
exitCode: installed ? 0 : 1,
|
|
110430
|
+
guiCliPath,
|
|
110431
|
+
installed,
|
|
110432
|
+
persisted: platform === "darwin" ? plistPresent : null,
|
|
110433
|
+
platform,
|
|
110434
|
+
plistPath: platform === "darwin" ? paths.plistPath : null,
|
|
110435
|
+
plistPresent,
|
|
110436
|
+
realPath: paths.realPath,
|
|
110437
|
+
socketPath,
|
|
110438
|
+
socketSource: env.CODEX_APP_SERVER_SOCK ? "CODEX_APP_SERVER_SOCK" : "CODEX_HOME",
|
|
110439
|
+
socketState: socketStateOf(socketPath),
|
|
110440
|
+
warnings,
|
|
110441
|
+
wrapperExecutable: wrapperPresent && isExecutable(paths.wrapperPath),
|
|
110442
|
+
wrapperPath: paths.wrapperPath,
|
|
110443
|
+
wrapperPointsAtShim: desktopCliPath === paths.wrapperPath,
|
|
110444
|
+
wrapperPresent
|
|
110445
|
+
};
|
|
110446
|
+
}
|
|
110447
|
+
|
|
110448
|
+
|
|
106551
110449
|
},
|
|
106552
110450
|
"./src/core/gateway.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
106553
110451
|
/* import */ var node_crypto__rspack_import_0 = __webpack_require__("node:crypto");
|
|
@@ -106571,20 +110469,33 @@ class GatewayError extends Error {
|
|
|
106571
110469
|
// ponytail: fixed 30 s deadline and buffered byte cap; upgrade path is per-method budgets plus streaming reads.
|
|
106572
110470
|
const GATEWAY_TIMEOUT_MS = 30000;
|
|
106573
110471
|
const GATEWAY_MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
110472
|
+
function assertGatewayActive(signal) {
|
|
110473
|
+
if (signal?.aborted) {
|
|
110474
|
+
const error = new GatewayError("Gateway submission cancelled before transmission");
|
|
110475
|
+
error.delivery = "rejected";
|
|
110476
|
+
error.reason = "cancelled";
|
|
110477
|
+
throw error;
|
|
110478
|
+
}
|
|
110479
|
+
}
|
|
110480
|
+
function gatewayDeadline(signal) {
|
|
110481
|
+
const timeout = AbortSignal.timeout(GATEWAY_TIMEOUT_MS);
|
|
110482
|
+
return signal ? AbortSignal.any([
|
|
110483
|
+
signal,
|
|
110484
|
+
timeout
|
|
110485
|
+
]) : timeout;
|
|
110486
|
+
}
|
|
106574
110487
|
function backendBase() {
|
|
106575
|
-
return (process.env.
|
|
110488
|
+
return (process.env.CURSOR_API_BASE_URL || "https://api2.cursor.sh").replace(/\/$/, "");
|
|
106576
110489
|
}
|
|
106577
110490
|
function accessTokenFromEnv() {
|
|
106578
|
-
return (process.env.CURSOR_ACCESS_TOKEN ||
|
|
110491
|
+
return (process.env.CURSOR_ACCESS_TOKEN || "").trim();
|
|
106579
110492
|
}
|
|
106580
110493
|
function gatewayTokenFromEnv() {
|
|
106581
|
-
return (process.env.GROK_BOT_GATEWAY_TOKEN ||
|
|
110494
|
+
return (process.env.GROK_BOT_GATEWAY_TOKEN || "").trim();
|
|
106582
110495
|
}
|
|
106583
110496
|
function gatewayOverride() {
|
|
106584
110497
|
const token = gatewayTokenFromEnv();
|
|
106585
|
-
const
|
|
106586
|
-
const localUrl = token ? "http://127.0.0.1:" + (process.env.SAND_HOST_PORT || "1340") : "";
|
|
106587
|
-
const url = explicitUrl || localUrl;
|
|
110498
|
+
const url = (process.env.GROK_BOT_GATEWAY_URL || "").trim();
|
|
106588
110499
|
if (url && token) {
|
|
106589
110500
|
return {
|
|
106590
110501
|
gatewayUrl: (0,_url_policy_js__rspack_import_3/* .assertAllowedCredentialUrl */.Re)(url.replace(/\/$/, ""), {
|
|
@@ -106661,18 +110572,26 @@ function pick(obj, ...keys) {
|
|
|
106661
110572
|
}
|
|
106662
110573
|
return undefined;
|
|
106663
110574
|
}
|
|
106664
|
-
async function ensureSandbox(accessToken) {
|
|
110575
|
+
async function ensureSandbox(accessToken, { signal } = {}) {
|
|
110576
|
+
assertGatewayActive(signal);
|
|
106665
110577
|
const url = (0,_url_policy_js__rspack_import_3/* .assertAllowedCredentialUrl */.Re)(backendBase(), {
|
|
106666
110578
|
kind: "backend"
|
|
106667
110579
|
}) + "/aiserver.v1.GrokBotService/EnsureSandBox";
|
|
106668
|
-
|
|
106669
|
-
|
|
106670
|
-
|
|
106671
|
-
|
|
106672
|
-
|
|
106673
|
-
|
|
106674
|
-
|
|
106675
|
-
|
|
110580
|
+
let res, body;
|
|
110581
|
+
try {
|
|
110582
|
+
res = await fetch(url, {
|
|
110583
|
+
method: "POST",
|
|
110584
|
+
redirect: "error",
|
|
110585
|
+
signal: gatewayDeadline(signal),
|
|
110586
|
+
headers: (0,_headers_js__rspack_import_4/* .ensureSandboxHeaders */._6)(accessToken),
|
|
110587
|
+
body: "{}"
|
|
110588
|
+
});
|
|
110589
|
+
body = await readJson(res);
|
|
110590
|
+
} catch (error) {
|
|
110591
|
+
assertGatewayActive(signal);
|
|
110592
|
+
throw error;
|
|
110593
|
+
}
|
|
110594
|
+
assertGatewayActive(signal);
|
|
106676
110595
|
if (!res.ok) {
|
|
106677
110596
|
const detail = body.message || body.error || body.raw || res.statusText;
|
|
106678
110597
|
throw new GatewayError("EnsureSandBox failed: " + res.status + " " + (0,_url_policy_js__rspack_import_3/* .redactSecrets */.fp)(detail), {
|
|
@@ -106693,7 +110612,8 @@ async function ensureSandbox(accessToken) {
|
|
|
106693
110612
|
gatewayHeaders: (0,_headers_js__rspack_import_4/* .mergeGatewayHeaders */.bQ)((0,_headers_js__rspack_import_4/* .headersFromEnsureSandbox */.Ew)(body), (0,_headers_js__rspack_import_4/* .headersFromEnv */.gx)())
|
|
106694
110613
|
};
|
|
106695
110614
|
}
|
|
106696
|
-
async function connectGateway() {
|
|
110615
|
+
async function connectGateway({ signal } = {}) {
|
|
110616
|
+
assertGatewayActive(signal);
|
|
106697
110617
|
const override = gatewayOverride();
|
|
106698
110618
|
if (override) return override;
|
|
106699
110619
|
const fromApp = sessionFromApp();
|
|
@@ -106702,21 +110622,36 @@ async function connectGateway() {
|
|
|
106702
110622
|
if (!token) {
|
|
106703
110623
|
throw new GatewayError("Set CURSOR_ACCESS_TOKEN, or GROK_BOT_GATEWAY_URL + GROK_BOT_GATEWAY_TOKEN. Do not use a Cursor dashboard API key.");
|
|
106704
110624
|
}
|
|
106705
|
-
return ensureSandbox(token
|
|
110625
|
+
return ensureSandbox(token, {
|
|
110626
|
+
signal
|
|
110627
|
+
});
|
|
106706
110628
|
}
|
|
106707
|
-
async function gatewayCall(session, method, body = {}) {
|
|
110629
|
+
async function gatewayCall(session, method, body = {}, { signal } = {}) {
|
|
110630
|
+
assertGatewayActive(signal);
|
|
106708
110631
|
const base = (0,_url_policy_js__rspack_import_3/* .assertAllowedCredentialUrl */.Re)(session.gatewayUrl, {
|
|
106709
110632
|
kind: "gateway"
|
|
106710
110633
|
});
|
|
106711
110634
|
const url = base + "/api/" + method;
|
|
106712
|
-
|
|
110635
|
+
// Cancellation can abort read/auth preflights. Once a prompt request starts,
|
|
110636
|
+
// observe its actual receipt (or timeout) instead of losing certainty on stop.
|
|
110637
|
+
const prompt = method === "sendPrompt";
|
|
110638
|
+
const options = {
|
|
106713
110639
|
method: "POST",
|
|
106714
110640
|
redirect: "error",
|
|
106715
|
-
signal:
|
|
110641
|
+
signal: gatewayDeadline(prompt ? undefined : signal),
|
|
106716
110642
|
headers: (0,_headers_js__rspack_import_4/* .requestHeaders */.A1)(session),
|
|
106717
110643
|
body: JSON.stringify(body)
|
|
106718
|
-
}
|
|
106719
|
-
|
|
110644
|
+
};
|
|
110645
|
+
assertGatewayActive(signal); // Final synchronous boundary before transmission.
|
|
110646
|
+
let res, data;
|
|
110647
|
+
try {
|
|
110648
|
+
res = await fetch(url, options);
|
|
110649
|
+
data = await readJson(res);
|
|
110650
|
+
} catch (error) {
|
|
110651
|
+
if (!prompt) assertGatewayActive(signal);
|
|
110652
|
+
throw error;
|
|
110653
|
+
}
|
|
110654
|
+
if (!prompt) assertGatewayActive(signal);
|
|
106720
110655
|
if (!res.ok) {
|
|
106721
110656
|
const detail = data.message || data.error || data.raw || res.statusText;
|
|
106722
110657
|
throw new GatewayError(method + " failed: " + res.status + " " + (0,_url_policy_js__rspack_import_3/* .redactSecrets */.fp)(String(detail).slice(0, 300)), {
|
|
@@ -106768,8 +110703,10 @@ function unwrapList(data) {
|
|
|
106768
110703
|
function unwrapOne(data) {
|
|
106769
110704
|
return asRecord(data.agent || data);
|
|
106770
110705
|
}
|
|
106771
|
-
async function listAgents(session) {
|
|
106772
|
-
const data = await gatewayCall(session, "listAgents", {}
|
|
110706
|
+
async function listAgents(session, { signal } = {}) {
|
|
110707
|
+
const data = await gatewayCall(session, "listAgents", {}, {
|
|
110708
|
+
signal
|
|
110709
|
+
});
|
|
106773
110710
|
return unwrapList(data).map(asRecord).filter((r)=>r && r.id);
|
|
106774
110711
|
}
|
|
106775
110712
|
function resolveFromList(records, ref) {
|
|
@@ -106781,8 +110718,10 @@ function resolveFromList(records, ref) {
|
|
|
106781
110718
|
if (matches.length === 0) throw new GatewayError("No bot or group named \"" + ref + "\"");
|
|
106782
110719
|
throw new GatewayError("Ambiguous name \"" + ref + "\"");
|
|
106783
110720
|
}
|
|
106784
|
-
async function resolveRef(session, ref) {
|
|
106785
|
-
return resolveFromList(await listAgents(session
|
|
110721
|
+
async function resolveRef(session, ref, { signal } = {}) {
|
|
110722
|
+
return resolveFromList(await listAgents(session, {
|
|
110723
|
+
signal
|
|
110724
|
+
}), ref);
|
|
106786
110725
|
}
|
|
106787
110726
|
async function createAgent(session, input) {
|
|
106788
110727
|
const data = await gatewayCall(session, "createAgent", {
|
|
@@ -106905,7 +110844,10 @@ async function removeGroupMember(session, groupRef, memberRef) {
|
|
|
106905
110844
|
return setGroupMembers(session, group.id, next);
|
|
106906
110845
|
}
|
|
106907
110846
|
async function sendPrompt(session, ref, prompt, extra = {}) {
|
|
106908
|
-
|
|
110847
|
+
assertGatewayActive(extra.signal);
|
|
110848
|
+
const rec = await resolveRef(session, ref, {
|
|
110849
|
+
signal: extra.signal
|
|
110850
|
+
});
|
|
106909
110851
|
const body = {
|
|
106910
110852
|
agentId: rec.id,
|
|
106911
110853
|
prompt,
|
|
@@ -106914,7 +110856,9 @@ async function sendPrompt(session, ref, prompt, extra = {}) {
|
|
|
106914
110856
|
if (extra.replyToId) body.replyToId = extra.replyToId;
|
|
106915
110857
|
let data;
|
|
106916
110858
|
try {
|
|
106917
|
-
data = await gatewayCall(session, "sendPrompt", body
|
|
110859
|
+
data = await gatewayCall(session, "sendPrompt", body, {
|
|
110860
|
+
signal: extra.signal
|
|
110861
|
+
});
|
|
106918
110862
|
} catch (err) {
|
|
106919
110863
|
// Delivery states: the server answered no (rejected) vs the request may have landed (unknown).
|
|
106920
110864
|
// Never retry an unknown delivery blindly; read the thread first.
|
|
@@ -107035,6 +110979,268 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
107035
110979
|
});
|
|
107036
110980
|
|
|
107037
110981
|
|
|
110982
|
+
},
|
|
110983
|
+
"./src/core/relay/control.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
110984
|
+
/* import */ var node_string_decoder__rspack_import_0 = __webpack_require__("node:string_decoder");
|
|
110985
|
+
/* import */ var node_net__rspack_import_1 = __webpack_require__("node:net");
|
|
110986
|
+
/* import */ var node_crypto__rspack_import_2 = __webpack_require__("node:crypto");
|
|
110987
|
+
/* import */ var _profile_js__rspack_import_3 = __webpack_require__("./src/core/relay/profile.js");
|
|
110988
|
+
|
|
110989
|
+
|
|
110990
|
+
|
|
110991
|
+
|
|
110992
|
+
const RELAY_PROTOCOL = 1;
|
|
110993
|
+
const CONTROL_BYTES = 1024 * 1024;
|
|
110994
|
+
const CONTROL_TIMEOUT = 45000;
|
|
110995
|
+
function relayRequest(options, method, input = {}, { timeoutMs = CONTROL_TIMEOUT, signal, requestId = (0,node_crypto__rspack_import_2.randomUUID)() } = {}) {
|
|
110996
|
+
const { socketPath, profile } = (0,_profile_js__rspack_import_3/* .relayLocation */.hQ)(options);
|
|
110997
|
+
return new Promise((resolve, reject)=>{
|
|
110998
|
+
const decoder = new node_string_decoder__rspack_import_0.StringDecoder("utf8");
|
|
110999
|
+
let buffer = "", bytes = 0, settled = false, connected = false;
|
|
111000
|
+
const socket = (0,node_net__rspack_import_1.connect)(socketPath);
|
|
111001
|
+
const finish = (error, value)=>{
|
|
111002
|
+
if (settled) return;
|
|
111003
|
+
settled = true;
|
|
111004
|
+
clearTimeout(timer);
|
|
111005
|
+
signal?.removeEventListener("abort", abort);
|
|
111006
|
+
socket.destroy();
|
|
111007
|
+
error ? reject(error) : resolve(value);
|
|
111008
|
+
};
|
|
111009
|
+
const uncertain = ()=>Object.assign(Error(`Relay control connection lost; do not resend with a new requestId (${requestId}). Check bridge status.`), {
|
|
111010
|
+
requestId
|
|
111011
|
+
});
|
|
111012
|
+
const abort = ()=>finish(uncertain());
|
|
111013
|
+
const timer = setTimeout(abort, timeoutMs);
|
|
111014
|
+
signal?.addEventListener("abort", abort, {
|
|
111015
|
+
once: true
|
|
111016
|
+
});
|
|
111017
|
+
if (signal?.aborted) return abort();
|
|
111018
|
+
socket.on("error", (error)=>finish(connected ? uncertain() : error));
|
|
111019
|
+
socket.on("close", ()=>finish(uncertain()));
|
|
111020
|
+
socket.on("connect", ()=>{
|
|
111021
|
+
connected = true;
|
|
111022
|
+
const line = JSON.stringify({
|
|
111023
|
+
version: RELAY_PROTOCOL,
|
|
111024
|
+
profile,
|
|
111025
|
+
requestId,
|
|
111026
|
+
method,
|
|
111027
|
+
input
|
|
111028
|
+
}) + "\n";
|
|
111029
|
+
if (Buffer.byteLength(line) > CONTROL_BYTES) return finish(Error("Relay control request exceeds budget"));
|
|
111030
|
+
socket.write(line);
|
|
111031
|
+
});
|
|
111032
|
+
socket.on("data", (chunk)=>{
|
|
111033
|
+
bytes += chunk.length;
|
|
111034
|
+
if (bytes > CONTROL_BYTES) return finish(Error("Relay control response exceeds budget"));
|
|
111035
|
+
buffer += decoder.write(chunk);
|
|
111036
|
+
const end = buffer.indexOf("\n");
|
|
111037
|
+
if (end < 0) return;
|
|
111038
|
+
try {
|
|
111039
|
+
const reply = JSON.parse(buffer.slice(0, end));
|
|
111040
|
+
if (reply.version !== RELAY_PROTOCOL || reply.requestId !== requestId) throw Error("Relay protocol identity mismatch");
|
|
111041
|
+
if (reply.error) throw Error(reply.error);
|
|
111042
|
+
if (reply.profile !== profile) throw Error("Relay profile mismatch");
|
|
111043
|
+
finish(null, reply.result);
|
|
111044
|
+
} catch (error) {
|
|
111045
|
+
finish(error);
|
|
111046
|
+
}
|
|
111047
|
+
});
|
|
111048
|
+
});
|
|
111049
|
+
}
|
|
111050
|
+
|
|
111051
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
111052
|
+
lJ: () => (relayRequest)
|
|
111053
|
+
});
|
|
111054
|
+
|
|
111055
|
+
|
|
111056
|
+
},
|
|
111057
|
+
"./src/core/relay/managed.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
111058
|
+
/* import */ var node_child_process__rspack_import_0 = __webpack_require__("node:child_process");
|
|
111059
|
+
/* import */ var node_fs_promises__rspack_import_1 = __webpack_require__("node:fs/promises");
|
|
111060
|
+
/* import */ var node_path__rspack_import_2 = __webpack_require__("node:path");
|
|
111061
|
+
/* import */ var node_url__rspack_import_3 = __webpack_require__("node:url");
|
|
111062
|
+
/* import */ var node_crypto__rspack_import_4 = __webpack_require__("node:crypto");
|
|
111063
|
+
/* import */ var _profile_js__rspack_import_5 = __webpack_require__("./src/core/relay/profile.js");
|
|
111064
|
+
/* import */ var _control_js__rspack_import_6 = __webpack_require__("./src/core/relay/control.js");
|
|
111065
|
+
|
|
111066
|
+
|
|
111067
|
+
|
|
111068
|
+
|
|
111069
|
+
|
|
111070
|
+
|
|
111071
|
+
|
|
111072
|
+
/** @param {{pluginRoot?: string, moduleUrl?: string}} options */ async function resolveRelayWorker({ pluginRoot, moduleUrl = import.meta.url } = {}) {
|
|
111073
|
+
const roots = [];
|
|
111074
|
+
if (pluginRoot) roots.push(pluginRoot);
|
|
111075
|
+
let path = (0,node_path__rspack_import_2.dirname)((0,node_url__rspack_import_3.fileURLToPath)(moduleUrl));
|
|
111076
|
+
for(let i = 0; i < 5; i++){
|
|
111077
|
+
roots.push(path);
|
|
111078
|
+
path = (0,node_path__rspack_import_2.dirname)(path);
|
|
111079
|
+
}
|
|
111080
|
+
for (const candidate of new Set(roots)){
|
|
111081
|
+
let manifest;
|
|
111082
|
+
try {
|
|
111083
|
+
manifest = JSON.parse(await (0,node_fs_promises__rspack_import_1.readFile)((0,node_path__rspack_import_2.join)(candidate, "agent-bundle.manifest.json"), "utf8"));
|
|
111084
|
+
} catch (error) {
|
|
111085
|
+
if (error.code === "ENOENT") continue;
|
|
111086
|
+
throw error;
|
|
111087
|
+
}
|
|
111088
|
+
const relative = "scripts/gbot-relay.mjs";
|
|
111089
|
+
const file = manifest.files?.find((f)=>f.path === relative);
|
|
111090
|
+
if (manifest.application?.name !== "gbot" || !file || !manifest.executables?.scripts?.some((s)=>s.path === relative)) continue;
|
|
111091
|
+
const root = await (0,node_fs_promises__rspack_import_1.realpath)(candidate), worker = (0,node_path__rspack_import_2.join)(root, relative), stat = await (0,node_fs_promises__rspack_import_1.lstat)(worker);
|
|
111092
|
+
if (!stat.isFile() || stat.isSymbolicLink() || await (0,node_fs_promises__rspack_import_1.realpath)(worker) !== worker) throw Error("Relay worker must be a regular packaged script");
|
|
111093
|
+
if (stat.size !== file.bytes || (0,_profile_js__rspack_import_5/* .digest */.br)(await (0,node_fs_promises__rspack_import_1.readFile)(worker)) !== file.sha256) throw Error("Packaged relay worker checksum mismatch");
|
|
111094
|
+
return worker;
|
|
111095
|
+
}
|
|
111096
|
+
throw Error("Packaged relay worker not found; rebuild or reinstall the plugin");
|
|
111097
|
+
}
|
|
111098
|
+
const unavailable = (error)=>[
|
|
111099
|
+
"ENOENT",
|
|
111100
|
+
"ECONNREFUSED"
|
|
111101
|
+
].includes(error.code);
|
|
111102
|
+
async function ensureRelayWorker(options = {}) {
|
|
111103
|
+
const location = (0,_profile_js__rspack_import_5/* .relayLocation */.hQ)(options);
|
|
111104
|
+
try {
|
|
111105
|
+
return await (0,_control_js__rspack_import_6/* .relayRequest */.lJ)(location, "hello", {}, {
|
|
111106
|
+
timeoutMs: 1500
|
|
111107
|
+
});
|
|
111108
|
+
} catch (error) {
|
|
111109
|
+
if (!unavailable(error)) throw error;
|
|
111110
|
+
}
|
|
111111
|
+
const workerPath = await resolveRelayWorker(options);
|
|
111112
|
+
const child = (0,node_child_process__rspack_import_0.spawn)(process.execPath, [
|
|
111113
|
+
workerPath
|
|
111114
|
+
], {
|
|
111115
|
+
detached: true,
|
|
111116
|
+
stdio: "ignore",
|
|
111117
|
+
env: {
|
|
111118
|
+
...location.env,
|
|
111119
|
+
GROK_BOT_RELAY_DIR: location.stateDir
|
|
111120
|
+
},
|
|
111121
|
+
cwd: (0,node_path__rspack_import_2.dirname)(workerPath)
|
|
111122
|
+
});
|
|
111123
|
+
let spawnError;
|
|
111124
|
+
child.on("error", (error)=>{
|
|
111125
|
+
spawnError = error;
|
|
111126
|
+
});
|
|
111127
|
+
child.unref();
|
|
111128
|
+
const end = Date.now() + 10000;
|
|
111129
|
+
while(Date.now() < end){
|
|
111130
|
+
if (spawnError) throw spawnError;
|
|
111131
|
+
if (options.signal?.aborted) throw Error("Relay startup cancelled before submission");
|
|
111132
|
+
try {
|
|
111133
|
+
return await (0,_control_js__rspack_import_6/* .relayRequest */.lJ)(location, "hello", {}, {
|
|
111134
|
+
timeoutMs: 1000,
|
|
111135
|
+
signal: options.signal
|
|
111136
|
+
});
|
|
111137
|
+
} catch (error) {
|
|
111138
|
+
if (!unavailable(error)) throw error;
|
|
111139
|
+
}
|
|
111140
|
+
await new Promise((resolve)=>setTimeout(resolve, 75));
|
|
111141
|
+
}
|
|
111142
|
+
throw Error("Relay worker startup failed or timed out; no untracked send was attempted. Inspect bridge status and the relay owner lock.");
|
|
111143
|
+
}
|
|
111144
|
+
async function managedOperation(method, input, options = {}) {
|
|
111145
|
+
const location = (0,_profile_js__rspack_import_5/* .relayLocation */.hQ)(options);
|
|
111146
|
+
const requestId = input.requestId ?? (0,node_crypto__rspack_import_4.randomUUID)();
|
|
111147
|
+
if (![
|
|
111148
|
+
"status",
|
|
111149
|
+
"stop",
|
|
111150
|
+
"respond"
|
|
111151
|
+
].includes(method)) await ensureRelayWorker(options);
|
|
111152
|
+
try {
|
|
111153
|
+
return await (0,_control_js__rspack_import_6/* .relayRequest */.lJ)(location, method, input, {
|
|
111154
|
+
signal: options.signal,
|
|
111155
|
+
requestId
|
|
111156
|
+
});
|
|
111157
|
+
} catch (error) {
|
|
111158
|
+
if (method === "status" && unavailable(error)) return {
|
|
111159
|
+
worker: {
|
|
111160
|
+
state: "stopped",
|
|
111161
|
+
profile: location.profile,
|
|
111162
|
+
supervised: false
|
|
111163
|
+
},
|
|
111164
|
+
reason: "Worker is not running. Start a route or tracked send to resume saved routes."
|
|
111165
|
+
};
|
|
111166
|
+
// Never retry a disconnected mutation. Its durable request ID is the recovery handle.
|
|
111167
|
+
throw error;
|
|
111168
|
+
}
|
|
111169
|
+
}
|
|
111170
|
+
|
|
111171
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
111172
|
+
Bb: () => (managedOperation)
|
|
111173
|
+
});
|
|
111174
|
+
|
|
111175
|
+
|
|
111176
|
+
},
|
|
111177
|
+
"./src/core/relay/profile.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
111178
|
+
/* import */ var node_crypto__rspack_import_0 = __webpack_require__("node:crypto");
|
|
111179
|
+
/* import */ var node_os__rspack_import_1 = __webpack_require__("node:os");
|
|
111180
|
+
/* import */ var node_path__rspack_import_2 = __webpack_require__("node:path");
|
|
111181
|
+
/* import */ var _codex_bridge_js__rspack_import_3 = __webpack_require__("./src/core/codex-bridge.js");
|
|
111182
|
+
/* import */ var _app_session_js__rspack_import_4 = __webpack_require__("./src/core/app-session.js");
|
|
111183
|
+
|
|
111184
|
+
|
|
111185
|
+
|
|
111186
|
+
|
|
111187
|
+
|
|
111188
|
+
const digest = (value)=>(0,node_crypto__rspack_import_0.createHash)("sha256").update(value).digest("hex");
|
|
111189
|
+
// Only explicit overrides are hashed. App-session token refresh retains its source identity.
|
|
111190
|
+
function relayProfile(env = process.env) {
|
|
111191
|
+
const keys = [
|
|
111192
|
+
"GROK_BOT_GATEWAY_URL",
|
|
111193
|
+
"SAND_HOST_GATEWAY_URL",
|
|
111194
|
+
"SAND_HOST_PORT",
|
|
111195
|
+
"GROK_BOT_GATEWAY_TOKEN",
|
|
111196
|
+
"SAND_HOST_GATEWAY_TOKEN",
|
|
111197
|
+
"SAND_GATEWAY_TOKEN",
|
|
111198
|
+
"CURSOR_ACCESS_TOKEN",
|
|
111199
|
+
"GROK_BOT_ACCESS_TOKEN",
|
|
111200
|
+
"SAND_ACCESS_TOKEN",
|
|
111201
|
+
"GROK_BOT_GATEWAY_HEADERS",
|
|
111202
|
+
"SAND_BACKEND_URL",
|
|
111203
|
+
"CURSOR_API_BASE_URL",
|
|
111204
|
+
"SAND_BOX_NAMESPACE",
|
|
111205
|
+
"SAND_CLIENT_VERSION",
|
|
111206
|
+
"GROK_BOT_CODEX_THREADS",
|
|
111207
|
+
"GROK_BOT_MAX_HOPS",
|
|
111208
|
+
"GROK_BOT_CODEX_EXPERIMENTAL",
|
|
111209
|
+
"GROK_BOT_ALLOW_LOCAL_GATEWAY",
|
|
111210
|
+
"GROK_BOT_ALLOW_ANY_GATEWAY",
|
|
111211
|
+
"GROK_BOT_TEST",
|
|
111212
|
+
"NODE_ENV"
|
|
111213
|
+
];
|
|
111214
|
+
return digest(JSON.stringify([
|
|
111215
|
+
(0,node_path__rspack_import_2.resolve)((0,_codex_bridge_js__rspack_import_3/* .codexSocketPath */.ql)(env)),
|
|
111216
|
+
(0,_app_session_js__rspack_import_4/* .grokBotGatewayDescriptorPath */.dQ)((0,node_os__rspack_import_1.homedir)(), process.platform, env),
|
|
111217
|
+
...keys.map((key)=>[
|
|
111218
|
+
key,
|
|
111219
|
+
env[key] ?? ""
|
|
111220
|
+
])
|
|
111221
|
+
]));
|
|
111222
|
+
}
|
|
111223
|
+
function relayLocation({ env = process.env, stateDir, profile = relayProfile(env) } = {}) {
|
|
111224
|
+
if (process.platform === "win32") throw Error("Codex relay requires Unix-domain sockets; Windows is unsupported.");
|
|
111225
|
+
const dir = (0,node_path__rspack_import_2.resolve)(stateDir ?? env.GROK_BOT_RELAY_DIR ?? (0,node_path__rspack_import_2.join)((0,node_os__rspack_import_1.homedir)(), ".grok-bot-cli", "relay", profile.slice(0, 24)));
|
|
111226
|
+
// macOS Unix sockets cannot use arbitrarily long installation/state paths.
|
|
111227
|
+
const socketDir = Buffer.byteLength((0,node_path__rspack_import_2.join)(dir, "control.sock")) < 100 ? dir : (0,node_path__rspack_import_2.join)("/tmp", `gbot-relay-${process.getuid()}`, digest(dir).slice(0, 24));
|
|
111228
|
+
return {
|
|
111229
|
+
stateDir: dir,
|
|
111230
|
+
profile,
|
|
111231
|
+
env,
|
|
111232
|
+
socketDir,
|
|
111233
|
+
socketPath: (0,node_path__rspack_import_2.join)(socketDir, "control.sock")
|
|
111234
|
+
};
|
|
111235
|
+
}
|
|
111236
|
+
|
|
111237
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
111238
|
+
hQ: () => (relayLocation)
|
|
111239
|
+
}, {
|
|
111240
|
+
br: digest
|
|
111241
|
+
});
|
|
111242
|
+
|
|
111243
|
+
|
|
107038
111244
|
},
|
|
107039
111245
|
"./src/core/store.js"(__unused_rspack___webpack_module__, __unused_rspack___webpack_exports__, __webpack_require__) {
|
|
107040
111246
|
/* import */ var node_crypto__rspack_import_0 = __webpack_require__("node:crypto");
|
|
@@ -107102,10 +111308,7 @@ function isUuid(value) {
|
|
|
107102
111308
|
function defaultCandidateRoots() {
|
|
107103
111309
|
const home = homedir();
|
|
107104
111310
|
const env = [
|
|
107105
|
-
process.env.GROK_BOT_AGENTS_DIR
|
|
107106
|
-
process.env.SAND_AGENTS_DIR,
|
|
107107
|
-
process.env.SAND_DATA_ROOT && join(process.env.SAND_DATA_ROOT, "agents"),
|
|
107108
|
-
process.env.SAND_DATA_ROOT && join(process.env.SAND_DATA_ROOT, "agent-data", "agents")
|
|
111311
|
+
process.env.GROK_BOT_AGENTS_DIR
|
|
107109
111312
|
].filter(Boolean);
|
|
107110
111313
|
return [
|
|
107111
111314
|
...env,
|
|
@@ -107365,7 +111568,6 @@ function removeGroupMember(root, groupRef, memberRef) {
|
|
|
107365
111568
|
|
|
107366
111569
|
},
|
|
107367
111570
|
"./src/core/transcript.js"(__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
107368
|
-
// Shared by `gbot thread` and the grok-bot plugin's gbot_thread tool.
|
|
107369
111571
|
/** Coerce anything to a string without throwing (numbers, BigInt, unserializable objects). */ function toSafeText(value) {
|
|
107370
111572
|
if (typeof value === "string") return value;
|
|
107371
111573
|
if (value == null) return "";
|
|
@@ -107403,15 +111605,12 @@ function entryTextRaw(e) {
|
|
|
107403
111605
|
return typeof e.preview === "string" ? e.preview : "";
|
|
107404
111606
|
}
|
|
107405
111607
|
function transcriptEntries(payload) {
|
|
107406
|
-
if (Array.isArray(payload)) return payload;
|
|
107407
111608
|
if (!payload || typeof payload !== "object") return [];
|
|
107408
|
-
|
|
107409
|
-
return Array.isArray(entries) ? entries : [];
|
|
111609
|
+
return Array.isArray(payload.entries) ? payload.entries : [];
|
|
107410
111610
|
}
|
|
107411
111611
|
function sourceEntryId(entry) {
|
|
107412
111612
|
if (!entry || typeof entry !== "object") return "";
|
|
107413
|
-
|
|
107414
|
-
return typeof entry.messageId === "string" ? entry.messageId : "";
|
|
111613
|
+
return typeof entry.id === "string" ? entry.id : "";
|
|
107415
111614
|
}
|
|
107416
111615
|
function lastSourceId(entries, fallback = "") {
|
|
107417
111616
|
for(let index = entries.length - 1; index >= 0; index -= 1){
|
|
@@ -107587,6 +111786,10 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
107587
111786
|
});
|
|
107588
111787
|
|
|
107589
111788
|
|
|
111789
|
+
},
|
|
111790
|
+
"./package.json"(module) {
|
|
111791
|
+
module.exports = {"rE":"0.6.0"}
|
|
111792
|
+
|
|
107590
111793
|
},
|
|
107591
111794
|
|
|
107592
111795
|
});
|