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.
@@ -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 `envelope` so outcome documents still classify the failure.
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/gbot_send.tsx"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
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 zod__rspack_import_3 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js");
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 inputSchema = zod__rspack_import_3/* .object */.Ikc({
11118
- message: zod__rspack_import_3/* .string */.YjP().min(1),
11119
- target: zod__rspack_import_3/* .string */.YjP().min(1)
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: 'Send a message to a Grok Bot bot or group by name or id, like `gbot send`. The bot answers asynchronously; read its reply later with gbot_thread.',
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
- message: {
11127
- description: 'Message text. Say who you are and what you need in the first line.',
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
- description: 'Bot or group name or id, for example "General".',
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
- type: 'object'
11140
- },
11141
- inputSchema,
11142
- resultSchema: zod__rspack_import_3/* .object */.Ikc({
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: 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: `Sent to ${value.target.kind} ${value.target.name} (${value.target.id})${messageId === undefined ? ' (no receipt; check the thread before resending)' : ` as ${messageId}`}. Read the reply with gbot_thread.`
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)(delta.entries);
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 _agent_bundle_runtime__rspack_import_5 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/49.js");
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 _agent_bundle_runtime_lineage__rspack_import_6 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/lineage.js");
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 _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_send_tsx__rspack_import_3 = __webpack_require__("./src/mcp/grok-bot/tools/gbot_send.tsx");
106195
- /* import */ var _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_thread_tsx__rspack_import_4 = __webpack_require__("./src/mcp/grok-bot/tools/gbot_thread.tsx");
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(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_send_tsx__rspack_import_3, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_send_tsx__rspack_import_3);
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(_home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_thread_tsx__rspack_import_4, 'default'), _home_runner_work_grok_bot_cli_grok_bot_cli_src_mcp_grok_bot_tools_gbot_thread_tsx__rspack_import_4);
106205
- const ARTIFACT_EPOCH = "gbot@0.4.5";
106206
- const pluginRoot = (0,_agent_bundle_runtime__rspack_import_5/* .resolvePluginRoot */.E7)({
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,_agent_bundle_runtime_lineage__rspack_import_6/* .createAgentLineageRegistry */.Q5)()
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
- "description": "Send a message to a Grok Bot bot or group by name or id, like `gbot send`. The bot answers asynchronously; read its reply later with gbot_thread.",
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
- "description": "Message text. Say who you are and what you need in the first line.",
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: route0,
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: route1,
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.4.5"
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.SAND_BACKEND_URL || process.env.CURSOR_API_BASE_URL || "https://api2.cursor.sh").replace(/\/$/, "");
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 || process.env.GROK_BOT_ACCESS_TOKEN || process.env.SAND_ACCESS_TOKEN || "").trim();
110491
+ return (process.env.CURSOR_ACCESS_TOKEN || "").trim();
106579
110492
  }
106580
110493
  function gatewayTokenFromEnv() {
106581
- return (process.env.GROK_BOT_GATEWAY_TOKEN || process.env.SAND_HOST_GATEWAY_TOKEN || process.env.SAND_GATEWAY_TOKEN || "").trim();
110494
+ return (process.env.GROK_BOT_GATEWAY_TOKEN || "").trim();
106582
110495
  }
106583
110496
  function gatewayOverride() {
106584
110497
  const token = gatewayTokenFromEnv();
106585
- const explicitUrl = (process.env.GROK_BOT_GATEWAY_URL || process.env.SAND_HOST_GATEWAY_URL || "").trim();
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
- const res = await fetch(url, {
106669
- method: "POST",
106670
- redirect: "error",
106671
- signal: AbortSignal.timeout(GATEWAY_TIMEOUT_MS),
106672
- headers: (0,_headers_js__rspack_import_4/* .ensureSandboxHeaders */._6)(accessToken),
106673
- body: "{}"
106674
- });
106675
- const body = await readJson(res);
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
- const res = await fetch(url, {
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: AbortSignal.timeout(GATEWAY_TIMEOUT_MS),
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
- const data = await readJson(res);
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), ref);
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
- const rec = await resolveRef(session, ref);
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
- const entries = payload.entries || payload.messages || payload.items;
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
- if (typeof entry.id === "string" && entry.id) return entry.id;
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
  });