From 83ccded7a9186794204596a7fda08d96b903f371 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:49:43 -0700 Subject: [PATCH 1/5] chore: add changeset for Codex sender prefix and thread search --- .changeset/codex-sender-prefix-thread-search.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/codex-sender-prefix-thread-search.md diff --git a/.changeset/codex-sender-prefix-thread-search.md b/.changeset/codex-sender-prefix-thread-search.md new file mode 100644 index 0000000..dc3135c --- /dev/null +++ b/.changeset/codex-sender-prefix-thread-search.md @@ -0,0 +1,5 @@ +--- +"grok-bot-cli": minor +--- + +Codex → Grok Bot messages now carry a sender prefix, `[from Codex thread @ , cwd ; reply: codex_send({threadId:"", message:"..."}) via MCP on (or CLI: gbot codex send "...")]`, on the managed relay path, the plain `gbot_send` path with a known native thread, and `gbot send` inside a Codex terminal (`$CODEX_THREAD_ID`); unknown fields are omitted. Relay return messages use the same prefix. `codex_threads` / `gbot codex list-threads` now sort by recent activity (`updatedAt`) by default (`sort`: `updated` | `created` | `recency`, `order`), and add `query` (case-insensitive name/title, preview or id prefix, scanning every page), `activeWithin` / `since`, `cwd`, `modelProvider`, `sourceKind` and `archived` filters, so old-but-active threads are no longer hidden past the first 100. From e89c166d637550b79cf7a898b426967017bcee4a Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:49:43 -0700 Subject: [PATCH 2/5] feat: prefix Codex->Grok messages with thread/machine/cwd/reply; sort, filter and search codex threads --- src/cli/codex/list-threads.tsx | 23 ++- src/cli/send.tsx | 7 +- src/core/codex-bridge.js | 151 +++++++++++++++--- src/core/codex/routes.ts | 32 +++- src/core/format.js | 5 +- src/core/relay/completion.js | 24 ++- src/core/relay/engine.js | 11 +- src/core/relay/routes.ts | 8 +- src/core/sender-prefix.js | 44 +++++ src/mcp/grok-bot/tools/codex_threads.tsx | 21 +-- src/skills/talk-to-grok-bot/SKILL.md | 14 ++ .../references/bridge-administration.md | 2 +- 12 files changed, 291 insertions(+), 51 deletions(-) create mode 100644 src/core/sender-prefix.js diff --git a/src/cli/codex/list-threads.tsx b/src/cli/codex/list-threads.tsx index 81588e3..72d5eda 100644 --- a/src/cli/codex/list-threads.tsx +++ b/src/cli/codex/list-threads.tsx @@ -6,10 +6,11 @@ import { listCodexThreads, singleLine } from '../../core/codex-bridge.js'; import { outcomeFromError } from '../../core/codex/contract.js'; import { formatCodexThread } from '../../core/format.js'; import { failureDocumentSchema } from '../_shared.js'; +import { threadsSchema } from '../../core/codex/routes.js'; export const config = { description: - 'List Codex daemon-managed threads (all modelProviders; pages via --cursor / nextCursor).', + 'List Codex daemon-managed threads, newest activity first (all modelProviders; pages via --cursor / nextCursor). Find old threads with --query (name/title/id prefix, all pages), --active-within 7d, --since, --sort created.', exitCode: 'result', inputJsonSchema: { additionalProperties: false, @@ -19,19 +20,28 @@ export const config = { type: 'string', }, limit: { default: 20, description: 'Max threads to list (1-200)', type: 'number' }, + sort: { default: 'updated', description: 'updated (last activity, default) | created | recency', enum: ['updated', 'created', 'recency'], type: 'string' }, + order: { default: 'desc', enum: ['desc', 'asc'], type: 'string' }, + query: { description: 'Case-insensitive substring of name/title, preview or id (id prefix works); scans every page', type: 'string' }, + activeWithin: { description: 'Only threads updated within 90s, 30m, 12h, 7d, 2w', type: 'string' }, + since: { description: 'Only threads updated at/after this ISO date/time or epoch seconds', type: 'string' }, + cwd: { description: 'Exact session cwd', type: 'string' }, + modelProvider: { description: 'Any modelProvider id; omit for all', type: 'string' }, + sourceKind: { description: 'Any app-server source kind; omit for interactive sources', type: 'string' }, + archived: { description: 'Archived threads only', type: 'boolean' }, }, type: 'object', }, } satisfies CliRouteConfig; -export const inputSchema = z.object({ - cursor: z.string().min(1).optional(), - limit: z.number().int().min(1).max(200).default(20), -}).strict(); +export const inputSchema = threadsSchema; export const resultSchema = z.union([ z.object({ exitCode: z.literal(0), limit: z.number().int().min(1).max(200), + sort: z.string().optional(), + order: z.string().optional(), + scanned: z.number().int().min(0).optional(), nextCursor: z.string().nullable(), threads: z.array(z.record(z.string(), z.json())), useStateDbOnly: z.boolean().optional(), @@ -42,7 +52,8 @@ export const resultSchema = z.union([ export default async function codexListThreads({ input }: CliRouteProps) { let out; try { - out = await listCodexThreads({ cursor: input.cursor, limit: input.limit }); + const { sourceKind, ...rest } = input; + out = await listCodexThreads({ ...rest, ...(sourceKind ? { sourceKinds: [sourceKind] } : {}) }); } catch (error) { const failure = outcomeFromError(error); return ( diff --git a/src/cli/send.tsx b/src/cli/send.tsx index df26fd8..83a0cd8 100644 --- a/src/cli/send.tsx +++ b/src/cli/send.tsx @@ -9,6 +9,7 @@ import { relayResultSchema, } from '../core/relay/routes.js'; import { buildEnvelope, withEnvelopeHeader } from '../core/codex-bridge.js'; +import { envCodexThreadId, withCodexSender } from '../core/sender-prefix.js'; import { outcomeFromError } from '../core/codex/contract.js'; import { saveHistory } from '../core/history.js'; import { @@ -111,9 +112,13 @@ const deliver = async ( }); const message = input.message.join(' ').trim(); const backend = await openBackendFromInput(input); + // Inside a Codex terminal ($CODEX_THREAD_ID is set) say which thread is asking and how to answer. const out = await backend.send( input.target, - withEnvelopeHeader(message, envelope), + withCodexSender(withEnvelopeHeader(message, envelope), { + threadId: envCodexThreadId(), + cwd: input.expectedCwd ?? process.cwd(), + }), ); saveHistory(out, { dir: input.historyDir, diff --git a/src/core/codex-bridge.js b/src/core/codex-bridge.js index 6ad8ff2..e689d58 100644 --- a/src/core/codex-bridge.js +++ b/src/core/codex-bridge.js @@ -882,14 +882,68 @@ function summarizeThread(t) { } const THREAD_LIST_MAX_LIMIT = 200; +// Daemon sort keys (ThreadSortKey in `codex app-server generate-json-schema`). The daemon's own +// default is created_at, which buries old-but-active threads, so gbot defaults to updated_at. +const THREAD_SORT_KEYS = { updated: "updated_at", created: "created_at", recency: "recency_at" }; +const GBOT_CURSOR = "gbot1:"; +const DURATION_MS = { s: 1000, m: 60_000, h: 3_600_000, d: 86_400_000, w: 604_800_000 }; + +const toSeconds = (value) => (value > 1e11 ? value / 1000 : value); + +/** `7d`, `12h`, `30m`, `2w`, `90s` -> milliseconds. */ +export function parseActiveWithin(text) { + const m = /^(\d+(?:\.\d+)?)\s*([smhdw])$/i.exec(String(text).trim()); + if (!m) throw new RangeError("--active-within must look like 30m, 12h, 7d or 2w"); + return Number(m[1]) * DURATION_MS[m[2].toLowerCase()]; +} + +/** ISO date/time or epoch (seconds or ms) -> epoch seconds. */ +export function parseSince(value) { + const text = String(value).trim(); + const n = /^\d+(?:\.\d+)?$/.test(text) ? toSeconds(Number(text)) : Date.parse(text) / 1000; + if (!Number.isFinite(n)) throw new RangeError("--since must be an ISO date/time or epoch seconds"); + return n; +} + +function encodeThreadCursor(state) { + return GBOT_CURSOR + Buffer.from(JSON.stringify(state)).toString("base64url"); +} +function decodeThreadCursor(cursor) { + if (cursor === undefined) return { skip: 0 }; + if (!cursor.startsWith(GBOT_CURSOR)) return { c: cursor, skip: 0 }; + try { + const v = JSON.parse(Buffer.from(cursor.slice(GBOT_CURSOR.length), "base64url").toString("utf8")); + if (isObject(v) && Number.isInteger(v.skip) && v.skip >= 0 && (v.c === undefined || typeof v.c === "string")) return { c: v.c, skip: v.skip }; + } catch { /* fall through */ } + throw new RangeError("--cursor is not a valid thread cursor"); +} /** - * @param {{ limit?: number, cursor?: string, modelProviders?: string[], env?: NodeJS.ProcessEnv }} [opts] + * List daemon threads. + * + * Server-side (dynamic, pass-through): sort key/direction, cwd, archived, source kinds, providers. + * Client-side, scanning page after page until `limit` matches or the daemon runs out (nothing is + * capped at the first page): `query` (case-insensitive substring of name/title, preview, or the + * id - so an id prefix works) and the recent-activity cutoff (`since` / `activeWithin`, compared + * with `updatedAt`). When a page holds more matches than are needed, `nextCursor` is a gbot cursor + * that resumes inside that page; otherwise it is the daemon's own cursor, verbatim. + * + * @param {{ limit?: number, cursor?: string, modelProviders?: string[], modelProvider?: string, sort?: "updated"|"created"|"recency", order?: "asc"|"desc", query?: string, since?: string|number, activeWithin?: string, cwd?: string, archived?: boolean, sourceKinds?: string[], now?: number, env?: NodeJS.ProcessEnv }} [opts] */ export async function listCodexThreads({ limit = 20, cursor, modelProviders = [], + modelProvider, + sort = "updated", + order = "desc", + query, + since, + activeWithin, + cwd, + archived, + sourceKinds, + now = Date.now(), env = process.env, } = {}) { if (!Number.isInteger(limit) || limit < 1 || limit > THREAD_LIST_MAX_LIMIT) { @@ -899,6 +953,30 @@ export async function listCodexThreads({ if (!Array.isArray(modelProviders) || modelProviders.some((p) => typeof p !== "string")) { throw new RangeError("modelProviders must be an array of strings (empty = all providers)"); } + if (!Object.hasOwn(THREAD_SORT_KEYS, sort)) throw new RangeError("--sort must be one of: " + Object.keys(THREAD_SORT_KEYS).join(", ")); + if (order !== "asc" && order !== "desc") throw new RangeError("--order must be asc or desc"); + if (query !== undefined && (typeof query !== "string" || !query.trim())) throw new RangeError("--query must be a non-empty string"); + if (sourceKinds !== undefined && (!Array.isArray(sourceKinds) || sourceKinds.some((k) => typeof k !== "string" || !k))) { + throw new RangeError("--source-kind must be a non-empty string"); + } + const providers = modelProvider ? [...modelProviders, modelProvider] : modelProviders; + const needle = query?.trim().toLowerCase(); + const cutoffs = []; + if (since !== undefined) cutoffs.push(parseSince(since)); + if (activeWithin !== undefined) cutoffs.push((now - parseActiveWithin(activeWithin)) / 1000); + const cutoff = cutoffs.length ? Math.max(...cutoffs) : undefined; + const clientSide = needle !== undefined || cutoff !== undefined; + const activityOf = (t) => (typeof t.updatedAt === "number" ? toSeconds(t.updatedAt) : typeof t.createdAt === "number" ? toSeconds(t.createdAt) : null); + const keep = (t) => { + if (cutoff !== undefined) { + const at = activityOf(t); + if (at === null || at < cutoff) return false; + } + if (needle !== undefined && ![t.name, t.preview, t.id].some((f) => typeof f === "string" && f.toLowerCase().includes(needle))) return false; + return true; + }; + const pageSize = clientSide ? THREAD_LIST_MAX_LIMIT : limit; + const start = decodeThreadCursor(cursor); const { client } = await openSession(env); try { // Default daemon filter is the current provider only. Pass modelProviders: [] for @@ -906,38 +984,67 @@ export async function listCodexThreads({ // rollout rescan (tens of seconds); fall back to a full scan when the state DB // returns nothing on the first page. const baseParams = { - limit, - modelProviders, - ...(cursor !== undefined ? { cursor } : {}), + limit: pageSize, + modelProviders: providers, + sortKey: THREAD_SORT_KEYS[sort], + ...(order === "asc" ? { sortDirection: "asc" } : {}), + ...(cwd ? { cwd } : {}), + ...(archived === true ? { archived: true } : {}), + ...(sourceKinds?.length ? { sourceKinds } : {}), }; - let out; - let usedStateDbOnly = true; - try { - out = await client.request("thread/list", { ...baseParams, useStateDbOnly: true }); - } catch (err) { - throw transportError(err); - } - if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); - if ( - out.data.length === 0 - && cursor === undefined - && (out.nextCursor == null || out.nextCursor === "") - ) { + const fetchPage = async (pageCursor, useStateDbOnly) => { try { - out = await client.request("thread/list", { ...baseParams, useStateDbOnly: false }); - usedStateDbOnly = false; + return await client.request("thread/list", { ...baseParams, ...(pageCursor !== undefined ? { cursor: pageCursor } : {}), useStateDbOnly }); } catch (err) { throw transportError(err); } + }; + const checkPage = (out) => { if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); + if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); + }; + const threads = []; + let usedStateDbOnly = true; + let scanned = 0; + let nextCursor = null; + let pageCursor = start.c; + let skip = start.skip; + for (;;) { + let out = await fetchPage(pageCursor, true); + checkPage(out); + if (out.data.length === 0 && pageCursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + out = await fetchPage(pageCursor, false); + usedStateDbOnly = false; + checkPage(out); + } + const rows = out.data.map(summarizeThread); + scanned += rows.length; + let matches = rows.filter(keep); + const pageSkip = skip; + if (skip) { matches = matches.slice(skip); skip = 0; } + const need = limit - threads.length; + if (matches.length > need) { + threads.push(...matches.slice(0, need)); + nextCursor = encodeThreadCursor({ ...(pageCursor !== undefined ? { c: pageCursor } : {}), skip: pageSkip + need }); + break; + } + threads.push(...matches); + const more = out.nextCursor || null; + // Newest-first by activity: once a page ends before the cutoff nothing later can qualify. + const last = rows[rows.length - 1]; + const pastCutoff = cutoff !== undefined && sort === "updated" && order === "desc" && last !== undefined && (activityOf(last) ?? -Infinity) < cutoff; + if (!more || pastCutoff) break; + if (threads.length >= limit) { nextCursor = more; break; } + pageCursor = more; } - if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); - const threads = out.data.map(summarizeThread); return { threads, - nextCursor: out.nextCursor ?? null, + nextCursor, limit, useStateDbOnly: usedStateDbOnly, + sort, + order, + scanned, }; } finally { client.close(); diff --git a/src/core/codex/routes.ts b/src/core/codex/routes.ts index 481e779..b0752a3 100644 --- a/src/core/codex/routes.ts +++ b/src/core/codex/routes.ts @@ -2,6 +2,7 @@ import { z } from 'zod'; import { buildEnvelope, listCodexThreads, sendToCodexThread } from '../codex-bridge.js'; import { outcomeFromError } from './contract.js'; import { openCodexConversation } from './conversation.js'; +import { formatCodexThread } from '../format.js'; import { normalizeCodexThreadId } from './thread-id.js'; const bareId = z.string().regex(/^[A-Za-z0-9_.:-]{1,128}$/); @@ -34,7 +35,26 @@ export const sendFields = { export const sendSchema = z.object({ ...sendFields, message: z.string().min(1).max(4194304) }).strict(); export const waitSchema = z.object({ ...observationFields, turnId: bareId, messageId: bareId.optional(), maxOutputBytes: z.number().int().min(1).max(4194304).optional() }).strict(); export const watchSchema = z.object({ expectedCwd: z.string().min(1).optional(), threadId: id, timeoutMs: z.number().int().min(1).max(600000).optional(), maxEvents: z.number().int().min(1).max(500).default(100) }).strict(); -export const threadsSchema = z.object({ limit: z.number().int().min(1).max(200).default(20), cursor: z.string().min(1).max(4096).optional() }).strict(); +export const threadsSchema = z.object({ + limit: z.number().int().min(1).max(200).default(20), + cursor: z.string().min(1).max(4096).optional(), + /** Recent activity (updatedAt) first by default; `created` is the daemon's own default order. */ + sort: z.enum(['updated', 'created', 'recency']).default('updated'), + order: z.enum(['desc', 'asc']).default('desc'), + /** Case-insensitive substring of thread name/title, preview or id (so an id prefix works); scans every page. */ + query: z.string().trim().min(1).max(256).optional(), + /** Only threads active within this long: 90s, 30m, 12h, 7d, 2w. */ + activeWithin: z.string().trim().regex(/^\d+(?:\.\d+)?\s*[smhdw]$/i, 'use a duration like 30m, 12h, 7d or 2w').optional(), + /** Only threads updated at or after this ISO date/time or epoch seconds. */ + since: z.string().trim().min(1).max(64).optional(), + /** Exact session cwd. */ + cwd: z.string().min(1).max(4096).optional(), + /** Any modelProvider id; omit for all providers. Not an enum. */ + modelProvider: z.string().min(1).max(256).optional(), + archived: z.boolean().optional(), + /** Any app-server source kind (cli, vscode, exec, appServer, subAgent...); omit for the daemon's interactive default. Not an enum. */ + sourceKind: z.string().min(1).max(64).optional(), +}).strict(); export const resultSchema = z.object({ exitCode: z.number().int().min(0).max(1), threadId: z.string().optional(), turnId: z.string().optional(), messageId: z.string().optional(), @@ -86,7 +106,10 @@ export async function observeOperation(kind: 'wait' | 'watch', input: z.infer) { - try { return { ...await listCodexThreads(input), exitCode: 0 }; } + try { + const { sourceKind, ...rest } = input; + return { ...await listCodexThreads({ ...rest, ...(sourceKind ? { sourceKinds: [sourceKind] } : {}) }), exitCode: 0 }; + } catch (error) { return outcomeFromError(error); } } export function resultText(result: Record) { @@ -96,6 +119,9 @@ export function resultText(result: Record) { if (result.delivery === 'accepted') return `Started turn ${result.turnId} (${result.turnStatus}) on Codex thread ${result.threadId}; message ${result.messageId}`; if (result.delivery) return `Codex delivery ${result.delivery} on thread ${result.threadId}`; if (result.reason) return `Codex observation: ${result.reason}`; - if (Array.isArray(result.threads)) return `${result.threads.length} Codex threads`; + if (Array.isArray(result.threads)) { + const rows = result.threads.map((t) => formatCodexThread(t as never)).join('\n\n'); + return `${result.threads.length} Codex threads (sort ${String(result.sort ?? 'updated')} ${String(result.order ?? 'desc')})${result.nextCursor ? `; more: pass cursor ${JSON.stringify(result.nextCursor)}` : ''}${rows ? `\n\n${rows}` : ''}`; + } return String(result.error ?? 'Codex observation complete'); } diff --git a/src/core/format.js b/src/core/format.js index 720e03e..9045fc5 100644 --- a/src/core/format.js +++ b/src/core/format.js @@ -103,8 +103,11 @@ export function formatCodexThread(t) { const preview = t.preview ? "\n " + stripTerminalControls(String(t.preview).replace(/\s+/g, " ")).slice(0, 200) : ""; + const at = typeof t.updatedAt === "number" && Number.isFinite(t.updatedAt) + ? new Date((t.updatedAt > 1e11 ? t.updatedAt : t.updatedAt * 1000)).toISOString().replace(/\.\d{3}Z$/, "Z") + : ""; return stripTerminalControls(t.id) + " " + stripTerminalControls(t.status) + title - + "\n " + stripTerminalControls(t.cwd ?? "") + preview; + + "\n " + stripTerminalControls(t.cwd ?? "") + (at ? " (updated " + at + ")" : "") + preview; } /** Shell-safe single-quoting for copy-pasteable export lines (spaces, quotes, $). */ diff --git a/src/core/relay/completion.js b/src/core/relay/completion.js index aae15c4..4b4163e 100644 --- a/src/core/relay/completion.js +++ b/src/core/relay/completion.js @@ -1,7 +1,9 @@ +import { codexSenderPrefix } from "../sender-prefix.js"; import { hash, op, records, terminal, MAX_TEXT } from "./records.js"; /** Each target/thread/turn gets one durable return intent, anchored to its associated inputs. */ export function createCompletion({ + env = process.env, state, codex, update, @@ -87,12 +89,22 @@ export function createCompletion({ suffix = result.reply.truncated ? "\n[Output truncated]" : ""; let output = result.reply.text || `Codex turn ${execution} with no final text.`; - const prefix = `[Codex ${first.threadId}; turn ${first.turnId}; status ${execution}; sources ${sources - .slice(0, 8) - .map((id) => id.slice(0, 128)) - .join( - ", ", - )}${sources.length > 8 ? " (additional source IDs retained in relay state)" : ""}]\n`; + const prefix = + codexSenderPrefix({ + threadId: first.threadId, + cwd: first.expectedCwd, + env, + details: [ + `turn ${first.turnId}`, + `status ${execution}`, + `sources ${sources + .slice(0, 8) + .map((id) => id.slice(0, 128)) + .join( + ", ", + )}${sources.length > 8 ? " (additional source IDs retained in relay state)" : ""}`, + ], + }) + "\n"; // Bound UTF-8 without cutting a code point, and make truncation explicit. const budget = MAX_TEXT - Buffer.byteLength(prefix + suffix) - 32; let truncated = false; diff --git a/src/core/relay/engine.js b/src/core/relay/engine.js index 8e4ff54..722ecda 100644 --- a/src/core/relay/engine.js +++ b/src/core/relay/engine.js @@ -12,6 +12,7 @@ import { createRecordFactory, } from "./records.js"; import { createIntake } from "./intake.js"; +import { withCodexSender } from "../sender-prefix.js"; import { createCompletion } from "./completion.js"; import { connectGateway, @@ -97,6 +98,7 @@ export async function openRelayEngine({ stoppedBindings, }); const completions = createCompletion({ + env, state, codex, update, @@ -246,9 +248,16 @@ export async function openRelayEngine({ throw new Error("Idempotency conflict"); return receipt(old); } - const text = messageText(input.message); + const raw = messageText(input.message); envelope(input); const r = await route(input); + // Codex -> Grok: say which thread/machine/cwd is asking and how to answer it. + const text = + kind === "grok-request" + ? messageText( + withCodexSender(raw, { threadId: r.threadId, cwd: r.expectedCwd, env }), + ) + : raw; await baseline(r.targetId); if (state.read().targets[r.targetId].state !== "running") throw new Error("Target coverage is paused"); diff --git a/src/core/relay/routes.ts b/src/core/relay/routes.ts index f0b977f..db7741c 100644 --- a/src/core/relay/routes.ts +++ b/src/core/relay/routes.ts @@ -11,6 +11,7 @@ import { } from "../../gbot.js"; import { buildEnvelope, withEnvelopeHeader } from "../codex-bridge.js"; +import { withCodexSender } from "../sender-prefix.js"; const id = z.string().min(1).max(128); export const routeFields = { @@ -138,10 +139,15 @@ export async function grokSendOperation( throw Error( "Automatic reply delivery requires a native Codex source, codexThreadId or bindingId", ); - const message = + const stamped = input.hop !== undefined || input.correlationId !== undefined ? withEnvelopeHeader(input.message, buildEnvelope(input)) : input.message; + // Codex -> Grok without the managed relay: still say which thread is asking and how to answer. + const message = withCodexSender(stamped, { + threadId: route.codexThreadId, + cwd: route.expectedCwd, + }); const sent = await withRedactedErrors(async () => sendPrompt(await connectGateway(), input.target, message), ); diff --git a/src/core/sender-prefix.js b/src/core/sender-prefix.js new file mode 100644 index 0000000..9aa4127 --- /dev/null +++ b/src/core/sender-prefix.js @@ -0,0 +1,44 @@ +import { hostname } from "node:os"; + +/** + * Provenance prefix for messages a Codex thread sends to Grok Bot, so the receiver can answer. + * Unknown fields are omitted; the thread id is always present when it is known. MCP is the + * primary reply surface (`codex_send`), the CLI is the fallback. + */ +const oneLine = (value) => String(value ?? "").replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/[\]]/g, ")").trim(); + +export function machineName(env = process.env) { + try { + return oneLine(env.GROK_BOT_MACHINE_NAME || hostname()); + } catch { + return ""; + } +} + +/** + * @param {{ threadId?: string, machine?: string, cwd?: string, details?: string[], env?: NodeJS.ProcessEnv }} fields + * @returns {string} `[from Codex thread @ , cwd ; ...; reply: ...]` or "" without a thread id + */ +export function codexSenderPrefix({ threadId, machine, cwd, details = [], env = process.env } = {}) { + const id = oneLine(threadId); + if (!id) return ""; + const where = oneLine(machine ?? machineName(env)); + const dir = oneLine(cwd); + const head = "from Codex thread " + id + (where ? " @ " + where : "") + (dir ? (where ? ", " : " ") + "cwd " + dir : ""); + const reply = "reply: codex_send({threadId:\"" + id + "\", message:\"...\"})" + + (where ? " via MCP on " + where : " via MCP") + + " (or CLI: gbot codex send " + id + " \"...\")"; + return "[" + [head, ...details.map(oneLine).filter(Boolean), reply].join("; ") + "]"; +} + +/** Prefix + newline + text; the text unchanged when no thread id is known. */ +export function withCodexSender(text, fields) { + const prefix = codexSenderPrefix(fields); + return prefix ? prefix + "\n" + text : text; +} + +/** The Codex terminal exports the current thread id to every command it runs. */ +export function envCodexThreadId(env = process.env) { + const id = env.CODEX_THREAD_ID?.trim(); + return id && /^[A-Za-z0-9_.:-]{1,128}$/.test(id) ? id : undefined; +} diff --git a/src/mcp/grok-bot/tools/codex_threads.tsx b/src/mcp/grok-bot/tools/codex_threads.tsx index 7350eca..3b1c515 100644 --- a/src/mcp/grok-bot/tools/codex_threads.tsx +++ b/src/mcp/grok-bot/tools/codex_threads.tsx @@ -4,18 +4,21 @@ import { threadsSchema as inputSchema, resultSchema, threadsOperation, resultTex export { inputSchema }; export default defineTool({ excludeClients: ['codex'], - description: 'Discover a bounded page of Codex daemon threads. Runs on the user\'s registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.', title: 'Codex threads', annotations: { readOnlyHint: true }, + description: 'Discover Codex daemon threads on the user\'s registered machine (local socket, not the Grok Bot box; from the box run gbot there through Shell with a machineId after codex app-server daemon start or bootstrap). Newest activity first by default (sort:"updated"), so old-but-active threads surface; sort:"created" restores creation order. Find one thread with query (case-insensitive substring of name/title, preview or id, so an id prefix works) - it scans every page, not just the first 100. Narrow with activeWithin ("30m", "12h", "7d", "2w") or since (ISO/epoch seconds), cwd, modelProvider, sourceKind, archived. limit is the page size (1-200); pass nextCursor back as cursor for more.', title: 'Codex threads', annotations: { readOnlyHint: true }, render: { maxElapsedMs: 660000 }, inputSchema, resultSchema, inputJsonSchema: { type: 'object', additionalProperties: false, properties: { - "limit": { - "type": "number", - "description": "Maximum threads in this page: 1-200. Pass modelProviders:[] internally so every provider is included; use cursor/nextCursor to page." - }, - "cursor": { - "type": "string", - "description": "Opaque nextCursor from a previous page." - } + limit: { type: 'number', description: 'Maximum threads in this page: 1-200 (default 20). Every provider is included; use cursor/nextCursor to page.' }, + cursor: { type: 'string', description: 'Opaque nextCursor from a previous page.' }, + sort: { type: 'string', enum: ['updated', 'created', 'recency'], default: 'updated', description: 'updated = last activity (default), created = creation time, recency = daemon recency order.' }, + order: { type: 'string', enum: ['desc', 'asc'], default: 'desc' }, + query: { type: 'string', description: 'Case-insensitive substring of thread name/title, preview or id (id prefix works). Scans all pages.' }, + activeWithin: { type: 'string', description: 'Only threads updated within this long: 90s, 30m, 12h, 7d, 2w.' }, + since: { type: 'string', description: 'Only threads updated at or after this ISO date/time or epoch seconds.' }, + cwd: { type: 'string', description: 'Exact session working directory.' }, + modelProvider: { type: 'string', description: 'Any modelProvider id; omit for all.' }, + sourceKind: { type: 'string', description: 'Any app-server source kind (cli, vscode, exec, appServer, subAgent...); omit for interactive sources.' }, + archived: { type: 'boolean', description: 'true = archived threads only.' }, }, required: [] }, }, async input => { const context = await agent(); diff --git a/src/skills/talk-to-grok-bot/SKILL.md b/src/skills/talk-to-grok-bot/SKILL.md index 68c5ded..173d154 100644 --- a/src/skills/talk-to-grok-bot/SKILL.md +++ b/src/skills/talk-to-grok-bot/SKILL.md @@ -44,6 +44,20 @@ continue useful work instead of waiting or polling. Read `gbot_thread` later, using `after` for a known cursor and `full: true` only when entry bodies are needed. `replyMode: manual` explicitly requests this flow. +Every Codex -> Grok message arrives prefixed +`[from Codex thread @ , cwd ; reply: codex_send({threadId:"", message:"..."}) via MCP on (or CLI: gbot codex send "...")]`. +**If you are Grok Bot, answer a Codex sender by calling `codex_send` with that +`threadId`** (from the box, run `gbot codex send "..."` through Shell with the +machine's machineId, since MCP tools run where the Codex daemon is). Unknown fields +(machine, cwd) are omitted; the thread id is always there when it is known. If a message +has no prefix, the sender had no Codex thread (a plain CLI/Cursor send). + +Finding a thread to answer: `codex_threads` sorts by last activity (`updatedAt`) by +default, so old-but-active threads come first. Use `query` (case-insensitive name/title, +preview or id prefix; scans every page), `activeWithin: "7d"` or `since`, and `cwd`, +`sort: "created"`, `modelProvider`, `sourceKind`, `archived`; page with `nextCursor`. +CLI: `gbot codex list-threads --query zerofs --active-within 7d`. + Never resend an unknown submission under a new identity. Inspect delivery with `gbot_bridge_status`. Never infer permission from chat replies or auto-approve a Codex/Grok interaction; keep approvals in the owning UI unless the user explicitly diff --git a/src/skills/talk-to-grok-bot/references/bridge-administration.md b/src/skills/talk-to-grok-bot/references/bridge-administration.md index 268b1e6..5c1bdf9 100644 --- a/src/skills/talk-to-grok-bot/references/bridge-administration.md +++ b/src/skills/talk-to-grok-bot/references/bridge-administration.md @@ -39,7 +39,7 @@ Shell with a machineId, after `codex app-server daemon start` (or bootstrap) the Grok tools use the Grok gateway. Portable MCP artifacts must be configured in an MCP-capable host; they are not automatically loaded by the Grok app. -- `codex_threads`: bounded discovery of daemon-managed Codex threads. +- `codex_threads`: discovery of daemon-managed Codex threads, newest activity first. `query` (name/title, preview or id prefix, all pages), `activeWithin`/`since`, `sort`/`order`, `cwd`, `modelProvider`, `sourceKind`, `archived`; `limit` is the page size (1-200) and `nextCursor` continues. - `codex_send`: submit a message with a correlation envelope. Default delivery is immediate acceptance, which does not mean execution finished. `wait: true` adds bounded execution and final reply fields. An accepted message remains accepted From 211ef36ead26bcafca2818f6b886526bc8efcf66 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:49:43 -0700 Subject: [PATCH 3/5] test: sender prefix, thread sort/filter/search paging --- test/codex-bridge.test.js | 150 +++++++++++++++++++++++++++++++-- test/relay-engine.test.js | 21 ++++- tests/route-unit/tools.test.ts | 22 +++++ 3 files changed, 184 insertions(+), 9 deletions(-) diff --git a/test/codex-bridge.test.js b/test/codex-bridge.test.js index 5f229d9..0ef8b2c 100644 --- a/test/codex-bridge.test.js +++ b/test/codex-bridge.test.js @@ -6,9 +6,10 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; import test from "node:test"; +import { codexSenderPrefix, envCodexThreadId, withCodexSender } from "../src/core/sender-prefix.js"; import { fakeAppServer, createCodexFixtureHome } from "./helpers/codex-server.js"; -import { decodeFrame, encodeFrame, websocketAccept, connectCodexAppServer, sendToCodexThread, startCodexThread, codexSocketPath, codexStatus, detectDesktopPrivateAppServer, unreachableMessage, looksLikeGrokBotBox, boxUnreachableMessage } from "../src/core/codex-bridge.js"; +import { decodeFrame, encodeFrame, websocketAccept, connectCodexAppServer, sendToCodexThread, listCodexThreads, startCodexThread, codexSocketPath, codexStatus, detectDesktopPrivateAppServer, unreachableMessage, looksLikeGrokBotBox, boxUnreachableMessage } from "../src/core/codex-bridge.js"; test('send applies model and effort overrides supported by Codex 0.158.0', async () => { const fake = await fakeAppServer(baseHandlers); @@ -142,11 +143,11 @@ test("codex list-threads passes --limit and prints threads", async () => { try { const text = await gbot(fake.home, "codex", "list-threads", "--limit", "1"); assert.equal(text.code, 0, text.err); - assert.equal(text.out, "t-1 idle - Fix the build\n /repo/a\n please fix the build\n\nmore: --cursor \"cursor-2\"\n"); + assert.equal(text.out, "t-1 idle - Fix the build\n /repo/a (updated 2023-11-14T22:13:21Z)\n please fix the build\n\nmore: --cursor \"cursor-2\"\n"); assert.deepEqual(fake.received.find((m) => m.method === "thread/list").params, { limit: 1, useStateDbOnly: true, - modelProviders: [], + modelProviders: [], sortKey: "updated_at", }); const json = await gbot(fake.home, "codex", "list-threads", "--json"); @@ -189,12 +190,15 @@ test("codex list-threads passes --limit and prints threads", async () => { nextCursor: null, limit: 20, useStateDbOnly: true, + sort: "updated", + order: "desc", + scanned: 2, exitCode: 0, }); assert.deepEqual(fake.received.at(-1).params, { limit: 20, useStateDbOnly: true, - modelProviders: [], + modelProviders: [], sortKey: "updated_at", }); } finally { await fake.close(); @@ -240,7 +244,7 @@ test("codex list-threads passes modelProviders:[] so other providers are not fil try { const { code, out } = await gbot(fake.home, "codex", "list-threads", "--json"); assert.equal(code, 0, out); - assert.deepEqual(seen[0], { limit: 20, useStateDbOnly: true, modelProviders: [] }); + assert.deepEqual(seen[0], { limit: 20, useStateDbOnly: true, modelProviders: [], sortKey: "updated_at" }); const page = JSON.parse(out); assert.deepEqual(page.threads.map((t) => t.id), ["openai-1", "other-1"]); assert.equal(page.threads[1].modelProvider, "azure"); @@ -922,7 +926,7 @@ test("codex list-threads pages with --cursor, echoes nextCursor, and rejects unk const second = await gbot(fake.home, "codex", "list-threads", "--limit", "1", "--cursor", "page-2", "--json"); assert.deepEqual(JSON.parse(second.out).threads.map((t) => t.id), ["t-2"]); assert.equal(JSON.parse(second.out).nextCursor, null); - assert.deepEqual(seen.at(-1), { limit: 1, useStateDbOnly: true, modelProviders: [], cursor: "page-2" }); + assert.deepEqual(seen.at(-1), { limit: 1, useStateDbOnly: true, modelProviders: [], sortKey: "updated_at", cursor: "page-2" }); const unknown = await gbot(fake.home, "codex", "list-threads", "--all"); assert.equal(unknown.code, 2); @@ -1587,8 +1591,8 @@ test("codex list-threads falls back to a full scan when useStateDbOnly returns n assert.deepEqual(page.threads.map((t) => t.id), ["t-1"]); assert.equal(page.useStateDbOnly, false); assert.deepEqual(seen, [ - { limit: 20, modelProviders: [], useStateDbOnly: true }, - { limit: 20, modelProviders: [], useStateDbOnly: false }, + { limit: 20, modelProviders: [], sortKey: "updated_at", useStateDbOnly: true }, + { limit: 20, modelProviders: [], sortKey: "updated_at", useStateDbOnly: false }, ]); } finally { await fake.close(); @@ -1720,3 +1724,133 @@ test("normalizeCodexThreadId strips local: and rejects temporary Desktop rows", assert.throws(() => normalizeCodexThreadId("local:client-new-thread:x"), /Temporary Desktop/); assert.throws(() => normalizeCodexThreadId("client-new-thread:x"), /Temporary Desktop/); }); + +// A daemon with 450 threads whose creation order differs from its activity order: the +// thread we want was created first but touched last. +function bigDaemon() { + const rows = Array.from({ length: 450 }, (_, i) => ({ + id: `01a0${String(i).padStart(4, "0")}-aaaa-7000-8000-000000000000`, + status: { type: "idle" }, + name: i === 3 ? "ZeroFS recovery notes" : `Thread ${i}`, + preview: i === 3 ? "recover the zero fs pool" : `preview ${i}`, + cwd: `/repo/${i % 5}`, + source: "cli", + createdAt: 1_700_000_000 + (449 - i), + updatedAt: 1_700_000_000 + (i === 3 ? 100_000 : 449 - i), + })); + const calls = []; + return { + calls, + handler: (params, ok) => { + calls.push(params); + const key = params.sortKey === "updated_at" ? "updatedAt" : "createdAt"; + let sorted = [...rows].sort((a, b) => (params.sortDirection === "asc" ? a[key] - b[key] : b[key] - a[key])); + if (params.cwd) sorted = sorted.filter((r) => r.cwd === params.cwd); + const offset = params.cursor ? Number(params.cursor.slice(2)) : 0; + const page = sorted.slice(offset, offset + params.limit); + ok({ data: page, nextCursor: offset + page.length < sorted.length ? "o:" + (offset + page.length) : null }); + }, + }; +} + +test("list-threads sorts by recent activity by default and finds an old-but-active thread past page one", async () => { + const daemon = bigDaemon(); + const fake = await fakeAppServer({ ...baseHandlers, "thread/list": daemon.handler }); + const env = { CODEX_HOME: fake.home }; + try { + const recent = await listCodexThreads({ limit: 5, env }); + assert.equal(recent.sort, "updated"); + assert.equal(daemon.calls[0].sortKey, "updated_at"); + assert.equal(recent.threads[0].name, "ZeroFS recovery notes"); + assert.match(recent.nextCursor, /^o:/); + + const created = await listCodexThreads({ limit: 5, sort: "created", env }); + assert.equal(created.threads[0].name, "Thread 0"); + assert.equal(daemon.calls.at(-1).sortKey, "created_at"); + // In creation order the thread is 4th; ask for the oldest first and it is last of 450. + const oldest = await listCodexThreads({ limit: 1, sort: "created", order: "asc", env }); + assert.equal(oldest.threads[0].name, "Thread 449"); + assert.equal(daemon.calls.at(-1).sortDirection, "asc"); + } finally { + await fake.close(); + } +}); + +test("list-threads query scans every page by name, preview and id prefix", async () => { + const daemon = bigDaemon(); + const fake = await fakeAppServer({ ...baseHandlers, "thread/list": daemon.handler }); + const env = { CODEX_HOME: fake.home }; + try { + const byName = await listCodexThreads({ query: "zerofs", sort: "created", env }); + assert.deepEqual(byName.threads.map((t) => t.name), ["ZeroFS recovery notes"]); + assert.equal(byName.scanned, 450); + assert.equal(byName.nextCursor, null); + assert.ok(daemon.calls.length >= 3, "paged past the first 200"); + + const byPreview = await listCodexThreads({ query: "zero fs pool", env }); + assert.equal(byPreview.threads.length, 1); + const byId = await listCodexThreads({ query: "01a00003-AAAA", sort: "created", env }); + assert.deepEqual(byId.threads.map((t) => t.id), ["01a00003-aaaa-7000-8000-000000000000"]); + assert.equal((await listCodexThreads({ query: "no such thread", env })).threads.length, 0); + } finally { + await fake.close(); + } +}); + +test("list-threads activeWithin/since filter by updatedAt and a gbot cursor resumes mid-page without gaps or repeats", async () => { + const daemon = bigDaemon(); + const fake = await fakeAppServer({ ...baseHandlers, "thread/list": daemon.handler }); + const env = { CODEX_HOME: fake.home }; + const now = (1_700_000_000 + 449) * 1000; + try { + // Updated within the last 300s => updatedAt >= base+149: threads 0..300 (301, the revived one among them). + const within = await listCodexThreads({ activeWithin: "5m", limit: 150, now, env }); + assert.equal(within.threads.length, 150); + assert.match(within.nextCursor, /^gbot1:/); + const rest = await listCodexThreads({ activeWithin: "5m", limit: 200, cursor: within.nextCursor, now, env }); + assert.equal(rest.threads.length, 151); + assert.equal(rest.nextCursor, null); + const ids = [...within.threads, ...rest.threads].map((t) => t.id); + assert.equal(new Set(ids).size, 301); + assert.equal(ids[0], "01a00003-aaaa-7000-8000-000000000000"); + + const since = await listCodexThreads({ since: new Date((1_700_000_000 + 440) * 1000).toISOString(), limit: 50, env }); + assert.equal(since.threads.length, 10); + assert.equal(since.nextCursor, null); + const epoch = await listCodexThreads({ since: String(1_700_000_000 + 440), limit: 50, env }); + assert.equal(epoch.threads.length, 10); + await assert.rejects(listCodexThreads({ activeWithin: "soon", env }), /--active-within/); + await assert.rejects(listCodexThreads({ since: "not a date", env }), /--since/); + await assert.rejects(listCodexThreads({ cursor: "gbot1:%%%", env }), /valid thread cursor/); + } finally { + await fake.close(); + } +}); + +test("list-threads passes cwd, provider, archived and source kind filters to the daemon", async () => { + const daemon = bigDaemon(); + const fake = await fakeAppServer({ ...baseHandlers, "thread/list": daemon.handler }); + try { + const out = await listCodexThreads({ cwd: "/repo/3", modelProvider: "openai", archived: true, sourceKinds: ["vscode"], limit: 3, env: { CODEX_HOME: fake.home } }); + assert.ok(out.threads.every((t) => t.cwd === "/repo/3")); + assert.deepEqual(daemon.calls[0], { limit: 3, modelProviders: ["openai"], sortKey: "updated_at", cwd: "/repo/3", archived: true, sourceKinds: ["vscode"], useStateDbOnly: true }); + } finally { + await fake.close(); + } +}); + +test("Codex sender prefix names thread, machine, cwd and both reply forms; unknown fields drop out", () => { + const full = codexSenderPrefix({ threadId: "01a03c14-5bb0-7850-a2c7-15f6f4a1ab74", machine: "mac-studio", cwd: "/repo/x" }); + assert.equal(full, '[from Codex thread 01a03c14-5bb0-7850-a2c7-15f6f4a1ab74 @ mac-studio, cwd /repo/x; reply: codex_send({threadId:"01a03c14-5bb0-7850-a2c7-15f6f4a1ab74", message:"..."}) via MCP on mac-studio (or CLI: gbot codex send 01a03c14-5bb0-7850-a2c7-15f6f4a1ab74 "...")]'); + const noCwd = codexSenderPrefix({ threadId: "t-1", machine: "box" }); + assert.match(noCwd, /^\[from Codex thread t-1 @ box; reply: /); + assert.doesNotMatch(noCwd, /cwd/); + const bare = codexSenderPrefix({ threadId: "t-1", machine: "" }); + assert.match(bare, /^\[from Codex thread t-1; reply: codex_send\(\{threadId:"t-1", message:"\.\.\."\}\) via MCP \(or CLI/); + assert.equal(codexSenderPrefix({ machine: "box", cwd: "/x" }), ""); + assert.equal(withCodexSender("hello", { cwd: "/x" }), "hello"); + assert.equal(codexSenderPrefix({ threadId: "t-1", machine: "a]\nb", cwd: "/x]\u0007y" }).includes("\n"), false); + assert.equal(envCodexThreadId({ CODEX_THREAD_ID: " t-9 " }), "t-9"); + assert.equal(envCodexThreadId({ CODEX_THREAD_ID: "bad id" }), undefined); + assert.equal(envCodexThreadId({}), undefined); +}); diff --git a/test/relay-engine.test.js b/test/relay-engine.test.js index f647c0a..48d0a91 100644 --- a/test/relay-engine.test.js +++ b/test/relay-engine.test.js @@ -1,7 +1,8 @@ import assert from "node:assert/strict"; import test from "node:test"; import { mkdtemp, rm } from "node:fs/promises"; -import { tmpdir } from "node:os"; +import { hostname, tmpdir } from "node:os"; +import { realpathSync } from "node:fs"; import { join } from "node:path"; import { fakeAppServer } from "./helpers/codex-server.js"; @@ -711,3 +712,21 @@ test("invalid per-send binding busy policies reject before recording or submitti 0, ); }); + +test("Codex -> Grok requests and returns carry the sender prefix with thread id, machine, cwd and reply forms", async (t) => { + const f = await fixture(t); + const cwd = realpathSync(process.cwd()); + const machine = hostname(); + const prefix = `[from Codex thread thread @ ${machine}, cwd ${cwd}; reply: codex_send({threadId:"thread", message:"..."}) via MCP on ${machine} (or CLI: gbot codex send thread "...")]`; + await f.engine.sendToGrok({ grokTarget: "target", codexThreadId: "thread", message: "Ask Grok", requestId: "ask" }); + assert.equal(f.sent[0].text, prefix + "\nAsk Grok"); + + const g = await fixture(t); + await g.engine.startBinding({ grokTarget: "target", codexThreadId: "thread", requestId: "link" }); + g.page.push({ id: "g1", kind: "send-message", requestId: "proactive", message: { content: "Hello Codex" } }); + await g.engine.tick(); + const returned = g.sent[0].text; + assert.ok(returned.startsWith(`[from Codex thread thread @ ${machine}, cwd ${cwd}; turn turn-1; status completed; sources `), returned); + assert.match(returned, /; reply: codex_send\(\{threadId:"thread", message:"\.\.\."\}\) via MCP on /); + assert.ok(returned.endsWith("]\nCodex answer"), returned); +}); diff --git a/tests/route-unit/tools.test.ts b/tests/route-unit/tools.test.ts index e7b6d10..dc40490 100644 --- a/tests/route-unit/tools.test.ts +++ b/tests/route-unit/tools.test.ts @@ -162,6 +162,28 @@ describe('grok-bot MCP server', () => { } }); + it('codex_threads input defaults to recent-activity order and rejects a malformed activeWithin', async () => { + const { threadsSchema } = await import('../../src/core/codex/routes.js'); + expect(threadsSchema.parse({})).toEqual({ limit: 20, sort: 'updated', order: 'desc' }); + expect(threadsSchema.parse({ query: ' zerofs ', activeWithin: '7d', sourceKind: 'whatever-new' })).toMatchObject({ query: 'zerofs', activeWithin: '7d', sourceKind: 'whatever-new' }); + expect(() => threadsSchema.parse({ activeWithin: 'lately' })).toThrow(); + expect(() => threadsSchema.parse({ sort: 'name' })).toThrow(); + const surface = await invokeMcpTool('codex_threads', { input: { activeWithin: 'lately' }, server: 'grok-bot' }); + expect(surface.isError).toBe(true); + }); + + it('gbot_send from a known Codex thread (manual replies) prefixes the prompt with thread, machine, cwd and reply forms', async () => { + const result = await invokeMcpTool('gbot_send', { + input: { message: 'ZeroFS recovery notes', target: 'general', replyMode: 'manual', codexThreadId: '01a03c14-5bb0-7850-a2c7-15f6f4a1ab74', expectedCwd: '/repo/zerofs' }, + server: 'grok-bot', + }); + expect(result.isError).toBe(false); + const prompt = String(calls.at(-1)?.body.prompt); + expect(prompt).toContain('[from Codex thread 01a03c14-5bb0-7850-a2c7-15f6f4a1ab74 @ '); + expect(prompt).toContain(', cwd /repo/zerofs; reply: codex_send({threadId:"01a03c14-5bb0-7850-a2c7-15f6f4a1ab74", message:"..."}) via MCP on '); + expect(prompt).toContain('(or CLI: gbot codex send 01a03c14-5bb0-7850-a2c7-15f6f4a1ab74 "...")]\nZeroFS recovery notes'); + }); + it('gbot_send resolves the target by name and posts the prompt with the gateway token', async () => { const result = await invokeMcpTool('gbot_send', { input: { message: 'automated smoke', target: 'general' }, From 14af5b292cb0737964a9bcb400b410bbbf7f0bb8 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:49:43 -0700 Subject: [PATCH 4/5] docs: Codex sender prefix and thread discovery --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e9ced7d..d0fbfe5 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,8 @@ All gateway / `EnsureSandBox` fetches use `redirect: "error"` so credentials are ```sh codex app-server daemon start # once per machine session gbot codex status # socket, daemon version, reachability -gbot codex list-threads --limit 10 # id, status, cwd, preview +gbot codex list-threads --limit 10 # newest activity first: id, status, cwd, updated, preview +gbot codex list-threads --query zerofs --active-within 7d # find an old-but-active thread gbot codex send "Grok here: the build is green, please continue." gbot codex send --model gpt-6-astra --effort high "Review this change" gbot codex new --cwd /path/to/project --model gpt-6-astra --effort high "Start here" @@ -248,7 +249,7 @@ MCP tools: `chatgpt_desktop_status`, `chatgpt_desktop_list_threads`, `chatgpt_de `desktopShimConfigured` is true when the installed wrapper is selected by Desktop-facing `CODEX_CLI_PATH` (the GUI domain on macOS). This describes configuration for future launches; a running Desktop may not have inherited it, and the wrapper may have fallen back to stock Codex. `desktopAttached` is `"private-stdio"` when a Desktop-bundled app-server process is observed, otherwise `"unknown"`. That process observation and shim configuration can both be present. Neither a configured shim nor a reachable daemon proves Desktop is attached to that daemon. Verify actual attachment with a controlled shared-thread interaction and matching thread/turn IDs. -**Thread discovery.** `list-threads --limit N` (1–200) pages with the opaque `--cursor` from the previous `nextCursor`; JSON keeps the cursor verbatim, text output prints a sanitized `more: --cursor …` hint. Requests pass `modelProviders: []` so threads from every provider appear (the daemon otherwise filters to the current provider) and `useStateDbOnly: true` for a fast state-DB listing, falling back to a full scan when that first page is empty. Text fields are stripped of terminal control sequences in both outputs (single-line fields also lose line breaks; `preview` keeps its newlines; a structured `source` such as `{ "custom": … }` passes through unchanged), `status` is one of `notLoaded | idle | active | systemError | unknown`, and non-numeric `updatedAt` / `createdAt` become `null`. Extra fields when present: `section`, `projectId`, `modelProvider`, `model`, `originator`. Unknown arguments are rejected before the socket is touched; a response that does not match the pinned schema (including an entry without a string `id`) fails with `reason: "bad-response"`. +**Thread discovery.** `list-threads` is newest-activity-first (`--sort updated`, the default; `--sort created|recency`, `--order asc`) and finds old-but-active threads: `--query zerofs` (case-insensitive name/title, preview or id prefix, scanning every page, not just the first 100), `--active-within 7d` / `--since 2026-09-01`, `--cwd`, `--model-provider`, `--source-kind`, `--archived`; the `codex_threads` MCP tool takes the same fields (`query`, `activeWithin`, `since`, `sort`, `order`, ...). `--limit N` (1–200) is the page size and pages with the opaque `--cursor` from the previous `nextCursor`; JSON keeps the cursor verbatim, text output prints a sanitized `more: --cursor …` hint. Requests pass `modelProviders: []` so threads from every provider appear (the daemon otherwise filters to the current provider) and `useStateDbOnly: true` for a fast state-DB listing, falling back to a full scan when that first page is empty. Text fields are stripped of terminal control sequences in both outputs (single-line fields also lose line breaks; `preview` keeps its newlines; a structured `source` such as `{ "custom": … }` passes through unchanged), `status` is one of `notLoaded | idle | active | systemError | unknown`, and non-numeric `updatedAt` / `createdAt` become `null`. Extra fields when present: `section`, `projectId`, `modelProvider`, `model`, `originator`. Unknown arguments are rejected before the socket is touched; a response that does not match the pinned schema (including an entry without a string `id`) fails with `reason: "bad-response"`. With client-side filters (`--query`, `--since`, `--active-within`) a page can hold more matches than `--limit`; `nextCursor` is then a `gbot1:` cursor that resumes inside that page, so nothing repeats or is skipped. **Routes, attribution, and loops.** `gbot codex send` runs on the machine that owns `CODEX_HOME`, as the user who owns the socket, with that user's Codex credentials; the socket path comes only from `CODEX_HOME` or `CODEX_APP_SERVER_SOCK`, never from the message or an agent-supplied argument. gbot has no remote transport. A cloud-hosted Grok Bot on the box cannot reach a desktop socket at `/home/box/.codex/...` — use Grok Bot Shell with a machineId to run `gbot` on the user's registered machine (after `codex app-server daemon start` / bootstrap there). `GROK_BOT_CODEX_THREADS=id,id` lets the operator pin `send` to approved threads (`reason: "route-not-allowed"` otherwise). Every send gets a delivery envelope: `messageId` (also sent as Codex's native `clientUserMessageId`), `correlationId` (defaults to the message id), optional `replyTo`, and `hop`. A reply passes the original correlation id and `hop` + 1: @@ -287,6 +288,13 @@ fallback). Claude Code and Cursor bundles also include `/gbot:codex-send`, The tools bundle this repository's gateway client and worker, so the installed plugin does not need `gbot` on `PATH`. +**Replying to a Codex sender.** Messages a Codex thread sends to Grok Bot +(`gbot_send` with a native or explicit `codexThreadId`, the managed bridge, its +returned answers, and `gbot send` run inside a Codex terminal via `$CODEX_THREAD_ID`) +start with `[from Codex thread @ , cwd ; reply: codex_send({threadId:"", message:"..."}) via MCP on (or CLI: gbot codex send "...")]`. +`` is the real hostname (`GROK_BOT_MACHINE_NAME` overrides); unknown fields are left out but the thread id never is. +Find a thread to answer with `codex_threads` (`query`, `activeWithin`, newest activity first). + Install the committed bundle directly from GitHub without cloning or building it: ```sh From 67075b96232b4f6ef454a0793eba31f9f8b91ff1 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:50:56 -0700 Subject: [PATCH 5/5] build: rebuild artifact --- artifact/agent-bundle.compile-evidence.json | 2 +- artifact/agent-bundle.manifest.json | 2 +- artifact/bin/gbot-flight.mjs | 496 +++++++++++---- artifact/bin/gbot.mjs | 580 ++++++++++++++---- artifact/mcp/mcp-grok-bot-b8c2461e-flight.mjs | 556 ++++++++++++++--- artifact/mcp/mcp-grok-bot-b8c2461e.mjs | 556 ++++++++++++++--- artifact/scripts/gbot-relay.mjs | 254 ++++++-- artifact/skills/talk-to-grok-bot/SKILL.md | 14 + .../references/bridge-administration.md | 2 +- 9 files changed, 2026 insertions(+), 436 deletions(-) diff --git a/artifact/agent-bundle.compile-evidence.json b/artifact/agent-bundle.compile-evidence.json index 0b962b9..d7754f8 100644 --- a/artifact/agent-bundle.compile-evidence.json +++ b/artifact/agent-bundle.compile-evidence.json @@ -1 +1 @@ -{"assets":[{"externals":[{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"async_hooks","userRequest":"async_hooks"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"crypto","userRequest":"crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/cli/codex/bridge/run.tsx","src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/chatgpt-desktop/facade.ts","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/40.js","src/cli/skills/add.tsx","src/core/claude-channel.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js","src/core/codex-bridge.js","src/core/relay/control.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/cli/skills/add.tsx","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["src/core/history.js"],"kind":"builtin","request":"node:readline","userRequest":"node:readline"},{"externalType":"module","issuers":["src/core/relay/control.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"},{"externalType":"module","issuers":[".agent-bundle-virtual/bin-gbot-flight-entry.mjs","src/core/relay/managed.js"],"kind":"builtin","request":"node:url","userRequest":"node:url"},{"externalType":"module","issuers":[".agent-bundle-virtual/bin-gbot-flight-entry.mjs"],"kind":"builtin","request":"node:worker_threads","userRequest":"node:worker_threads"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"stream","userRequest":"stream"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.production.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"util","userRequest":"util"}],"packages":["@agent-bundle/runtime","effect","react","react-dom","react-server-dom-rspack","rsc-markdown-stream","zod"],"path":"bin/gbot-flight.mjs","sha256":"ae6e5122b4e1721eacbebea9f3cf8eeaded2ac6afcb094fa5f87ee5d2de40bab"},{"externals":[{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/cli/codex/bridge/run.tsx","src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/667~1.js","src/core/app-session.js","src/core/chatgpt-desktop/facade.ts","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/launch-env.js","node_modules/agent-bundle/dist/terminal-capability.js","src/core/app-session.js","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/40.js","node_modules/agent-bundle/dist/667~1.js","src/cli/skills/add.tsx","src/core/claude-channel.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js","src/core/codex-bridge.js","src/core/relay/control.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/launch-env.js","src/cli/skills/add.tsx","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["src/core/history.js"],"kind":"builtin","request":"node:readline","userRequest":"node:readline"},{"externalType":"module","issuers":["src/core/relay/control.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"},{"externalType":"module","issuers":[".agent-bundle-virtual/bin-gbot-0.mjs",".agent-bundle-virtual/bin-gbot-entry.mjs","src/core/relay/managed.js"],"kind":"builtin","request":"node:url","userRequest":"node:url"},{"externalType":"module","issuers":[".agent-bundle-virtual/bin-gbot-entry.mjs"],"kind":"builtin","request":"node:worker_threads","userRequest":"node:worker_threads"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.production.js"],"kind":"builtin","request":"util","userRequest":"util"}],"packages":["@agent-bundle/runtime","agent-bundle","effect","react","react-dom","react-server-dom-rspack","rsc-markdown-stream","zod"],"path":"bin/gbot.mjs","sha256":"f879db18627f1c6c71a2e194db8f77a36f79eb1c58ae0ef400f67afd395fedb8"},{"externals":[{"externalType":"module","issuers":["src/core/claude-channel.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/agent-bundle/dist/launch-env.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["src/core/claude-channel.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["src/core/claude-channel.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/agent-bundle/dist/launch-env.js","src/core/claude-channel.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["node_modules/@modelcontextprotocol/server/dist/shimsNode.mjs","node_modules/agent-bundle/node_modules/@modelcontextprotocol/server/dist/shimsNode.mjs"],"kind":"builtin","request":"node:process","userRequest":"node:process"},{"externalType":"module","issuers":[".agent-bundle-virtual/mcp-claude-channel-8029413c-1.mjs"],"kind":"builtin","request":"node:url","userRequest":"node:url"}],"packages":["@modelcontextprotocol/core","@modelcontextprotocol/server","agent-bundle","zod"],"path":"mcp/mcp-claude-channel-8029413c.mjs","sha256":"46c0e5abb42f0dcd1152ec9d6bf5fed42c3bcb109f89312bfaa9870ecc059fe3"},{"externals":[{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"async_hooks","userRequest":"async_hooks"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"crypto","userRequest":"crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/chatgpt-desktop/facade.ts","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/40.js","src/core/claude-channel.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js","src/core/codex-bridge.js","src/core/relay/control.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["src/core/relay/control.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"},{"externalType":"module","issuers":[".agent-bundle-virtual/mcp-grok-bot-b8c2461e-flight-entry.mjs","src/core/relay/managed.js"],"kind":"builtin","request":"node:url","userRequest":"node:url"},{"externalType":"module","issuers":[".agent-bundle-virtual/mcp-grok-bot-b8c2461e-flight-entry.mjs"],"kind":"builtin","request":"node:worker_threads","userRequest":"node:worker_threads"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"stream","userRequest":"stream"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.production.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"util","userRequest":"util"}],"packages":["@agent-bundle/runtime","agent-bundle","effect","react","react-dom","react-server-dom-rspack","rsc-markdown-stream","zod"],"path":"mcp/mcp-grok-bot-b8c2461e-flight.mjs","sha256":"8d49ea30728efd1025b90c50ff21150907c7fce7dba95d851a606f0bafbaa4aa"},{"externals":[{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/@agent-bundle/runtime/dist/lineage.js","node_modules/agent-bundle/dist/667~1.js","node_modules/agent-bundle/dist/mcp-server-runtime.js","src/core/app-session.js","src/core/chatgpt-desktop/facade.ts","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/launch-env.js","node_modules/agent-bundle/dist/terminal-capability.js","src/core/app-session.js","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/40.js","node_modules/agent-bundle/dist/667~1.js","src/core/claude-channel.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js","src/core/codex-bridge.js","src/core/relay/control.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/launch-env.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["node_modules/agent-bundle/node_modules/@modelcontextprotocol/server/dist/shimsNode.mjs"],"kind":"builtin","request":"node:process","userRequest":"node:process"},{"externalType":"module","issuers":["src/core/relay/control.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"},{"externalType":"module","issuers":[".agent-bundle-virtual/mcp-grok-bot-b8c2461e-1.mjs",".agent-bundle-virtual/mcp-grok-bot-b8c2461e-2.mjs","src/core/relay/managed.js"],"kind":"builtin","request":"node:url","userRequest":"node:url"},{"externalType":"module","issuers":["node_modules/agent-bundle/dist/mcp-server-runtime.js"],"kind":"builtin","request":"node:worker_threads","userRequest":"node:worker_threads"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.production.js"],"kind":"builtin","request":"util","userRequest":"util"}],"packages":["@agent-bundle/runtime","@modelcontextprotocol/core","@modelcontextprotocol/server","agent-bundle","effect","react","react-dom","react-server-dom-rspack","rsc-markdown-stream","zod"],"path":"mcp/mcp-grok-bot-b8c2461e.mjs","sha256":"6203d726018516415799977b5851f121ca0d05d20e1d5b64eea43089ae06785b"},{"externals":[{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state.js"],"kind":"builtin","request":"node:assert/strict","userRequest":"node:assert/strict"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state/sqlite.js","src/core/app-session.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/codex.js","src/core/relay/control.js","src/core/relay/engine.js","src/core/relay/profile.js","src/core/relay/records.js","src/core/relay/state.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state/sqlite.js","src/core/app-session.js","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/codex.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["src/core/relay/ownership.js","src/core/relay/state.js","src/core/relay/worker.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/codex-bridge.js","src/core/relay/control.js","src/core/relay/ownership.js","src/core/relay/worker.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["src/core/app-session.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/engine.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state/sqlite.js","src/core/app-session.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/engine.js","src/core/relay/ownership.js","src/core/relay/profile.js","src/core/relay/state.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"import","issuers":["src/core/relay/ownership.js"],"kind":"builtin","request":"node:sqlite","userRequest":"node:sqlite"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state/sqlite.js"],"kind":"builtin","request":"node:sqlite","userRequest":"node:sqlite"},{"externalType":"module","issuers":["src/core/relay/control.js","src/core/relay/worker.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"}],"packages":["@agent-bundle/runtime","effect","zod"],"path":"scripts/gbot-relay.mjs","sha256":"9d35ecc3eca0703941fbb8dd93c86d065f609d3e1eedbfef69b90597fb490323"}],"coverage":{"rewritable":false,"unobserved":["import()","require()","require.resolve(…)","createRequire(…)(…)","import.meta.resolve(…)"]},"policy":{"name":"closed-world-externals","revision":1},"producer":{"name":"agent-bundle","rspack":"2.2.8","version":"0.3.2"}} +{"assets":[{"externals":[{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"async_hooks","userRequest":"async_hooks"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"crypto","userRequest":"crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/cli/codex/bridge/run.tsx","src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/chatgpt-desktop/facade.ts","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/40.js","src/cli/skills/add.tsx","src/core/claude-channel.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js","src/core/codex-bridge.js","src/core/relay/control.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/relay/profile.js","src/core/sender-prefix.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/cli/skills/add.tsx","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["src/core/history.js"],"kind":"builtin","request":"node:readline","userRequest":"node:readline"},{"externalType":"module","issuers":["src/core/relay/control.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"},{"externalType":"module","issuers":[".agent-bundle-virtual/bin-gbot-flight-entry.mjs","src/core/relay/managed.js"],"kind":"builtin","request":"node:url","userRequest":"node:url"},{"externalType":"module","issuers":[".agent-bundle-virtual/bin-gbot-flight-entry.mjs"],"kind":"builtin","request":"node:worker_threads","userRequest":"node:worker_threads"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"stream","userRequest":"stream"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.production.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"util","userRequest":"util"}],"packages":["@agent-bundle/runtime","effect","react","react-dom","react-server-dom-rspack","rsc-markdown-stream","zod"],"path":"bin/gbot-flight.mjs","sha256":"0836c81ba857d4a33727ba4c1d4a7ca9c81324ac22b198c8062751dfa5e5b14f"},{"externals":[{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/cli/codex/bridge/run.tsx","src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/667~1.js","src/core/app-session.js","src/core/chatgpt-desktop/facade.ts","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/launch-env.js","node_modules/agent-bundle/dist/terminal-capability.js","src/core/app-session.js","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/40.js","node_modules/agent-bundle/dist/667~1.js","src/cli/skills/add.tsx","src/core/claude-channel.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js","src/core/codex-bridge.js","src/core/relay/control.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/relay/profile.js","src/core/sender-prefix.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/launch-env.js","src/cli/skills/add.tsx","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/history.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["src/core/history.js"],"kind":"builtin","request":"node:readline","userRequest":"node:readline"},{"externalType":"module","issuers":["src/core/relay/control.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"},{"externalType":"module","issuers":[".agent-bundle-virtual/bin-gbot-0.mjs",".agent-bundle-virtual/bin-gbot-entry.mjs","src/core/relay/managed.js"],"kind":"builtin","request":"node:url","userRequest":"node:url"},{"externalType":"module","issuers":[".agent-bundle-virtual/bin-gbot-entry.mjs"],"kind":"builtin","request":"node:worker_threads","userRequest":"node:worker_threads"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.production.js"],"kind":"builtin","request":"util","userRequest":"util"}],"packages":["@agent-bundle/runtime","agent-bundle","effect","react","react-dom","react-server-dom-rspack","rsc-markdown-stream","zod"],"path":"bin/gbot.mjs","sha256":"7a7e23153fa84d0e1bcc2e40d7d8e213ea129c709d000268cfa7b19425389073"},{"externals":[{"externalType":"module","issuers":["src/core/claude-channel.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/agent-bundle/dist/launch-env.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["src/core/claude-channel.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["src/core/claude-channel.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/agent-bundle/dist/launch-env.js","src/core/claude-channel.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["node_modules/@modelcontextprotocol/server/dist/shimsNode.mjs","node_modules/agent-bundle/node_modules/@modelcontextprotocol/server/dist/shimsNode.mjs"],"kind":"builtin","request":"node:process","userRequest":"node:process"},{"externalType":"module","issuers":[".agent-bundle-virtual/mcp-claude-channel-8029413c-1.mjs"],"kind":"builtin","request":"node:url","userRequest":"node:url"}],"packages":["@modelcontextprotocol/core","@modelcontextprotocol/server","agent-bundle","zod"],"path":"mcp/mcp-claude-channel-8029413c.mjs","sha256":"46c0e5abb42f0dcd1152ec9d6bf5fed42c3bcb109f89312bfaa9870ecc059fe3"},{"externals":[{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"async_hooks","userRequest":"async_hooks"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"crypto","userRequest":"crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/chatgpt-desktop/facade.ts","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/40.js","src/core/claude-channel.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js","src/core/codex-bridge.js","src/core/relay/control.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/profile.js","src/core/sender-prefix.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["src/core/relay/control.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"},{"externalType":"module","issuers":[".agent-bundle-virtual/mcp-grok-bot-b8c2461e-flight-entry.mjs","src/core/relay/managed.js"],"kind":"builtin","request":"node:url","userRequest":"node:url"},{"externalType":"module","issuers":[".agent-bundle-virtual/mcp-grok-bot-b8c2461e-flight-entry.mjs"],"kind":"builtin","request":"node:worker_threads","userRequest":"node:worker_threads"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"stream","userRequest":"stream"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.production.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-server.node.production.js"],"kind":"builtin","request":"util","userRequest":"util"}],"packages":["@agent-bundle/runtime","agent-bundle","effect","react","react-dom","react-server-dom-rspack","rsc-markdown-stream","zod"],"path":"mcp/mcp-grok-bot-b8c2461e-flight.mjs","sha256":"b7ca9c0235dbde3ebddf98b4c7b024e9872b529f42b84a70370bdba8d429568d"},{"externals":[{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/@agent-bundle/runtime/dist/lineage.js","node_modules/agent-bundle/dist/667~1.js","node_modules/agent-bundle/dist/mcp-server-runtime.js","src/core/app-session.js","src/core/chatgpt-desktop/facade.ts","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/launch-env.js","node_modules/agent-bundle/dist/terminal-capability.js","src/core/app-session.js","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/40.js","node_modules/agent-bundle/dist/667~1.js","src/core/claude-channel.js","src/core/relay/managed.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/claude-channel.js","src/core/codex-bridge.js","src/core/relay/control.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/profile.js","src/core/sender-prefix.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/49.js","node_modules/agent-bundle/dist/launch-env.js","src/core/app-session.js","src/core/claude-channel.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"module","issuers":["node_modules/agent-bundle/node_modules/@modelcontextprotocol/server/dist/shimsNode.mjs"],"kind":"builtin","request":"node:process","userRequest":"node:process"},{"externalType":"module","issuers":["src/core/relay/control.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"},{"externalType":"module","issuers":[".agent-bundle-virtual/mcp-grok-bot-b8c2461e-1.mjs",".agent-bundle-virtual/mcp-grok-bot-b8c2461e-2.mjs","src/core/relay/managed.js"],"kind":"builtin","request":"node:url","userRequest":"node:url"},{"externalType":"module","issuers":["node_modules/agent-bundle/dist/mcp-server-runtime.js"],"kind":"builtin","request":"node:worker_threads","userRequest":"node:worker_threads"},{"externalType":"node-commonjs","issuers":["node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.development.js","node_modules/react-server-dom-rspack/cjs/react-server-dom-rspack-client.node.production.js"],"kind":"builtin","request":"util","userRequest":"util"}],"packages":["@agent-bundle/runtime","@modelcontextprotocol/core","@modelcontextprotocol/server","agent-bundle","effect","react","react-dom","react-server-dom-rspack","rsc-markdown-stream","zod"],"path":"mcp/mcp-grok-bot-b8c2461e.mjs","sha256":"0195717cbb211454a6b36694d8c3e620298585cbadeece3ae73f9539b0ce52f5"},{"externals":[{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state.js"],"kind":"builtin","request":"node:assert/strict","userRequest":"node:assert/strict"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/736.js"],"kind":"builtin","request":"node:async_hooks","userRequest":"node:async_hooks"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/302.js"],"kind":"builtin","request":"node:buffer","userRequest":"node:buffer"},{"externalType":"module","issuers":["src/core/app-session.js","src/core/codex-bridge.js","src/core/desktop-shim.js"],"kind":"builtin","request":"node:child_process","userRequest":"node:child_process"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state/sqlite.js","src/core/app-session.js","src/core/codex-bridge.js","src/core/gateway.js","src/core/relay/codex.js","src/core/relay/control.js","src/core/relay/engine.js","src/core/relay/profile.js","src/core/relay/records.js","src/core/relay/state.js","src/core/store.js"],"kind":"builtin","request":"node:crypto","userRequest":"node:crypto"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state/sqlite.js","src/core/app-session.js","src/core/codex-bridge.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/codex.js","src/core/store.js"],"kind":"builtin","request":"node:fs","userRequest":"node:fs"},{"externalType":"module","issuers":["src/core/relay/ownership.js","src/core/relay/state.js","src/core/relay/worker.js"],"kind":"builtin","request":"node:fs/promises","userRequest":"node:fs/promises"},{"externalType":"module","issuers":["src/core/codex-bridge.js","src/core/relay/control.js","src/core/relay/ownership.js","src/core/relay/worker.js"],"kind":"builtin","request":"node:net","userRequest":"node:net"},{"externalType":"module","issuers":["src/core/app-session.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/engine.js","src/core/relay/profile.js","src/core/sender-prefix.js","src/core/store.js"],"kind":"builtin","request":"node:os","userRequest":"node:os"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state/sqlite.js","src/core/app-session.js","src/core/codex-bridge.js","src/core/codex/remote-control.js","src/core/desktop-shim.js","src/core/relay/engine.js","src/core/relay/ownership.js","src/core/relay/profile.js","src/core/relay/state.js","src/core/store.js"],"kind":"builtin","request":"node:path","userRequest":"node:path"},{"externalType":"import","issuers":["src/core/relay/ownership.js"],"kind":"builtin","request":"node:sqlite","userRequest":"node:sqlite"},{"externalType":"module","issuers":["node_modules/@agent-bundle/runtime/dist/state/sqlite.js"],"kind":"builtin","request":"node:sqlite","userRequest":"node:sqlite"},{"externalType":"module","issuers":["src/core/relay/control.js","src/core/relay/worker.js"],"kind":"builtin","request":"node:string_decoder","userRequest":"node:string_decoder"}],"packages":["@agent-bundle/runtime","effect","zod"],"path":"scripts/gbot-relay.mjs","sha256":"e9e91cfa084e23dadd45846ba74bab064e693ee68b4c76bcaef9a9091489fcb4"}],"coverage":{"rewritable":false,"unobserved":["import()","require()","require.resolve(…)","createRequire(…)(…)","import.meta.resolve(…)"]},"policy":{"name":"closed-world-externals","revision":1},"producer":{"name":"agent-bundle","rspack":"2.2.8","version":"0.3.2"}} diff --git a/artifact/agent-bundle.manifest.json b/artifact/agent-bundle.manifest.json index c874107..74afcf8 100644 --- a/artifact/agent-bundle.manifest.json +++ b/artifact/agent-bundle.manifest.json @@ -1 +1 @@ -{"application":{"description":"Message Grok Bot from Codex, Claude Code, and Cursor. Codex/Claude tools use local sockets on the user's registered machines only (no remote transport); from the Grok Bot box, run gbot via Grok Bot Shell with a machineId.","id":"plugin:gbot","name":"gbot","version":"0.11.3"},"compiler":{"adapters":[{"adapterRevision":"1.28.0","host":"claude","observedVersion":"2.1.260","schemas":[{"name":"hooks","revision":"2.1.260","sha256":"0cdfc5eb5201f2c3091768559ac82f4c563ccb1b7bce7a39d5f99e5f404654cb"},{"name":"lsp","revision":"2.1.260","sha256":"b4419c5d857267c7e2b21e3e1eb98b4fdc302c87109007190d3258e6ba7096e4"},{"name":"marketplace","revision":"2.1.260","sha256":"31ee4cc43ba5ce2be248030a69da2d31171550b2cc51c1fcb9f788a8ab92783d"},{"name":"mcp","revision":"2.1.260","sha256":"edd4770e41d6aee5beae1ff918d33139613a243e454ecbd52b72fa824be4a662"},{"name":"monitors","revision":"2.1.260","sha256":"6378d94b51fb7c784eaee178237008a03da0f889d0520d57486784954a1d484c"},{"name":"plugin","revision":"2.1.260","sha256":"2a976091b81ad07ae8eca57f6f9c5749efeba17fa089a0c12b6ca84d6e70f118"},{"name":"settings","revision":"2.1.260","sha256":"2bbca553621dbf9433a9b7d1ff7952543a368434f2d999a4e4e360b95b6d4c3d"},{"name":"theme","revision":"2.1.260","sha256":"9931264e6f5a1d4b3b854ce7a17d602c9ba1b57cc1991f1d3991b316eaa81ac2"}]},{"adapterRevision":"1.13.0","host":"codex","observedVersion":"0.147.0","schemas":[{"name":"app","revision":"0.147.0","sha256":"01c720a645e437bf0c4f8c26fd4cb5a13988e5649e4a8562ee23a1d4b7355c6a"},{"name":"hooks","revision":"0.147.0","sha256":"175b859eb8e85bd287d85ee840d97c3f5c2d0dda3223507a796d158e3770eeba"},{"name":"marketplace","revision":"0.147.0","sha256":"fbccce3ade39e1b077fcb440e60260de6e811e8c2d222b2ae0fe8fe47706b470"},{"name":"mcp","revision":"0.147.0","sha256":"75bd50f9fcb85c2e8d43bc132d61c172a02f28ea8bb77389816ae77b14a4257e"},{"name":"plugin","revision":"0.147.0","sha256":"074c6c71966a3e6560ccbceb8d82ec6a40cb1eccee2f2d863fb4ef1e2276a814"}]},{"adapterRevision":"1.13.0","host":"cursor","observedVersion":"2026-08-28","schemas":[{"name":"hooks","revision":"2026-08-28","sha256":"06154b7afa0861df462130b988912b897e7ccf962b8dd20c09193100bcde5d81"},{"name":"marketplace","revision":"2026-08-28","sha256":"1aae96a24c2796419933bc8bfe3a1255394e7199c35740b36325e0ce6dbc253d"},{"name":"mcp","revision":"2026-08-28","sha256":"f3fa4615afefe004c4fbcc09e635d890df0f1ec0cb39540feab72cbd3a31d844"},{"name":"plugin","revision":"2026-08-28","sha256":"a393b758901803fcf5cfe0d77bda8a83e987d32c3377dfce2d9edf445af884ed"}]},{"adapterRevision":"1.10.0","host":"portable","observedVersion":"1.0.0","schemas":[{"name":"mcp","revision":"1.0.0","sha256":"6539175bfcdf43085855183e86da40ea94b166547a72b47ae9a0a390516d3acb"},{"name":"plugin","revision":"1.0.0","sha256":"0a4aad95ce337878ad38802ebf0daa3fde76abe3f65400c86bcbb1ec0b3ab883"}]}],"agentSkills":{"schemaSha256":"6d06b61e423317421de2295ea1fd0c7b4491bfa36c5b7705c28616dfe76d4047","sourceRevision":"69ef37e9424c0a7ea9dd2293b559e43ec8176379","specification":"https://raw.githubusercontent.com/agentskills/agentskills/69ef37e9424c0a7ea9dd2293b559e43ec8176379/docs/specification.mdx"},"producer":{"name":"agent-bundle","version":"0.3.2"},"project":{"configDigest":"7718be28a54eb7ec9e28b9653ef671683604436af21e1eda99c11098f43e278f","configPath":"agent-bundle.config.ts","modelDigest":"7be2b40816cb6ea9b0304810697cf85136d0db74b68e79b72af1b8fd02c1fa75","packageName":"grok-bot-cli","packageVersion":"0.11.3","revision":"bf6d6d77c4d182c106035995fc2373d91fa97b51fe2fbe2e6bb07852d8271f80","sourceInputs":[{"executable":false,"path":".changeset/config.json","sha256":"0a97ce5d0488bada887ee9ea3726edecc727454b7da0294f1b5fe4947f48ee7c"},{"executable":false,"path":".changeset/README.md","sha256":"495bd4805f8362853bce99689c1cd75db8c475dfa38930619d2e197d7554db27"},{"executable":false,"path":".github/workflows/changeset.yml","sha256":"0139beb8a3dc0e95126c9701d09251a879331b1e8c5540bbfc69848525b40f23"},{"executable":false,"path":".github/workflows/ci.yml","sha256":"17a58cf5ceff03b7922d15c9b0eea11ae3e0fd00a581ff6881f69cf795f3ec0b"},{"executable":false,"path":".github/workflows/release.yml","sha256":"9c97360a2221fca9317edcac0eb343298c765e3b34bd048f916c47533dd90311"},{"executable":false,"path":".gitignore","sha256":"30aaeac24084f0a642d811aa493fc51b0fd3eddff322d359c39c573d8394ff3e"},{"executable":false,"path":".npmrc","sha256":"da47110e4c2d7cd216cd495b604ca78bd0f5caaca32da4837ec0efa6f967bba0"},{"executable":false,"path":"agent-bundle.config.ts","sha256":"7718be28a54eb7ec9e28b9653ef671683604436af21e1eda99c11098f43e278f"},{"executable":false,"path":"AGENTS.md","sha256":"e18ce90a031c533e7226789b97f6bce4aa7994b672544e0f425d20cc3bc15d29"},{"executable":false,"path":"CHANGELOG.md","sha256":"b6c5da29bce3a450517ce7bf023f48ccd10d2b627898c78f87b1ea486393871d"},{"executable":false,"path":"demo/grok-bot-cli-demo.gif","sha256":"0fe01e15fd2abbbc5cc3313e42931d404d3a320764e22fdcfb995f1a45dd73cd"},{"executable":false,"path":"demo/grok-bot-cli-demo.mp4","sha256":"b6ed66e43616674096c2f0a4a4da46fe4693c681833eab013f872a66b9ff933c"},{"executable":false,"path":"docs/chatgpt-desktop-cdp.md","sha256":"6dd6cfe00e9a888c1ced79f1db85744f9c92affef8a78126e22ea5205e76b732"},{"executable":false,"path":"docs/codex-busy-threads.md","sha256":"42509e8e4c2b519949f06d4e7028b8973d56f8fc0cd98decdb231375bb49d38d"},{"executable":false,"path":"docs/codex-duplex-architecture.md","sha256":"792f1be8bad508b042c5813c1fc3b7ea5ac87032803227830666727306e55fa2"},{"executable":false,"path":"docs/verification/2026-09-15-duplex.md","sha256":"c7d97f709a3c2d851c0a24690321bbda161ec925b4143a456b9951e174bf75df"},{"executable":false,"path":"LICENSE","sha256":"bc48c8a0f6b6e45842e574c79a6b955fe683ed13f48a50cc08bcccdb1a59fe59"},{"executable":false,"path":"package-lock.json","sha256":"1a446dd5db9fb93ef4fbe7a446139361f940d71985a3b74f7ea4af9603077975"},{"executable":false,"path":"package.json","sha256":"b273cd753bb56a470c0b7ac145ac84d06a54cbcd794811ad460395228c5ba20d"},{"executable":false,"path":"README.md","sha256":"efe1a601a87648defca4b223f5b6828ead8f17fc15ad1fb8eeac23b9b61b8b29"},{"executable":false,"path":"renovate.json","sha256":"e80b4e42a3043bc12fa0640db4bac392d2bf770acf841360d7c8ceeeac2ec1a9"},{"executable":false,"path":"rstest.route-unit.config.ts","sha256":"7286e20dc3d4162673e7c3dfe824db00307e1fda178410f23044a97286d141f2"},{"executable":false,"path":"scripts/run-unit-tests.mjs","sha256":"483f91b4856ce294a483dd2e62ca53bf09301adbc4c5fc9571da0e1d28049bc6"},{"executable":false,"path":"src/cli/_shared.ts","sha256":"555210759d9b2e2e60a01452c137abd73bad42bfab8b2311b66a3ab97f4ee5e9"},{"executable":false,"path":"src/cli/approvals/list.tsx","sha256":"8d21320b6cd9d6b2a266fd30196b8a439960f865a6f0a5dacf5845d64ed7388c"},{"executable":false,"path":"src/cli/approvals/respond.tsx","sha256":"7d9fe6e641deb08f444684733daac6da47fb472d90ed0e9ff77892f376a87255"},{"executable":false,"path":"src/cli/bots/create.tsx","sha256":"9f7a73a0595b642dd77f008ad596bcafd00fc5846ec1abff2ce62819d983eb84"},{"executable":false,"path":"src/cli/bots/delete.tsx","sha256":"126b53ac1da4a657f22d1a6770ddbab2cc66715c811de0873d50016bbe39cbf2"},{"executable":false,"path":"src/cli/bots/get.tsx","sha256":"f0c752a3b498819083a8ee5aa918d275727f1cc94d8774d8c84ac74db66e8a71"},{"executable":false,"path":"src/cli/bots/list.tsx","sha256":"21c0f7e39005860dfc2514b71f745bb4cab29d409ef2cff26f8759bb0fd261c1"},{"executable":false,"path":"src/cli/bots/update.tsx","sha256":"33b7f5aafbf931cf3cb5ecf423a76dacd09adb117a7d5490050639ae7f4210dd"},{"executable":false,"path":"src/cli/chatgpt-desktop/hosts.tsx","sha256":"64e3e873115a4f5c2b6a7fd68236dbf2ca4e4a880ba97bdd7409b48931bca632"},{"executable":false,"path":"src/cli/chatgpt-desktop/read.tsx","sha256":"11c86f604c2ee405f7544394db60ee1b36917d0b90769d441fcd361b5f0fe038"},{"executable":false,"path":"src/cli/chatgpt-desktop/search.tsx","sha256":"0dc3acdea178ff14d6c1c4b8b3bf1e18af47984f63b8ed8c41483e4da4b72f08"},{"executable":false,"path":"src/cli/chatgpt-desktop/send.tsx","sha256":"b801a028980e60fe37dca56e86887a1e2b0b8ce80ce77b379e7375d2e4544d5e"},{"executable":false,"path":"src/cli/chatgpt-desktop/status.tsx","sha256":"141b7b6db6d6f9236dd5343ca9495200752937b05764ad7fa7261631c2db5bbc"},{"executable":false,"path":"src/cli/chatgpt-desktop/threads.tsx","sha256":"d0a33935d992af349c52ef448622da5e460b4af1a9474aac60994295245b43ad"},{"executable":false,"path":"src/cli/claude/send.tsx","sha256":"d650caadec248aa59530d124ca6186c45d9f9fe1fb0f9c805e9eef6dc9f06d92"},{"executable":false,"path":"src/cli/codex/bridge/respond.tsx","sha256":"9d3a6af4904af6e44583dfb4ef317b3fe1045a78e765fc27406eaca9bcadcd13"},{"executable":false,"path":"src/cli/codex/bridge/run.tsx","sha256":"a49d334bebb00db62ad2c54370a47ec2c9119b4c07eb6ba11fc4bba4dd8e4217"},{"executable":false,"path":"src/cli/codex/bridge/start.tsx","sha256":"9e423cf5d65168606f6235baa2bcd127eb949647f7a4dee284d75f831474524d"},{"executable":false,"path":"src/cli/codex/bridge/status.tsx","sha256":"c801f69080985c87025429fb136487acdfac093acb07241b3417ea9a83915a18"},{"executable":false,"path":"src/cli/codex/bridge/stop.tsx","sha256":"6710e298a21d124c442d5aa1a3744280e5cd4df93213797f2ea3c0654174184a"},{"executable":false,"path":"src/cli/codex/desktop-shim.tsx","sha256":"fa3d88d11895bc4a15700bd590c055aa392b2b0e0c1185c52da233a23589aba0"},{"executable":false,"path":"src/cli/codex/list-threads.tsx","sha256":"6d754db238457ec63af76c0b34af47f9dc3888b2bae7cebaa7ed01135c7946e0"},{"executable":false,"path":"src/cli/codex/new.tsx","sha256":"11d0658c1a3e7173d53b71446b184fccccd867baefc6f733e43a9d543ca26ec9"},{"executable":false,"path":"src/cli/codex/queue.tsx","sha256":"7993ac5b827042cd95041775b183fde2d112b5ba7d5c82098e778a44e473826d"},{"executable":false,"path":"src/cli/codex/send.tsx","sha256":"a1b30f053a9e65bac561cd04d1361e292e2c672bbf69a6d76d2bdda441c46757"},{"executable":false,"path":"src/cli/codex/status.tsx","sha256":"b8c31001cb2892c1bfccf502f9776ee06998eac4fc0356f92936fa2c34f272d8"},{"executable":false,"path":"src/cli/codex/wait.tsx","sha256":"0a4cc6c440ad496682031658bda375fee29f5c346d833618d4f143de29b351cd"},{"executable":false,"path":"src/cli/codex/watch.tsx","sha256":"3280f42d15941cfd00b3727d9e271972c39165bd28db8f56acca5664d777cb4d"},{"executable":false,"path":"src/cli/doctor.tsx","sha256":"c30ce4e57fe707d36de29700abf5a2c56834bb4fb3adf2a70bb1089b4150ddc8"},{"executable":false,"path":"src/cli/groups/add.tsx","sha256":"2a5de115852f0ca6a6638300bd5006862a02a2f1e2f527b6fd680f610c1d777a"},{"executable":false,"path":"src/cli/groups/create.tsx","sha256":"da3f2539f338063daf51b80d86c27b2752f0e4a0334078d11508e27981590fa3"},{"executable":false,"path":"src/cli/groups/delete.tsx","sha256":"2d4e91113a2c24cefefcfd464513918791592b5e8734a4ef901eabe42c9c7289"},{"executable":false,"path":"src/cli/groups/get.tsx","sha256":"efed88fb3ab7292d60d6532f1f966f784ba3376b7826c9f3e5028467f86241e9"},{"executable":false,"path":"src/cli/groups/list.tsx","sha256":"f3cd229d41dd389b767447a04267700ab2293eae87a878f7d88149cb5798f4a6"},{"executable":false,"path":"src/cli/groups/members.tsx","sha256":"9b9eaecb65ea995006eff1b24a287110d16bf4830a0b0d07221c2f1317853641"},{"executable":false,"path":"src/cli/groups/remove.tsx","sha256":"96dd85d1b9732681ce9dc126ac3ae562d3f287f4c28e36b9a8f8c301dc93f63d"},{"executable":false,"path":"src/cli/groups/set.tsx","sha256":"4f9d90db612f14ddbb6d2afa5e45b66f044aed661ff95415e567e1be3b6108c6"},{"executable":false,"path":"src/cli/groups/update.tsx","sha256":"f44305815ddb6e27286f97ef68c04cfa5548acd5f04b1aba10ee7ce3cdbfc851"},{"executable":false,"path":"src/cli/history.tsx","sha256":"5151b48113b4ba0516bacabfabcd48e3256ead807c34d914deb84f31ded0b062"},{"executable":false,"path":"src/cli/send.tsx","sha256":"fd16790cfcde1c15328c3979acc0664112d5cf40d3f00a24da906e00dd63153e"},{"executable":false,"path":"src/cli/skills/add.tsx","sha256":"fbde237d172c026d7912174e705c03cbc9d74dad7806fc58c6ceb43127c69ba6"},{"executable":false,"path":"src/cli/skills/list.tsx","sha256":"34f255687c69aaf598a1dc54220453b57c46ed9ab4a168648d9c7eca6535ebae"},{"executable":false,"path":"src/cli/skills/remove.tsx","sha256":"21662c80a62f276c2dfd840a328e9665c0c5f63959a239d4dd877372c46f60d0"},{"executable":false,"path":"src/cli/thread.tsx","sha256":"29ab775936fa2987cb789754a44888fc52bdaad07180c5471122dda508cfd0c2"},{"executable":false,"path":"src/commands/codex-send.md","sha256":"1f88961a6656ae94a5cadd86e25eeaae111ee4c6aaad64f32917ac0c9d8410b8"},{"executable":false,"path":"src/commands/codex-threads.md","sha256":"e17b90cb8b0115a53161f83797ec55ca65e81600396cf3ea896b6306d2fb2dd2"},{"executable":false,"path":"src/commands/codex-wait.md","sha256":"acd0aaf00329256b874ec59666d2d803bbaf86b1d249d996a5f226b559619530"},{"executable":false,"path":"src/core/app-session.js","sha256":"2b2eb53ec3f4c7ea0dccf269fa9720af6f1ce36b8ca36e889d2bb271a092717d"},{"executable":false,"path":"src/core/chatgpt-desktop/adapter.ts","sha256":"5a0a4f2cea9f1fc1a739c534aed3979c28e0bd9c057b8475e6251974ad44ed7a"},{"executable":false,"path":"src/core/chatgpt-desktop/app-server-fallback.ts","sha256":"44002096eea29b5ea26d5b3d186b5616fcdab570888e3cb86fd4b5c5804af04c"},{"executable":false,"path":"src/core/chatgpt-desktop/cdp-adapter.ts","sha256":"db60fdd3be0259a6c76cad7d8ff86eddc6acbbd21c5f20d6aeffff5390063efa"},{"executable":false,"path":"src/core/chatgpt-desktop/cdp-dom.ts","sha256":"a122fb76626006fa8dedb7088f9b5533a8058c3a58838692b168e0753b7c89eb"},{"executable":false,"path":"src/core/chatgpt-desktop/cdp-session.ts","sha256":"8d6512ee80b179eedf54504110c1e88c5233b0b922667b00f87751452164cc00"},{"executable":false,"path":"src/core/chatgpt-desktop/errors.ts","sha256":"941ce4a9148fc53086cce64336dba473c1f7e4138774fd50a8ae524dcc05d34d"},{"executable":false,"path":"src/core/chatgpt-desktop/facade.ts","sha256":"bc9ac3bfd24db8458af6d20893fb3ab2ed701778f709aadbd141d61ed6c6c29b"},{"executable":false,"path":"src/core/chatgpt-desktop/index.ts","sha256":"591e6968c008cc75827da94b91c0ea15e573640876814e35e2470342dc8bccf9"},{"executable":false,"path":"src/core/chatgpt-desktop/loopback.ts","sha256":"b746681e5c45c67445e6620f850eff7c4627e13979747a7f686374c10a51f52f"},{"executable":false,"path":"src/core/chatgpt-desktop/payload-budget.ts","sha256":"89410474315b3769bad58d3ab61999e169410b7d1fdc20819efb4ee9c82fe1ac"},{"executable":false,"path":"src/core/chatgpt-desktop/project-state.ts","sha256":"b33e55b6d6abf15f3d7d1489b8b178d4e907ea83ed1a47d88f8f178a574709f8"},{"executable":false,"path":"src/core/chatgpt-desktop/relaunch.ts","sha256":"14851e115de7c45e256c4b9c3829dc4e796f1d989cf67d65115701a30b6d3a81"},{"executable":false,"path":"src/core/chatgpt-desktop/remote-threads.ts","sha256":"ed93418ff5d2bb51016783e7b0a458805e709b212974a66be804ddb9f7038033"},{"executable":false,"path":"src/core/chatgpt-desktop/routes.ts","sha256":"ccf8cde780da6e6e03f11e4dcc0d9d6bc4a6a3fd20d3210e74f0217e3660b7e1"},{"executable":false,"path":"src/core/chatgpt-desktop/thread-ids.ts","sha256":"0fe25e9d32c078bd9e7a171ab4bc4ee0b15190cd6d6c4d3b345926b3c608e082"},{"executable":false,"path":"src/core/chatgpt-desktop/types.ts","sha256":"59f89694eed34206e32db2a0afb48670bb164a4ffffacb907c8629bb0ce4bcca"},{"executable":false,"path":"src/core/claude-channel.js","sha256":"01ac7daef748a11bc99e132950ed7c59f50442e417eecf894b59cb4bb484202f"},{"executable":false,"path":"src/core/claude-routes.ts","sha256":"d34ddf25b8634ef86d46ab663f30a49aaedf87f8dc98e4036f84c1c88efa4083"},{"executable":false,"path":"src/core/codex-bridge.js","sha256":"78f0fbba7a5053eb78717c5885a9306871f08beaf39da90df1f815a66b1288d9"},{"executable":false,"path":"src/core/codex/contract.js","sha256":"16bcbd0fc09844166c52694ebb1075e60b91296a8f04fb02ad061c30b0e9c591"},{"executable":false,"path":"src/core/codex/conversation.js","sha256":"05abb2253480d0793bf5f6b3db17c47e7d154973747074c7c76a79e6f61b7deb"},{"executable":false,"path":"src/core/codex/remote-control.js","sha256":"52565007799e98c3bff4297287d8e53005e285a95bab9e4e4d0a088bded4fa8e"},{"executable":false,"path":"src/core/codex/routes.ts","sha256":"ae29d05e06cdd8e90bcdd723d277af748e16dc676db1e4b938b7cdd36340ed17"},{"executable":false,"path":"src/core/codex/thread-id.js","sha256":"4eb6c1929c2e7687ed6c1422789fa01c3e1c556ead7d16355eafbae46a7126f4"},{"executable":false,"path":"src/core/commands.js","sha256":"3ad8fafb86744a57992da93ad838ade0e9acb1b7ca09b829cefadbf2781be0c9"},{"executable":false,"path":"src/core/desktop-shim-bridge.js","sha256":"58f3f39b8527adf58f57313e02e34322b203b8c38d1acfbad419a8b9af214443"},{"executable":false,"path":"src/core/desktop-shim.js","sha256":"500b8617bade6fa1a9c395826e197892fb864067044cac80ab025849f8fd6f82"},{"executable":false,"path":"src/core/format.js","sha256":"83ee15f73a87ef24b75f7782f3b61dd4ef4cc1f2e01e38cdf19825b805fab3be"},{"executable":false,"path":"src/core/gateway.js","sha256":"3a4f838ee423600d29e05f58060dcaf81cdcea4ac93b36dd6108363ac24bc606"},{"executable":false,"path":"src/core/grok-approval-routes.ts","sha256":"a33daa4d05e0c2594c795bd7654c22f3e1003e4aaad41cd70034d03651dd01f9"},{"executable":false,"path":"src/core/grok-approvals.js","sha256":"6b651a65bdd17241dd5b7a01d94a318ece9356c1c9b965b0578e08250d74e8fe"},{"executable":false,"path":"src/core/headers.js","sha256":"e229f2826ebdfb52949dab500798c0fa8a5ff7c4e63de91a63103bf45d2ae3cc"},{"executable":false,"path":"src/core/history.js","sha256":"38ca8e8f8dcd2ad42952c424ea9f00be5972d8751e4c0ac87214171903d82d89"},{"executable":false,"path":"src/core/relay/codex.js","sha256":"ff6e8f3158d171911a35b829cd76e1f5fd8319f8143f727a4854448fc09edeec"},{"executable":false,"path":"src/core/relay/completion.js","sha256":"9d1a47f92716d1ccc7c4f44d92a580084f3b622c6ac0f20c6391be81abeb56e4"},{"executable":false,"path":"src/core/relay/control.js","sha256":"3645540f9f799b8742e0d5782b6324454a1486a780f6cb97260b96ef62411771"},{"executable":false,"path":"src/core/relay/engine.js","sha256":"205dd43b337439a56c7b1521b2603679ebc7fd3b2da430f8a477f83549efd453"},{"executable":false,"path":"src/core/relay/intake.js","sha256":"b31146fe3c9edd2f09323a454687403666591b6c12483a55b07ac610d2e3610a"},{"executable":false,"path":"src/core/relay/interactions.js","sha256":"6b576ed3a5b6659bc17e384d26e40d6ccb41b118b3a91cf5c902e9758ccbc1b1"},{"executable":false,"path":"src/core/relay/managed.js","sha256":"dbe03ed964bd09739e580de73b7e9f90508062fa2e53b8244c6ca7f78fc7a60d"},{"executable":false,"path":"src/core/relay/ownership.js","sha256":"74805f04f6a8bc02b2951614c4814aa42f54aaa3abca027a2413ed5a54814caf"},{"executable":false,"path":"src/core/relay/profile.js","sha256":"3347d1d493d3470d82722468d31571464d8e11aa0b4deac5bda75f574078dfe5"},{"executable":false,"path":"src/core/relay/records.js","sha256":"5b80f7dfe7e438811d9f27c1f9038d7631f8c73266d2ec7b1108c1ce9ecbbb47"},{"executable":false,"path":"src/core/relay/routes.ts","sha256":"4007e9908e285036786b7b0291dd480d03d51ad03f973fa578444accffa1f416"},{"executable":false,"path":"src/core/relay/state.js","sha256":"c18eda2f956944d0f318910de5239b954090eab81f7c77b4683e326a6d34b2b8"},{"executable":false,"path":"src/core/relay/worker.js","sha256":"4176ad91872f36f7ea6565d9f30d23d9d7a80ef27d7af975af760457132ba148"},{"executable":false,"path":"src/core/store.js","sha256":"caefeeebf686cecd37ef19585ef0a5d3acba9dbf1564fe128c3afe4de067305c"},{"executable":false,"path":"src/core/transcript.js","sha256":"0355f0978d2d126b90858e3f661130243fc4730ee81ba13080af1dfa39d8b081"},{"executable":false,"path":"src/core/url-policy.js","sha256":"62bf6d3c8af1f5840d5e2d682d8f2e52fcbfbee6695728b47ed31816f1736089"},{"executable":false,"path":"src/core/user-machine-guidance.js","sha256":"c8409ae9679246d8f907f1e0d16ec1c415d6697f2ce048fb64a599734486b9a6"},{"executable":false,"path":"src/gbot-install.ts","sha256":"e3c833d7662610e70e65232e541017229fb9a049eacee0bdf31e2c33c6ab7189"},{"executable":false,"path":"src/gbot.ts","sha256":"c89a37b764956ceacb2917a991a6d82d987ed8d8e453c8d553485bbd7f3edcc0"},{"executable":false,"path":"src/mcp/claude-channel.ts","sha256":"2d52e0d862a492026b6cb408e3177c994996e2b4292903da5bbf5bc191019913"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","sha256":"86334421686350ea044fb1160c19b6f5889425feb78fd608675feb8137492090"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx","sha256":"5f24cfdace92522891dfbaed0bd90e74b7de6bb8d193e0ef3bd5582c05a06914"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx","sha256":"b415d5bd303693649abae96b6b9d2920d29c797f5367ae8fbb2b62b635528e37"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx","sha256":"6adc4318f4b6c90b1d3970046266197348f79757c0d52ffe991d6338eb1fed6c"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx","sha256":"1d50db88cf7d06a74524c8937ed9045eaaf2560f6766d6c411b3bb55575d1d3f"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx","sha256":"9e1b93735b9a38216c7e9aac4c5b62bc2ac20b60e1979a19c4610f0208961af5"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx","sha256":"681e50ae6c7d3a04a76ad8eadf865ab9d793b5eb3c78f961a42d0902adacc306"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx","sha256":"2786b62ff2a1a4e68229199935ac63c15614a0f0bdbef74b2d06e0c405516272"},{"executable":false,"path":"src/mcp/grok-bot/tools/claude_send.tsx","sha256":"c02924049f370d9cb5ae459d6275c6cae2c9f4f1328cb5fa8e2f3e6d12a6d656"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_new.tsx","sha256":"556c8d6f5f2b07b20e9daae7aa8008ee3775582a4d034415fc86fecda0c63866"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_send.tsx","sha256":"5c02dc335a0354850d05e5827f6124d0ddc08b9b654059984887c55e4cd778c9"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_threads.tsx","sha256":"0164fc0c7b49df6524d56380763349cdd5ca26c68cffa5979b4e3346593ba2e4"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_wait.tsx","sha256":"cb08b094860f3a09c937eb8339108015fe0de57d9f6c6886aea2028cd33ef207"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_watch.tsx","sha256":"1bc603d36ea7542468e7e3eadbb86072990282e09e209f13ebfc64389d207c49"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_bridge_start.tsx","sha256":"c75c5c8a30ec43709a4d32baa8c3bc9796595381bb04fd2499ca30cd515c5a0b"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_bridge_status.tsx","sha256":"486ce643b35cfa2eabf78f0deeabce7198adc66133669eec630e1d12206ad642"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_bridge_stop.tsx","sha256":"371428a6e4b4e1312dd95d9681c29e765aec55e65d80d7c474535df838a43457"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_codex_respond.tsx","sha256":"030e9c2081ed4ed40732b098c929022af3083f609f10934b35e1f428d33ae637"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_grok_approvals.tsx","sha256":"17f164acdc48d6bc79a4c5044c7082760dd2a1646e5b56f6bff54c53fed96451"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_grok_respond.tsx","sha256":"41964bb8cf0eb0f8493afa1dde16cd94c4f589d1a7e410577d1ed63ec4648542"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_send.tsx","sha256":"2101d279a0e6bda2d57ba3da5366411df460a95692d4e64a1096880a89121d9a"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_thread.tsx","sha256":"ef4aefec7243efaad18335e8508c7c17af0cd9b0f8a4b3693a7af9f666807fd6"},{"executable":false,"path":"src/rules/codex-claude-on-user-machines.mdc","sha256":"a50ec93d021a807e0a18bf9311cdf103bc0ae3947e4c6a0bd78cbb941e8e5b24"},{"executable":false,"path":"src/scripts/gbot-relay.ts","sha256":"6690e316189ed8ebba43ea67a495338c927e4c0c21a9f896b7b2fecc8c6eb656"},{"executable":false,"path":"src/skills/chatgpt-desktop/SKILL.md","sha256":"0fe2560037f761203a317bf8755b0476ce864b7b1b13708559448d300aa4635c"},{"executable":false,"path":"src/skills/codex-dot/SKILL.md","sha256":"7e910c3e9e74800c09c9643983cf51cd090ff6ba448800d2702968cd89c6a005"},{"executable":false,"path":"src/skills/talk-to-grok-bot/references/bridge-administration.md","sha256":"3fc7d335822d9021cbd3770af6d7e95734d9213cd7331f41602598911c15ddf6"},{"executable":false,"path":"src/skills/talk-to-grok-bot/SKILL.md","sha256":"b80a88ea029564447a79dbc1a533191dc4839791368c6248c904bcfaf3ccb770"},{"executable":false,"path":"test/app-session.test.js","sha256":"0756b691703dd8c84bf0823f2afab16c6b158398e4ce6be229db6f459a0bbdb1"},{"executable":false,"path":"test/claude-channel.test.js","sha256":"c63337698001b9739414203d70b6d54d0794ec5970bd90d327923f50ab2355dc"},{"executable":false,"path":"test/codex-bridge.test.js","sha256":"55a1afcdea07f325b3528dd0c546ecc4cbfd6069610ecc4f773f049cd597e69c"},{"executable":false,"path":"test/codex-commands.test.js","sha256":"d07355741037270a82f9319ef615ace388585c44cff5586868330b6811847d2c"},{"executable":false,"path":"test/codex-contract.test.js","sha256":"926c7609679d8b6ac3b568d56ba5efa20df86d016a9031f085d19adbfb0e9064"},{"executable":false,"path":"test/codex-conversation.test.js","sha256":"789d0245a8d470860f7535c6ef3849313205097f6df517ab9946e47a789f8534"},{"executable":false,"path":"test/codex-session.test.js","sha256":"b39fe6afe0784b16e37b208089279dea01095d33e06ae26a1b60871796c7738a"},{"executable":false,"path":"test/codex-surfaces.test.js","sha256":"56d1b6550cc69d462a05e892cf82aa6a41495857b753215104e03207db514c81"},{"executable":false,"path":"test/connect-gateway.test.js","sha256":"5fabd87640b39e75c218300ca6be278268f248f3ff75e8cb72f9fade9eb0f7f3"},{"executable":false,"path":"test/desktop-shim.test.js","sha256":"89fb6c38a5fca5d41a96434cf9e8d51ae1d9992cf4f7930df0cc5840ef985705"},{"executable":false,"path":"test/doctor.test.js","sha256":"9685885df9e7363d3e077d246b1a17803c8899e9613b4a4d52ee4b9275e20694"},{"executable":false,"path":"test/gateway-groups.test.js","sha256":"14e227453e3e28c7cb60f91dba55733834c023ce9a914e40e22c68c899512bdc"},{"executable":false,"path":"test/gateway-send.test.js","sha256":"d059166153dde975f457e4e8c32ea08b0fc857b58fd48eab7da1959638e4fb05"},{"executable":false,"path":"test/gateway-skills.test.js","sha256":"feed62a884d1b7d12e358a27d73fb5587bcf761d4867ab1755d8bc34a4380069"},{"executable":false,"path":"test/gateway.test.js","sha256":"e5a7acd7ae347c82ef1e2a6000562767168e56d6f9d86aca8da46141731d1309"},{"executable":false,"path":"test/grok-approvals.test.js","sha256":"5ad4c548060a08dbe57949ab5ae240383fdb1709cd3694a909f5e1354fee3f73"},{"executable":false,"path":"test/helpers/codex-server.js","sha256":"432b4570601e94cf08c4861133d328404a97066642edb7ec0dbc314411a4d848"},{"executable":false,"path":"test/history.test.js","sha256":"eac4811f1b12d427df66996f33dd46bc3cbe31fc9fa030b3f32c571d5379f8dd"},{"executable":false,"path":"test/host-tool-inventory.test.js","sha256":"fa44f15f46d0cae486c13be3fae09568f17f8581001ec50a61478bec03f4c28c"},{"executable":false,"path":"test/pr69-integration.test.js","sha256":"a5dc99c11e2d3fcf18233c595f9c28301e5939f4b3657125eb3f970df2598840"},{"executable":false,"path":"test/relay-auth-recovery.test.js","sha256":"399c064f550fe33e166187a51da527728a97946d213377c8fcc8231378f5bbab"},{"executable":false,"path":"test/relay-codex.test.js","sha256":"43cb313e748e187f798a8a0bce5a01cce9ba360a52985b05ecededee9ad10581"},{"executable":false,"path":"test/relay-completion.test.js","sha256":"a8cc2402f82ce4b458074eafd32c8fa18f7ced7d85fdb6b7fa68f7b18b6a8c2e"},{"executable":false,"path":"test/relay-engine.test.js","sha256":"a8c06138d895ffaa30476f3a2ddf1ef50ef73a816a665f749f451d01d9cc2551"},{"executable":false,"path":"test/relay-gateway-lifecycle.test.js","sha256":"e16e7a34f7b6bb07965003e3018aa3a43ff192602db1c177bec9b6268fddb78b"},{"executable":false,"path":"test/relay-interactions.test.js","sha256":"83d70b1a813923fc6bae02b18d328107d0d04a6a761ab73b2051e3d114c7eaa5"},{"executable":false,"path":"test/relay-lifecycle.test.js","sha256":"e90130e1f609839bfd3f74c3edc333a22f37fe20dcde0146daa8d497133da4b7"},{"executable":false,"path":"test/relay-state.test.js","sha256":"c9143d5fa150b1ebcef9d515e161e25af3370b71eaf800a7b2bb1da1678b0bd3"},{"executable":false,"path":"test/relay-surfaces.test.js","sha256":"ba17ac4f1ffc02d4e06cd73eda143422a3d4d2f750630af9ed4e828dc9d7d2be"},{"executable":false,"path":"test/relay-worker.test.js","sha256":"6bd1bdaaaae59997132f289f822b6c4b8c9616c268fb2b45861e03f697c08197"},{"executable":false,"path":"test/release-config.test.js","sha256":"f3078277086d722f21d07e4134e10b89d2e849a94a0fa40f30025a5cb6fa6a15"},{"executable":false,"path":"test/store.test.js","sha256":"5d4ae4295287539ef4b7f98d0ca0cd42a931a3c7b25b092fbd2b8f1a08ca4bac"},{"executable":false,"path":"test/test-runner.test.js","sha256":"966ff3b67edb8e1f03b50120d4d820ab0f871121e9b359609e73faae8446454f"},{"executable":false,"path":"test/transcript.test.js","sha256":"28795d9cc8e42653ac430d18e17ff1e6bc2feb1b7935fe5c69b336d58e1793ae"},{"executable":false,"path":"test/url-policy.test.js","sha256":"dacfe322e0cbff178c0d67a5f76b6bd8d9fef14aa57c09c697eb69fa0019629c"},{"executable":false,"path":"tests/fixtures/codex-global-state-remote.json","sha256":"e59377d0f03cb24d57b55558e9c91dd363619a8a92566835f1ad49b639f99525"},{"executable":false,"path":"tests/route-unit/chatgpt-desktop-e2e-regressions.test.ts","sha256":"9cfc7f538899954970fe643c13571f03d417450c519525e91d382a0b5f0b086a"},{"executable":false,"path":"tests/route-unit/chatgpt-desktop-mcp-followup.test.ts","sha256":"4a2db11a642b8daef05285f096ce026ca5b9b6394c31c0966d7e5f8c1d49f4ca"},{"executable":false,"path":"tests/route-unit/chatgpt-desktop-review.test.ts","sha256":"208dfdea18ccc408a279666a521d2f70fdce9bdaf28f86bc5d053f7ad09a7dd2"},{"executable":false,"path":"tests/route-unit/chatgpt-desktop.test.ts","sha256":"5cf61e174b1d4a7c0f2209d6746bb1880a96fe550f7d2c4ea94e849dd7f21299"},{"executable":false,"path":"tests/route-unit/tools.test.ts","sha256":"7c7d971edaa7ef134d0dfba12208f88ec7f69c11dca79ad61d6e6cfae6d34c43"},{"executable":false,"path":"tsconfig.json","sha256":"fa2ced6d1721e8280a6aed615717cffcef25f6e2d16e15889b2be2a9df4fc226"}]},"provenance":[{"path":".agents/plugins/marketplace.json","sourceInputs":["agent-bundle.config.ts"]},{"path":".claude-plugin/marketplace.json","sourceInputs":["agent-bundle.config.ts","package.json"]},{"path":".claude-plugin/plugin.json","sourceInputs":["agent-bundle.config.ts","src/mcp/claude-channel.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/skills/chatgpt-desktop/SKILL.md","src/skills/codex-dot/SKILL.md","src/skills/talk-to-grok-bot/SKILL.md"]},{"path":".codex-plugin/mcp.json","sourceInputs":["agent-bundle.config.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"]},{"path":".codex-plugin/plugin.json","sourceInputs":["agent-bundle.config.ts","package.json","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/skills/chatgpt-desktop/SKILL.md","src/skills/codex-dot/SKILL.md","src/skills/talk-to-grok-bot/SKILL.md"]},{"path":".cursor-plugin/marketplace.json","sourceInputs":["agent-bundle.config.ts"]},{"path":".cursor-plugin/mcp.json","sourceInputs":["agent-bundle.config.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"]},{"path":".cursor-plugin/plugin.json","sourceInputs":["agent-bundle.config.ts","package.json","src/commands/codex-send.md","src/commands/codex-threads.md","src/commands/codex-wait.md","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/rules/codex-claude-on-user-machines.mdc","src/skills/chatgpt-desktop/SKILL.md","src/skills/codex-dot/SKILL.md","src/skills/talk-to-grok-bot/SKILL.md"]},{"path":".mcp.json","sourceInputs":["agent-bundle.config.ts","src/mcp/claude-channel.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"]},{"path":"agent-bundle.compile-evidence.json","sourceInputs":["agent-bundle.config.ts"]},{"path":"bin/gbot-flight.mjs","sourceInputs":["agent-bundle.config.ts","package.json","src/cli/_shared.ts","src/cli/approvals/list.tsx","src/cli/approvals/respond.tsx","src/cli/bots/create.tsx","src/cli/bots/delete.tsx","src/cli/bots/get.tsx","src/cli/bots/list.tsx","src/cli/bots/update.tsx","src/cli/chatgpt-desktop/hosts.tsx","src/cli/chatgpt-desktop/read.tsx","src/cli/chatgpt-desktop/search.tsx","src/cli/chatgpt-desktop/send.tsx","src/cli/chatgpt-desktop/status.tsx","src/cli/chatgpt-desktop/threads.tsx","src/cli/claude/send.tsx","src/cli/codex/bridge/respond.tsx","src/cli/codex/bridge/run.tsx","src/cli/codex/bridge/start.tsx","src/cli/codex/bridge/status.tsx","src/cli/codex/bridge/stop.tsx","src/cli/codex/desktop-shim.tsx","src/cli/codex/list-threads.tsx","src/cli/codex/new.tsx","src/cli/codex/queue.tsx","src/cli/codex/send.tsx","src/cli/codex/status.tsx","src/cli/codex/wait.tsx","src/cli/codex/watch.tsx","src/cli/doctor.tsx","src/cli/groups/add.tsx","src/cli/groups/create.tsx","src/cli/groups/delete.tsx","src/cli/groups/get.tsx","src/cli/groups/list.tsx","src/cli/groups/members.tsx","src/cli/groups/remove.tsx","src/cli/groups/set.tsx","src/cli/groups/update.tsx","src/cli/history.tsx","src/cli/send.tsx","src/cli/skills/add.tsx","src/cli/skills/list.tsx","src/cli/skills/remove.tsx","src/cli/thread.tsx","src/core/app-session.js","src/core/chatgpt-desktop/app-server-fallback.ts","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/chatgpt-desktop/cdp-dom.ts","src/core/chatgpt-desktop/cdp-session.ts","src/core/chatgpt-desktop/errors.ts","src/core/chatgpt-desktop/facade.ts","src/core/chatgpt-desktop/loopback.ts","src/core/chatgpt-desktop/payload-budget.ts","src/core/chatgpt-desktop/project-state.ts","src/core/chatgpt-desktop/remote-threads.ts","src/core/chatgpt-desktop/routes.ts","src/core/chatgpt-desktop/thread-ids.ts","src/core/claude-channel.js","src/core/claude-routes.ts","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/routes.ts","src/core/codex/thread-id.js","src/core/commands.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/format.js","src/core/gateway.js","src/core/grok-approval-routes.ts","src/core/grok-approvals.js","src/core/headers.js","src/core/history.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/relay/routes.ts","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/gbot.ts"]},{"path":"bin/gbot.mjs","sourceInputs":["agent-bundle.config.ts","package.json","src/cli/_shared.ts","src/cli/approvals/list.tsx","src/cli/approvals/respond.tsx","src/cli/bots/create.tsx","src/cli/bots/delete.tsx","src/cli/bots/get.tsx","src/cli/bots/list.tsx","src/cli/bots/update.tsx","src/cli/chatgpt-desktop/hosts.tsx","src/cli/chatgpt-desktop/read.tsx","src/cli/chatgpt-desktop/search.tsx","src/cli/chatgpt-desktop/send.tsx","src/cli/chatgpt-desktop/status.tsx","src/cli/chatgpt-desktop/threads.tsx","src/cli/claude/send.tsx","src/cli/codex/bridge/respond.tsx","src/cli/codex/bridge/run.tsx","src/cli/codex/bridge/start.tsx","src/cli/codex/bridge/status.tsx","src/cli/codex/bridge/stop.tsx","src/cli/codex/desktop-shim.tsx","src/cli/codex/list-threads.tsx","src/cli/codex/new.tsx","src/cli/codex/queue.tsx","src/cli/codex/send.tsx","src/cli/codex/status.tsx","src/cli/codex/wait.tsx","src/cli/codex/watch.tsx","src/cli/doctor.tsx","src/cli/groups/add.tsx","src/cli/groups/create.tsx","src/cli/groups/delete.tsx","src/cli/groups/get.tsx","src/cli/groups/list.tsx","src/cli/groups/members.tsx","src/cli/groups/remove.tsx","src/cli/groups/set.tsx","src/cli/groups/update.tsx","src/cli/history.tsx","src/cli/send.tsx","src/cli/skills/add.tsx","src/cli/skills/list.tsx","src/cli/skills/remove.tsx","src/cli/thread.tsx","src/core/app-session.js","src/core/chatgpt-desktop/app-server-fallback.ts","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/chatgpt-desktop/cdp-dom.ts","src/core/chatgpt-desktop/cdp-session.ts","src/core/chatgpt-desktop/errors.ts","src/core/chatgpt-desktop/facade.ts","src/core/chatgpt-desktop/loopback.ts","src/core/chatgpt-desktop/payload-budget.ts","src/core/chatgpt-desktop/project-state.ts","src/core/chatgpt-desktop/remote-threads.ts","src/core/chatgpt-desktop/routes.ts","src/core/chatgpt-desktop/thread-ids.ts","src/core/claude-channel.js","src/core/claude-routes.ts","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/routes.ts","src/core/codex/thread-id.js","src/core/commands.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/format.js","src/core/gateway.js","src/core/grok-approval-routes.ts","src/core/grok-approvals.js","src/core/headers.js","src/core/history.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/relay/routes.ts","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/gbot.ts"]},{"path":"commands/codex-send.md","sourceInputs":["src/commands/codex-send.md"]},{"path":"commands/codex-threads.md","sourceInputs":["src/commands/codex-threads.md"]},{"path":"commands/codex-wait.md","sourceInputs":["src/commands/codex-wait.md"]},{"path":"INSTALL.md","sourceInputs":["agent-bundle.config.ts"]},{"path":"install.mjs","sourceInputs":["agent-bundle.config.ts"]},{"path":"mcp.json","sourceInputs":["src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"]},{"path":"mcp/mcp-claude-channel-8029413c.mjs","sourceInputs":["src/core/claude-channel.js","src/core/user-machine-guidance.js","src/mcp/claude-channel.ts"]},{"path":"mcp/mcp-grok-bot-b8c2461e-flight.mjs","sourceInputs":["package.json","src/core/app-session.js","src/core/chatgpt-desktop/app-server-fallback.ts","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/chatgpt-desktop/cdp-dom.ts","src/core/chatgpt-desktop/cdp-session.ts","src/core/chatgpt-desktop/errors.ts","src/core/chatgpt-desktop/facade.ts","src/core/chatgpt-desktop/loopback.ts","src/core/chatgpt-desktop/payload-budget.ts","src/core/chatgpt-desktop/project-state.ts","src/core/chatgpt-desktop/remote-threads.ts","src/core/chatgpt-desktop/routes.ts","src/core/chatgpt-desktop/thread-ids.ts","src/core/claude-channel.js","src/core/claude-routes.ts","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/routes.ts","src/core/codex/thread-id.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/gateway.js","src/core/grok-approval-routes.ts","src/core/grok-approvals.js","src/core/headers.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/relay/routes.ts","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/gbot.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx","src/mcp/grok-bot/tools/claude_send.tsx","src/mcp/grok-bot/tools/codex_new.tsx","src/mcp/grok-bot/tools/codex_send.tsx","src/mcp/grok-bot/tools/codex_threads.tsx","src/mcp/grok-bot/tools/codex_wait.tsx","src/mcp/grok-bot/tools/codex_watch.tsx","src/mcp/grok-bot/tools/gbot_bridge_start.tsx","src/mcp/grok-bot/tools/gbot_bridge_status.tsx","src/mcp/grok-bot/tools/gbot_bridge_stop.tsx","src/mcp/grok-bot/tools/gbot_codex_respond.tsx","src/mcp/grok-bot/tools/gbot_grok_approvals.tsx","src/mcp/grok-bot/tools/gbot_grok_respond.tsx","src/mcp/grok-bot/tools/gbot_send.tsx","src/mcp/grok-bot/tools/gbot_thread.tsx"]},{"path":"mcp/mcp-grok-bot-b8c2461e.mjs","sourceInputs":["package.json","src/core/app-session.js","src/core/chatgpt-desktop/app-server-fallback.ts","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/chatgpt-desktop/cdp-dom.ts","src/core/chatgpt-desktop/cdp-session.ts","src/core/chatgpt-desktop/errors.ts","src/core/chatgpt-desktop/facade.ts","src/core/chatgpt-desktop/loopback.ts","src/core/chatgpt-desktop/payload-budget.ts","src/core/chatgpt-desktop/project-state.ts","src/core/chatgpt-desktop/remote-threads.ts","src/core/chatgpt-desktop/routes.ts","src/core/chatgpt-desktop/thread-ids.ts","src/core/claude-channel.js","src/core/claude-routes.ts","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/routes.ts","src/core/codex/thread-id.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/gateway.js","src/core/grok-approval-routes.ts","src/core/grok-approvals.js","src/core/headers.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/relay/routes.ts","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/gbot.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx","src/mcp/grok-bot/tools/claude_send.tsx","src/mcp/grok-bot/tools/codex_new.tsx","src/mcp/grok-bot/tools/codex_send.tsx","src/mcp/grok-bot/tools/codex_threads.tsx","src/mcp/grok-bot/tools/codex_wait.tsx","src/mcp/grok-bot/tools/codex_watch.tsx","src/mcp/grok-bot/tools/gbot_bridge_start.tsx","src/mcp/grok-bot/tools/gbot_bridge_status.tsx","src/mcp/grok-bot/tools/gbot_bridge_stop.tsx","src/mcp/grok-bot/tools/gbot_codex_respond.tsx","src/mcp/grok-bot/tools/gbot_grok_approvals.tsx","src/mcp/grok-bot/tools/gbot_grok_respond.tsx","src/mcp/grok-bot/tools/gbot_send.tsx","src/mcp/grok-bot/tools/gbot_thread.tsx"]},{"path":"plugin.json","sourceInputs":["agent-bundle.config.ts","package.json"]},{"path":"rules/codex-claude-on-user-machines.mdc","sourceInputs":["src/rules/codex-claude-on-user-machines.mdc"]},{"path":"scripts/gbot-relay.mjs","sourceInputs":["package.json","src/core/app-session.js","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/thread-id.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/gateway.js","src/core/grok-approvals.js","src/core/headers.js","src/core/relay/codex.js","src/core/relay/completion.js","src/core/relay/control.js","src/core/relay/engine.js","src/core/relay/intake.js","src/core/relay/interactions.js","src/core/relay/ownership.js","src/core/relay/profile.js","src/core/relay/records.js","src/core/relay/state.js","src/core/relay/worker.js","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/scripts/gbot-relay.ts"]},{"path":"skills/chatgpt-desktop/SKILL.md","sourceInputs":["src/skills/chatgpt-desktop/SKILL.md"]},{"path":"skills/codex-dot/SKILL.md","sourceInputs":["src/skills/codex-dot/SKILL.md"]},{"path":"skills/talk-to-grok-bot/references/bridge-administration.md","sourceInputs":["src/skills/talk-to-grok-bot/references/bridge-administration.md","src/skills/talk-to-grok-bot/SKILL.md"]},{"path":"skills/talk-to-grok-bot/SKILL.md","sourceInputs":["src/skills/talk-to-grok-bot/SKILL.md"]}],"recordVersion":1,"validation":{"artifact":{"status":"passed"},"projections":[{"host":"claude","status":"passed"},{"host":"codex","status":"passed"},{"host":"cursor","status":"passed"},{"host":"portable","status":"passed"}],"source":{"status":"passed"}}},"distribution":{"channels":["local","npm"],"install":{"instructions":"INSTALL.md","script":"install.mjs"},"payloads":[]},"executables":{"bins":[{"hosts":["claude","codex","cursor","portable"],"name":"gbot","path":"bin/gbot.mjs","worker":"bin/gbot-flight.mjs"}],"hooks":[],"mcpServers":[{"apps":[],"hosts":["claude"],"id":"mcp:claude-channel","kind":"compiled","launch":{"args":[],"entry":"mcp/mcp-claude-channel-8029413c.mjs","env":{}},"name":"claude-channel","transport":"stdio"},{"apps":[],"hosts":["claude","codex","cursor","portable"],"id":"mcp:grok-bot","kind":"compiled","launch":{"args":[],"entry":"mcp/mcp-grok-bot-b8c2461e.mjs","env":{},"worker":"mcp/mcp-grok-bot-b8c2461e-flight.mjs"},"name":"grok-bot","transport":"stdio"}],"scripts":[{"hosts":["claude","codex","cursor","portable"],"id":"script:gbot-relay","mode":"bundle","name":"gbot-relay","path":"scripts/gbot-relay.mjs"}]},"files":[{"bytes":225,"kind":"generated","path":".agents/plugins/marketplace.json","sha256":"54d575719e003eb71ba2d7fb7379e12098243e701646e0ca83dba38ef2a78b1d"},{"bytes":926,"kind":"generated","path":".claude-plugin/marketplace.json","sha256":"2006da147ad6fc10cb0e713d6f0556cd7c6fcd5de04ac9f9a0ad5e00073cff35"},{"bytes":339,"kind":"generated","path":".claude-plugin/plugin.json","sha256":"b449e763e51308ac3c0f60000528712743181e067737e5148b461aa3a2536274"},{"bytes":156,"kind":"generated","path":".codex-plugin/mcp.json","sha256":"4b442017d0d30ec207cef7a4e5d2cd9dca246080008633459a27e3a5f2f7935b"},{"bytes":1310,"kind":"generated","path":".codex-plugin/plugin.json","sha256":"8cbecfa2707913ac72558a9852a69ac6e1a15c577cf6724bf5be8f864f11c143"},{"bytes":332,"kind":"generated","path":".cursor-plugin/marketplace.json","sha256":"297ba8aebcdb8bcac814b520bf21d9d6acc9c8c94a1ecf3ca442a49d834aab59"},{"bytes":169,"kind":"generated","path":".cursor-plugin/mcp.json","sha256":"95c87d0f2ed3a4f6df7d0e519454b1234672eca030db3b8cd8776ef0f35dee74"},{"bytes":694,"kind":"generated","path":".cursor-plugin/plugin.json","sha256":"78c77772a4f0ca0c2fa4afbfd39e401f00e860c1164d474bc54a1097bccb847d"},{"bytes":363,"kind":"generated","path":".mcp.json","sha256":"5c56ac183c3d4fcbfa9386a73ab805495c6ab613b96bf71dbd5be80093e1a10b"},{"bytes":22592,"kind":"generated","path":"agent-bundle.compile-evidence.json","sha256":"2ff9b08a36d53288db5589149cbddd14bdc9ce7cf9db72eff9b8f908583dcdfc"},{"bytes":1592195,"kind":"bundle","path":"bin/gbot-flight.mjs","sha256":"ae6e5122b4e1721eacbebea9f3cf8eeaded2ac6afcb094fa5f87ee5d2de40bab"},{"bytes":2462573,"kind":"bundle","mode":493,"path":"bin/gbot.mjs","sha256":"f879db18627f1c6c71a2e194db8f77a36f79eb1c58ae0ef400f67afd395fedb8"},{"bytes":375,"kind":"generated","path":"commands/codex-send.md","sha256":"622af5d2945c3dc9fe3035b4e35a63cd6041e0b7a9570a5f5648ba857eae9074"},{"bytes":250,"kind":"generated","path":"commands/codex-threads.md","sha256":"a763a6e1d378d012cdf6f52bd5962cf8b3a0806ef5be88472ea199d250cf6a4b"},{"bytes":267,"kind":"generated","path":"commands/codex-wait.md","sha256":"f203f7e33ad2dd59723b1117fb65a5de062a16f8b7edda1b034f02e635c96f9a"},{"bytes":22762,"kind":"generated","path":"INSTALL.md","sha256":"f9525af2bbb64d13e003ffaab376daac03f6a1167405f6726a8aff15e2696e83"},{"bytes":78590,"kind":"generated","path":"install.mjs","sha256":"248c9642984cb95b2b6c13aa005dc3a5c002a61272754ffdf98868568ef111f1"},{"bytes":246,"kind":"generated","path":"mcp.json","sha256":"c06a01fa851792f42e0cc807a444e454c3ea2fd164dc1c2adef455acc93879e2"},{"bytes":2275669,"kind":"bundle","path":"mcp/mcp-claude-channel-8029413c.mjs","sha256":"46c0e5abb42f0dcd1152ec9d6bf5fed42c3bcb109f89312bfaa9870ecc059fe3"},{"bytes":1523717,"kind":"bundle","path":"mcp/mcp-grok-bot-b8c2461e-flight.mjs","sha256":"8d49ea30728efd1025b90c50ff21150907c7fce7dba95d851a606f0bafbaa4aa"},{"bytes":3351174,"kind":"bundle","path":"mcp/mcp-grok-bot-b8c2461e.mjs","sha256":"6203d726018516415799977b5851f121ca0d05d20e1d5b64eea43089ae06785b"},{"bytes":681,"kind":"generated","path":"plugin.json","sha256":"050f61f0459e9d78cf318bf6a6d6fc8b6c1d2dae3cab2ab3f873b49337bbe456"},{"bytes":953,"kind":"generated","path":"rules/codex-claude-on-user-machines.mdc","sha256":"a50ec93d021a807e0a18bf9311cdf103bc0ae3947e4c6a0bd78cbb941e8e5b24"},{"bytes":1305648,"kind":"bundle","path":"scripts/gbot-relay.mjs","sha256":"9d35ecc3eca0703941fbb8dd93c86d065f609d3e1eedbfef69b90597fb490323"},{"bytes":4856,"kind":"copy","path":"skills/chatgpt-desktop/SKILL.md","sha256":"0fe2560037f761203a317bf8755b0476ce864b7b1b13708559448d300aa4635c"},{"bytes":2134,"kind":"copy","path":"skills/codex-dot/SKILL.md","sha256":"7e910c3e9e74800c09c9643983cf51cd090ff6ba448800d2702968cd89c6a005"},{"bytes":6007,"kind":"copy","path":"skills/talk-to-grok-bot/references/bridge-administration.md","sha256":"3fc7d335822d9021cbd3770af6d7e95734d9213cd7331f41602598911c15ddf6"},{"bytes":4067,"kind":"copy","path":"skills/talk-to-grok-bot/SKILL.md","sha256":"b80a88ea029564447a79dbc1a533191dc4839791368c6248c904bcfaf3ccb770"}],"manifestVersion":6,"projections":[{"builtInHost":"claude","documents":{"marketplace":".claude-plugin/marketplace.json","mcp":".mcp.json","plugin":".claude-plugin/plugin.json"},"host":"claude","marketplace":{"name":"gbot-marketplace"}},{"builtInHost":"codex","documents":{"marketplace":".agents/plugins/marketplace.json","mcp":".codex-plugin/mcp.json","plugin":".codex-plugin/plugin.json"},"host":"codex","marketplace":{"name":"gbot-marketplace"}},{"builtInHost":"cursor","documents":{"marketplace":".cursor-plugin/marketplace.json","mcp":".cursor-plugin/mcp.json","plugin":".cursor-plugin/plugin.json"},"host":"cursor","marketplace":{"name":"gbot-marketplace"}},{"builtInHost":"portable","documents":{"mcp":"mcp.json","plugin":"plugin.json"},"host":"portable"}],"routes":{"cli":{"commands":[{"aliases":[],"description":"List current Grok approval cards (latest 200 entries).","exitCode":"zero","options":[{"key":"target","kind":"string","option":"target","positional":0,"repeated":false,"required":true}],"path":["approvals","list"],"routeId":"cli:approvals/list"},{"aliases":[],"description":"Explicit user decision: accept a Grok request once or decline; never grant persistent permissions.","exitCode":"zero","options":[{"choices":["accept","decline"],"key":"decision","kind":"enum","option":"decision","repeated":false,"required":true},{"key":"entryId","kind":"string","option":"entry-id","repeated":false,"required":true},{"key":"requestId","kind":"string","option":"request-id","repeated":false,"required":true},{"key":"target","kind":"string","option":"target","repeated":false,"required":true}],"path":["approvals","respond"],"routeId":"cli:approvals/respond"},{"aliases":[],"description":"Create a Grok Bot bot.","exitCode":"zero","options":[{"key":"avatarColor","kind":"string","option":"avatar-color","repeated":false,"required":false},{"key":"avatarShape","kind":"string","option":"avatar-shape","repeated":false,"required":false},{"key":"description","kind":"string","option":"description","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"name","kind":"string","option":"name","repeated":false,"required":true},{"key":"title","kind":"string","option":"title","repeated":false,"required":false}],"path":["bots","create"],"routeId":"cli:bots/create"},{"aliases":[],"description":"Delete a bot or group by id or name.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Bot or group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["bots","delete"],"routeId":"cli:bots/delete"},{"aliases":[],"description":"Show one bot or group by id or name.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Bot or group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["bots","get"],"routeId":"cli:bots/get"},{"aliases":[],"description":"List Grok Bot bots (not groups).","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false}],"path":["bots","list"],"routeId":"cli:bots/list"},{"aliases":[],"description":"Update a bot or group profile.","exitCode":"zero","options":[{"key":"avatarColor","kind":"string","option":"avatar-color","repeated":false,"required":false},{"key":"avatarShape","kind":"string","option":"avatar-shape","repeated":false,"required":false},{"key":"description","kind":"string","option":"description","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"hidden","kind":"string","option":"hidden","repeated":false,"required":false},{"key":"name","kind":"string","option":"name","repeated":false,"required":false},{"key":"notify","kind":"string","option":"notify","repeated":false,"required":false},{"description":"Bot or group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true},{"key":"title","kind":"string","option":"title","repeated":false,"required":false}],"path":["bots","update"],"routeId":"cli:bots/update"},{"aliases":[],"description":"Discover ChatGPT Desktop hosts and modelProviders at runtime (never hardcode). Always includes local plus every remote-thread-summaries-v3:; Providers come from distinct thread/list and remote-summary values.","exitCode":"result","options":[{"description":"Local CDP port","key":"port","kind":"number","option":"port","repeated":false,"required":false}],"path":["chatgpt-desktop","hosts"],"routeId":"cli:chatgpt-desktop/hosts"},{"aliases":[],"description":"Read a ChatGPT Desktop thread via app-server (turns/list); CDP DOM is fallback only.","exitCode":"result","options":[{"description":"Opaque nextCursor from the prior read page","key":"cursor","kind":"string","option":"cursor","repeated":false,"required":false},{"key":"full","kind":"boolean","option":"full","repeated":false,"required":false},{"description":"Recent default 100; full default 2000","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"key":"openTimeoutMs","kind":"number","option":"open-timeout-ms","repeated":false,"required":false},{"key":"port","kind":"number","option":"port","repeated":false,"required":false},{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true}],"path":["chatgpt-desktop","read"],"routeId":"cli:chatgpt-desktop/read"},{"aliases":[],"description":"Search ChatGPT Desktop threads. --host and --model-provider accept any string (see gbot chatgpt-desktop hosts); not enums.","exitCode":"result","options":[{"description":"Opaque nextCursor from a prior search page","key":"cursor","kind":"string","option":"cursor","repeated":false,"required":false},{"choices":["host"],"description":"Group results by host (grouping mode, not a host id)","key":"groupBy","kind":"enum","option":"group-by","repeated":false,"required":false},{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","key":"host","kind":"string","option":"host","repeated":false,"required":false},{"description":"Max matches (1-200)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","key":"modelProvider","kind":"string","option":"model-provider","repeated":false,"required":false},{"description":"Local CDP port","key":"port","kind":"number","option":"port","repeated":false,"required":false},{"description":"Project label or projectId filter.","key":"project","kind":"string","option":"project","repeated":false,"required":false},{"key":"query","kind":"string","option":"query","positional":0,"repeated":false,"required":true}],"path":["chatgpt-desktop","search"],"routeId":"cli:chatgpt-desktop/search"},{"aliases":[],"description":"Send to ChatGPT Desktop via CDP composer. Omit --thread-id for a new chat; --project prefers Start new chat in .","exitCode":"result","options":[{"key":"openTimeoutMs","kind":"number","option":"open-timeout-ms","repeated":false,"required":false},{"key":"port","kind":"number","option":"port","repeated":false,"required":false},{"key":"project","kind":"string","option":"project","repeated":false,"required":false},{"key":"text","kind":"string","option":"text","positional":0,"repeated":true,"required":true},{"key":"threadId","kind":"string","option":"thread-id","repeated":false,"required":false},{"description":"Explicitly unarchive an existing archived thread before sending.","key":"unarchive","kind":"boolean","option":"unarchive","repeated":false,"required":false}],"path":["chatgpt-desktop","send"],"routeId":"cli:chatgpt-desktop/send"},{"aliases":[],"description":"Probe local ChatGPT Desktop CDP on 127.0.0.1 and report app-server availability for list/deep-read.","exitCode":"result","options":[{"description":"Local CDP port (default 9222)","key":"port","kind":"number","option":"port","repeated":false,"required":false}],"path":["chatgpt-desktop","status"],"routeId":"cli:chatgpt-desktop/status"},{"aliases":[],"description":"List local + remote-control ChatGPT Desktop threads. --host and --model-provider accept any string (see gbot chatgpt-desktop hosts); not enums.","exitCode":"result","options":[{"description":"Opaque nextCursor from a previous page","key":"cursor","kind":"string","option":"cursor","repeated":false,"required":false},{"choices":["host"],"description":"Group results by host (grouping mode, not a host id)","key":"groupBy","kind":"enum","option":"group-by","repeated":false,"required":false},{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","key":"host","kind":"string","option":"host","repeated":false,"required":false},{"description":"Max threads (1-200)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","key":"modelProvider","kind":"string","option":"model-provider","repeated":false,"required":false},{"description":"Local CDP port","key":"port","kind":"number","option":"port","repeated":false,"required":false},{"description":"Project label or projectId filter.","key":"project","kind":"string","option":"project","repeated":false,"required":false}],"path":["chatgpt-desktop","threads"],"routeId":"cli:chatgpt-desktop/threads"},{"aliases":[],"description":"Send to an explicitly enabled live Claude Code channel and wait for its reply.","exitCode":"result","options":[{"key":"message","kind":"string","option":"message","positional":1,"repeated":false,"required":true},{"key":"name","kind":"string","option":"name","positional":0,"repeated":false,"required":true},{"key":"timeoutMs","kind":"number","option":"timeout-ms","repeated":false,"required":false}],"path":["claude","send"],"routeId":"cli:claude/send"},{"aliases":[],"description":"Managed Grok/Codex bridge respond.","exitCode":"result","options":[{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","key":"answersJson","kind":"string","option":"answers-json","repeated":false,"required":false},{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"choices":["accept","decline","cancel"],"key":"decision","kind":"enum","option":"decision","repeated":false,"required":false},{"key":"exchangeId","kind":"string","option":"exchange-id","repeated":false,"required":false},{"key":"generation","kind":"string","option":"generation","repeated":false,"required":true},{"key":"interactionId","kind":"string","option":"interaction-id","repeated":false,"required":true},{"key":"threadId","kind":"string","option":"thread-id","repeated":false,"required":true},{"key":"turnId","kind":"string","option":"turn-id","repeated":false,"required":true}],"path":["codex","bridge","respond"],"routeId":"cli:codex/bridge/respond"},{"aliases":[],"description":"Run a bounded foreground relay (up to 23 hours). Use the packaged gbot-relay.mjs script for unlimited service lifetime.","exitCode":"result","options":[{"description":"Foreground lifetime in milliseconds (100..82800000; default 23h).","key":"lifetimeMs","kind":"number","option":"lifetime-ms","repeated":false,"required":false}],"path":["codex","bridge","run"],"routeId":"cli:codex/bridge/run"},{"aliases":[],"description":"Managed Grok/Codex bridge start.","exitCode":"result","options":[{"choices":["steer","reject"],"key":"busyPolicy","kind":"enum","option":"busy-policy","repeated":false,"required":false},{"key":"codexThreadId","kind":"string","option":"codex-thread-id","repeated":false,"required":false},{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"key":"grokTarget","kind":"string","option":"grok-target","positional":0,"repeated":false,"required":true},{"key":"requestId","kind":"string","option":"request-id","repeated":false,"required":false}],"path":["codex","bridge","start"],"routeId":"cli:codex/bridge/start"},{"aliases":[],"description":"Managed Grok/Codex bridge status.","exitCode":"result","options":[{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"key":"limit","kind":"number","option":"limit","repeated":false,"required":false}],"path":["codex","bridge","status"],"routeId":"cli:codex/bridge/status"},{"aliases":[],"description":"Managed Grok/Codex bridge stop.","exitCode":"result","options":[{"key":"all","kind":"boolean","option":"all","repeated":false,"required":false},{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"key":"worker","kind":"boolean","option":"worker","repeated":false,"required":false}],"path":["codex","bridge","stop"],"routeId":"cli:codex/bridge/stop"},{"aliases":[],"description":"Install, remove, or check the ChatGPT Desktop shim: a CODEX_CLI_PATH wrapper that bridges Desktop stdio onto the managed Codex daemon (stock app-server proxy hangs). macOS persists via LaunchAgent; always fails open to real Codex.","exitCode":"result","options":[{"choices":["install","uninstall","status"],"description":"install | uninstall | status","key":"action","kind":"enum","option":"action","positional":0,"repeated":false,"required":true}],"path":["codex","desktop-shim"],"routeId":"cli:codex/desktop-shim"},{"aliases":[],"description":"List Codex daemon-managed threads (all modelProviders; pages via --cursor / nextCursor).","exitCode":"result","options":[{"description":"Opaque pagination cursor from a previous nextCursor (may start with -)","key":"cursor","kind":"string","option":"cursor","repeated":false,"required":false},{"description":"Max threads to list (1-200)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false}],"path":["codex","list-threads"],"routeId":"cli:codex/list-threads"},{"aliases":[],"description":"Start a new Codex thread in --cwd, optionally with --model, --effort and a message.","exitCode":"result","options":[{"key":"cwd","kind":"string","option":"cwd","repeated":false,"required":true},{"choices":["none","minimal","low","medium","high","xhigh"],"key":"effort","kind":"enum","option":"effort","repeated":false,"required":false},{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"key":"message","kind":"string","option":"message","positional":0,"repeated":true,"required":false},{"key":"model","kind":"string","option":"model","repeated":false,"required":false}],"path":["codex","new"],"routeId":"cli:codex/new"},{"aliases":[],"description":"List the experimental Codex thread queue (GROK_BOT_CODEX_EXPERIMENTAL=1).","exitCode":"result","options":[{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true}],"path":["codex","queue"],"routeId":"cli:codex/queue"},{"aliases":[],"description":"Send to Codex; acceptance is distinct from completion. Options precede threadId.","exitCode":"result","options":[{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"key":"correlationId","kind":"string","option":"correlation-id","repeated":false,"required":false},{"choices":["none","minimal","low","medium","high","xhigh"],"key":"effort","kind":"enum","option":"effort","repeated":false,"required":false},{"key":"envelope","kind":"boolean","option":"envelope","repeated":false,"required":false},{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"description":"Required active-turn guard for steer; stale guards reject.","key":"expectedTurnId","kind":"string","option":"expected-turn-id","repeated":false,"required":false},{"key":"hop","kind":"number","option":"hop","repeated":false,"required":false},{"description":"Reply budget: 1-4194304 bytes.","key":"maxOutputBytes","kind":"number","option":"max-output-bytes","repeated":false,"required":false},{"key":"message","kind":"string","option":"message","positional":1,"repeated":true,"required":true},{"key":"model","kind":"string","option":"model","repeated":false,"required":false},{"key":"replyTo","kind":"string","option":"reply-to","repeated":false,"required":false},{"key":"replyToGrok","kind":"string","option":"reply-to-grok","repeated":false,"required":false},{"key":"requestId","kind":"string","option":"request-id","repeated":false,"required":false},{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true},{"description":"Observation timeout: 1-7200000 milliseconds.","key":"timeoutMs","kind":"number","option":"timeout-ms","repeated":false,"required":false},{"key":"wait","kind":"boolean","option":"wait","repeated":false,"required":false},{"choices":["reject","queue","steer"],"key":"whenBusy","kind":"enum","option":"when-busy","repeated":false,"required":false}],"path":["codex","send"],"routeId":"cli:codex/send"},{"aliases":[],"description":"Probe the local Codex app-server daemon. Exit 0 only when it is usable.","exitCode":"result","options":[],"path":["codex","status"],"routeId":"cli:codex/status"},{"aliases":[],"description":"Bounded Codex wait observation; never interrupts execution.","exitCode":"result","options":[{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"description":"Reply budget: 1-4194304 bytes.","key":"maxOutputBytes","kind":"number","option":"max-output-bytes","repeated":false,"required":false},{"key":"messageId","kind":"string","option":"message-id","repeated":false,"required":false},{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true},{"description":"Observation timeout: 1-7200000 milliseconds.","key":"timeoutMs","kind":"number","option":"timeout-ms","repeated":false,"required":false},{"key":"turnId","kind":"string","option":"turn-id","positional":1,"repeated":false,"required":true}],"path":["codex","wait"],"routeId":"cli:codex/wait"},{"aliases":[],"description":"Bounded Codex watch observation; never interrupts execution.","exitCode":"result","options":[{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"description":"Maximum observed events: 1-500.","key":"maxEvents","kind":"number","option":"max-events","repeated":false,"required":false},{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true},{"description":"Observation timeout: 1-600000 milliseconds.","key":"timeoutMs","kind":"number","option":"timeout-ms","repeated":false,"required":false}],"path":["codex","watch"],"routeId":"cli:codex/watch"},{"aliases":[],"description":"Show which agents root and auth sources gbot can see.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false}],"path":["doctor"],"routeId":"cli:doctor"},{"aliases":[],"description":"Add a bot to a group.","exitCode":"zero","options":[{"key":"bot","kind":"string","option":"bot","positional":1,"repeated":false,"required":true},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"group","kind":"string","option":"group","positional":0,"repeated":false,"required":true}],"path":["groups","add"],"routeId":"cli:groups/add"},{"aliases":[],"description":"Create a Grok Bot group.","exitCode":"zero","options":[{"key":"avatarColor","kind":"string","option":"avatar-color","repeated":false,"required":false},{"key":"avatarShape","kind":"string","option":"avatar-shape","repeated":false,"required":false},{"key":"description","kind":"string","option":"description","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Member bot id or name (repeatable)","key":"member","kind":"string","option":"member","repeated":true,"required":true},{"key":"name","kind":"string","option":"name","repeated":false,"required":true},{"key":"title","kind":"string","option":"title","repeated":false,"required":false}],"path":["groups","create"],"routeId":"cli:groups/create"},{"aliases":[],"description":"Delete a group by id or name.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["groups","delete"],"routeId":"cli:groups/delete"},{"aliases":[],"description":"Show one group by id or name.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["groups","get"],"routeId":"cli:groups/get"},{"aliases":[],"description":"List Grok Bot groups.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false}],"path":["groups","list"],"routeId":"cli:groups/list"},{"aliases":[],"description":"Show members of a group (same payload as groups get).","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["groups","members"],"routeId":"cli:groups/members"},{"aliases":[],"description":"Remove a bot from a group.","exitCode":"zero","options":[{"key":"bot","kind":"string","option":"bot","positional":1,"repeated":false,"required":true},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"group","kind":"string","option":"group","positional":0,"repeated":false,"required":true}],"path":["groups","remove"],"routeId":"cli:groups/remove"},{"aliases":[],"description":"Replace a group's member list.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"group","kind":"string","option":"group","positional":0,"repeated":false,"required":true},{"description":"Member bot id or name (repeatable)","key":"member","kind":"string","option":"member","repeated":true,"required":true}],"path":["groups","set"],"routeId":"cli:groups/set"},{"aliases":[],"description":"Update a group profile (members stay on set/add/remove).","exitCode":"zero","options":[{"key":"avatarColor","kind":"string","option":"avatar-color","repeated":false,"required":false},{"key":"avatarShape","kind":"string","option":"avatar-shape","repeated":false,"required":false},{"key":"description","kind":"string","option":"description","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"hidden","kind":"string","option":"hidden","repeated":false,"required":false},{"key":"name","kind":"string","option":"name","repeated":false,"required":false},{"key":"notify","kind":"string","option":"notify","repeated":false,"required":false},{"description":"Group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true},{"key":"title","kind":"string","option":"title","repeated":false,"required":false}],"path":["groups","update"],"routeId":"cli:groups/update"},{"aliases":[],"description":"Read the opt-in local JSONL history without contacting the gateway.","exitCode":"zero","options":[{"description":"Directory containing history.jsonl","key":"historyDir","kind":"string","option":"history-dir","repeated":false,"required":false},{"description":"Maximum matching rows (1 or more)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"description":"Print the history file path","key":"path","kind":"boolean","option":"path","repeated":false,"required":false},{"description":"Bot or group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":false},{"description":"Case-insensitive message text filter","key":"search","kind":"string","option":"search","repeated":false,"required":false}],"path":["history"],"routeId":"cli:history"},{"aliases":[],"description":"Send a message to a Grok Bot bot or group by name or id.","exitCode":"result","options":[{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"key":"codexThreadId","kind":"string","option":"codex-thread-id","repeated":false,"required":false},{"description":"Stable correlation id for multi-hop replies","key":"correlationId","kind":"string","option":"correlation-id","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Prepend the [gbot …] header","key":"envelope","kind":"boolean","option":"envelope","repeated":false,"required":false},{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Directory containing history.jsonl","key":"historyDir","kind":"string","option":"history-dir","repeated":false,"required":false},{"description":"Hop count; refused at GROK_BOT_MAX_HOPS","key":"hop","kind":"number","option":"hop","repeated":false,"required":false},{"key":"message","kind":"string","option":"message","positional":1,"repeated":true,"required":true},{"description":"Skip local history for this command","key":"noHistory","kind":"boolean","option":"no-history","repeated":false,"required":false},{"choices":["auto","manual"],"key":"replyMode","kind":"enum","option":"reply-mode","repeated":false,"required":false},{"description":"Prior message id this send replies to","key":"replyTo","kind":"string","option":"reply-to","repeated":false,"required":false},{"key":"requestId","kind":"string","option":"request-id","repeated":false,"required":false},{"key":"target","kind":"string","option":"target","positional":0,"repeated":false,"required":true}],"path":["send"],"routeId":"cli:send"},{"aliases":[],"description":"Add a SKILL.md to the shared skill library. Every bot sees it.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"SKILL.md file, or a directory holding one","key":"path","kind":"string","option":"path","positional":0,"repeated":false,"required":true}],"path":["skills","add"],"routeId":"cli:skills/add"},{"aliases":[],"description":"List the skill library every bot in this Grok Bot shares.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false}],"path":["skills","list"],"routeId":"cli:skills/list"},{"aliases":[],"description":"Remove a library skill by id or name. Every bot loses it.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Skill id or name","key":"skill","kind":"string","option":"skill","positional":0,"repeated":false,"required":true}],"path":["skills","remove"],"routeId":"cli:skills/remove"},{"aliases":[],"description":"Read the most recent messages in a Grok Bot bot or group thread.","exitCode":"zero","options":[{"description":"Return entries after this opaque entry id","key":"after","kind":"string","option":"after","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Show full entry text in human output","key":"full","kind":"boolean","option":"full","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Directory containing history.jsonl","key":"historyDir","kind":"string","option":"history-dir","repeated":false,"required":false},{"description":"How many trailing entries to return (1-200)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"description":"Skip local history for this command","key":"noHistory","kind":"boolean","option":"no-history","repeated":false,"required":false},{"description":"Read one rooted thread by message id","key":"root","kind":"string","option":"root","repeated":false,"required":false},{"key":"target","kind":"string","option":"target","positional":0,"repeated":false,"required":true}],"path":["thread"],"routeId":"cli:thread"}],"mode":"generated","routes":[{"contract":"contract:src/cli/approvals/list.tsx#inputJsonSchema","description":"List current Grok approval cards (latest 200 entries).","id":"cli:approvals/list","inputSchema":{"additionalProperties":false,"properties":{"target":{"type":"string"}},"required":["target"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/approvals/list.tsx"},{"contract":"contract:src/cli/approvals/respond.tsx#inputJsonSchema","description":"Explicit user decision: accept a Grok request once or decline; never grant persistent permissions.","id":"cli:approvals/respond","inputSchema":{"additionalProperties":false,"properties":{"decision":{"enum":["accept","decline"],"type":"string"},"entryId":{"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","entryId","requestId","decision"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/approvals/respond.tsx"},{"contract":"contract:src/cli/bots/create.tsx#inputJsonSchema","description":"Create a Grok Bot bot.","id":"cli:bots/create","inputSchema":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"name":{"type":"string"},"title":{"type":"string"}},"required":["name"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/create.tsx"},{"contract":"contract:src/cli/bots/delete.tsx#inputJsonSchema","description":"Delete a bot or group by id or name.","id":"cli:bots/delete","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/delete.tsx"},{"contract":"contract:src/cli/bots/get.tsx#inputJsonSchema","description":"Show one bot or group by id or name.","id":"cli:bots/get","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/get.tsx"},{"contract":"contract:src/cli/bots/list.tsx#inputJsonSchema","description":"List Grok Bot bots (not groups).","id":"cli:bots/list","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/list.tsx"},{"contract":"contract:src/cli/bots/update.tsx#inputJsonSchema","description":"Update a bot or group profile.","id":"cli:bots/update","inputSchema":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"hidden":{"type":"string"},"name":{"type":"string"},"notify":{"type":"string"},"ref":{"description":"Bot or group id or name","type":"string"},"title":{"type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/update.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/hosts.tsx#inputJsonSchema","description":"Discover ChatGPT Desktop hosts and modelProviders at runtime (never hardcode). Always includes local plus every remote-thread-summaries-v3:; Providers come from distinct thread/list and remote-summary values.","id":"cli:chatgpt-desktop/hosts","inputSchema":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port","type":"number"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/hosts.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/read.tsx#inputJsonSchema","description":"Read a ChatGPT Desktop thread via app-server (turns/list); CDP DOM is fallback only.","id":"cli:chatgpt-desktop/read","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior read page","type":"string"},"full":{"default":false,"type":"boolean"},"limit":{"description":"Recent default 100; full default 2000","type":"number"},"openTimeoutMs":{"default":90000,"type":"number"},"port":{"type":"number"},"threadId":{"type":"string"}},"required":["threadId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/read.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/search.tsx#inputJsonSchema","description":"Search ChatGPT Desktop threads. --host and --model-provider accept any string (see gbot chatgpt-desktop hosts); not enums.","id":"cli:chatgpt-desktop/search","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a prior search page","type":"string"},"groupBy":{"description":"Group results by host (grouping mode, not a host id)","enum":["host"],"type":"string"},"host":{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"limit":{"default":50,"description":"Max matches (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"port":{"description":"Local CDP port","type":"number"},"project":{"description":"Project label or projectId filter.","type":"string"},"query":{"type":"string"}},"required":["query"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/search.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/send.tsx#inputJsonSchema","description":"Send to ChatGPT Desktop via CDP composer. Omit --thread-id for a new chat; --project prefers Start new chat in .","id":"cli:chatgpt-desktop/send","inputSchema":{"additionalProperties":false,"properties":{"openTimeoutMs":{"type":"number"},"port":{"type":"number"},"project":{"type":"string"},"text":{"items":{"type":"string"},"type":"array"},"threadId":{"type":"string"},"unarchive":{"description":"Explicitly unarchive an existing archived thread before sending.","type":"boolean"}},"required":["text"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/send.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/status.tsx#inputJsonSchema","description":"Probe local ChatGPT Desktop CDP on 127.0.0.1 and report app-server availability for list/deep-read.","id":"cli:chatgpt-desktop/status","inputSchema":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port (default 9222)","type":"number"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/status.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/threads.tsx#inputJsonSchema","description":"List local + remote-control ChatGPT Desktop threads. --host and --model-provider accept any string (see gbot chatgpt-desktop hosts); not enums.","id":"cli:chatgpt-desktop/threads","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a previous page","type":"string"},"groupBy":{"description":"Group results by host (grouping mode, not a host id)","enum":["host"],"type":"string"},"host":{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"limit":{"default":50,"description":"Max threads (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"port":{"description":"Local CDP port","type":"number"},"project":{"description":"Project label or projectId filter.","type":"string"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/threads.tsx"},{"contract":"contract:src/cli/claude/send.tsx#inputJsonSchema","description":"Send to an explicitly enabled live Claude Code channel and wait for its reply.","id":"cli:claude/send","inputSchema":{"additionalProperties":false,"properties":{"message":{"type":"string"},"name":{"type":"string"},"timeoutMs":{"type":"number"}},"required":["name","message"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/claude/send.tsx"},{"contract":"contract:src/cli/codex/bridge/respond.tsx#inputJsonSchema","description":"Managed Grok/Codex bridge respond.","id":"cli:codex/bridge/respond","inputSchema":{"additionalProperties":false,"properties":{"answersJson":{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","type":"string"},"bindingId":{"type":"string"},"decision":{"enum":["accept","decline","cancel"],"type":"string"},"exchangeId":{"type":"string"},"generation":{"type":"string"},"interactionId":{"type":"string"},"threadId":{"type":"string"},"turnId":{"type":"string"}},"required":["interactionId","generation","threadId","turnId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/respond.tsx"},{"contract":"contract:src/cli/codex/bridge/run.tsx#inputJsonSchema","description":"Run a bounded foreground relay (up to 23 hours). Use the packaged gbot-relay.mjs script for unlimited service lifetime.","id":"cli:codex/bridge/run","inputSchema":{"additionalProperties":false,"properties":{"lifetimeMs":{"description":"Foreground lifetime in milliseconds (100..82800000; default 23h).","type":"number"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/run.tsx"},{"contract":"contract:src/cli/codex/bridge/start.tsx#inputJsonSchema","description":"Managed Grok/Codex bridge start.","id":"cli:codex/bridge/start","inputSchema":{"additionalProperties":false,"properties":{"busyPolicy":{"enum":["steer","reject"],"type":"string"},"codexThreadId":{"type":"string"},"expectedCwd":{"type":"string"},"grokTarget":{"type":"string"},"requestId":{"type":"string"}},"required":["grokTarget"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/start.tsx"},{"contract":"contract:src/cli/codex/bridge/status.tsx#inputJsonSchema","description":"Managed Grok/Codex bridge status.","id":"cli:codex/bridge/status","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"limit":{"type":"number"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/status.tsx"},{"contract":"contract:src/cli/codex/bridge/stop.tsx#inputJsonSchema","description":"Managed Grok/Codex bridge stop.","id":"cli:codex/bridge/stop","inputSchema":{"additionalProperties":false,"properties":{"all":{"type":"boolean"},"bindingId":{"type":"string"},"worker":{"type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/stop.tsx"},{"contract":"contract:src/cli/codex/desktop-shim.tsx#inputJsonSchema","description":"Install, remove, or check the ChatGPT Desktop shim: a CODEX_CLI_PATH wrapper that bridges Desktop stdio onto the managed Codex daemon (stock app-server proxy hangs). macOS persists via LaunchAgent; always fails open to real Codex.","id":"cli:codex/desktop-shim","inputSchema":{"additionalProperties":false,"properties":{"action":{"description":"install | uninstall | status","enum":["install","uninstall","status"],"type":"string"}},"required":["action"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/desktop-shim.tsx"},{"contract":"contract:src/cli/codex/list-threads.tsx#inputJsonSchema","description":"List Codex daemon-managed threads (all modelProviders; pages via --cursor / nextCursor).","id":"cli:codex/list-threads","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque pagination cursor from a previous nextCursor (may start with -)","type":"string"},"limit":{"default":20,"description":"Max threads to list (1-200)","type":"number"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/list-threads.tsx"},{"contract":"contract:src/cli/codex/new.tsx#inputJsonSchema","description":"Start a new Codex thread in --cwd, optionally with --model, --effort and a message.","id":"cli:codex/new","inputSchema":{"additionalProperties":false,"properties":{"cwd":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"expectedCwd":{"type":"string"},"message":{"items":{"type":"string"},"type":"array"},"model":{"type":"string"}},"required":["cwd"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/new.tsx"},{"contract":"contract:src/cli/codex/queue.tsx#inputJsonSchema","description":"List the experimental Codex thread queue (GROK_BOT_CODEX_EXPERIMENTAL=1).","id":"cli:codex/queue","inputSchema":{"additionalProperties":false,"properties":{"threadId":{"type":"string"}},"required":["threadId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/queue.tsx"},{"contract":"contract:src/cli/codex/send.tsx#inputJsonSchema","description":"Send to Codex; acceptance is distinct from completion. Options precede threadId.","id":"cli:codex/send","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"correlationId":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"envelope":{"type":"boolean"},"expectedCwd":{"type":"string"},"expectedTurnId":{"description":"Required active-turn guard for steer; stale guards reject.","type":"string"},"hop":{"type":"number"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"message":{"items":{"type":"string"},"type":"array"},"model":{"type":"string"},"replyTo":{"type":"string"},"replyToGrok":{"type":"string"},"requestId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"wait":{"type":"boolean"},"whenBusy":{"enum":["reject","queue","steer"],"type":"string"}},"required":["threadId","message"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/send.tsx"},{"contract":"contract:src/cli/codex/status.tsx#inputJsonSchema","description":"Probe the local Codex app-server daemon. Exit 0 only when it is usable.","id":"cli:codex/status","inputSchema":{"additionalProperties":false,"properties":{},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/status.tsx"},{"contract":"contract:src/cli/codex/wait.tsx#inputJsonSchema","description":"Bounded Codex wait observation; never interrupts execution.","id":"cli:codex/wait","inputSchema":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"messageId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"turnId":{"type":"string"}},"required":["threadId","turnId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/wait.tsx"},{"contract":"contract:src/cli/codex/watch.tsx#inputJsonSchema","description":"Bounded Codex watch observation; never interrupts execution.","id":"cli:codex/watch","inputSchema":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxEvents":{"description":"Maximum observed events: 1-500.","type":"number"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-600000 milliseconds.","type":"number"}},"required":["threadId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/watch.tsx"},{"contract":"contract:src/cli/doctor.tsx#inputJsonSchema","description":"Show which agents root and auth sources gbot can see.","id":"cli:doctor","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/doctor.tsx"},{"contract":"contract:src/cli/groups/add.tsx#inputJsonSchema","description":"Add a bot to a group.","id":"cli:groups/add","inputSchema":{"additionalProperties":false,"properties":{"bot":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"}},"required":["group","bot"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/add.tsx"},{"contract":"contract:src/cli/groups/create.tsx#inputJsonSchema","description":"Create a Grok Bot group.","id":"cli:groups/create","inputSchema":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"member":{"description":"Member bot id or name (repeatable)","items":{"type":"string"},"type":"array"},"name":{"type":"string"},"title":{"type":"string"}},"required":["name","member"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/create.tsx"},{"contract":"contract:src/cli/groups/delete.tsx#inputJsonSchema","description":"Delete a group by id or name.","id":"cli:groups/delete","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/delete.tsx"},{"contract":"contract:src/cli/groups/get.tsx#inputJsonSchema","description":"Show one group by id or name.","id":"cli:groups/get","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/get.tsx"},{"contract":"contract:src/cli/groups/list.tsx#inputJsonSchema","description":"List Grok Bot groups.","id":"cli:groups/list","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/list.tsx"},{"contract":"contract:src/cli/groups/members.tsx#inputJsonSchema","description":"Show members of a group (same payload as groups get).","id":"cli:groups/members","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/members.tsx"},{"contract":"contract:src/cli/groups/remove.tsx#inputJsonSchema","description":"Remove a bot from a group.","id":"cli:groups/remove","inputSchema":{"additionalProperties":false,"properties":{"bot":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"}},"required":["group","bot"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/remove.tsx"},{"contract":"contract:src/cli/groups/set.tsx#inputJsonSchema","description":"Replace a group's member list.","id":"cli:groups/set","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"},"member":{"description":"Member bot id or name (repeatable)","items":{"type":"string"},"type":"array"}},"required":["group","member"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/set.tsx"},{"contract":"contract:src/cli/groups/update.tsx#inputJsonSchema","description":"Update a group profile (members stay on set/add/remove).","id":"cli:groups/update","inputSchema":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"hidden":{"type":"string"},"name":{"type":"string"},"notify":{"type":"string"},"ref":{"description":"Group id or name","type":"string"},"title":{"type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/update.tsx"},{"contract":"contract:src/cli/history.tsx#inputJsonSchema","description":"Read the opt-in local JSONL history without contacting the gateway.","id":"cli:history","inputSchema":{"additionalProperties":false,"properties":{"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"limit":{"default":40,"description":"Maximum matching rows (1 or more)","type":"number"},"path":{"description":"Print the history file path","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"},"search":{"description":"Case-insensitive message text filter","type":"string"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/history.tsx"},{"contract":"contract:src/cli/send.tsx#inputJsonSchema","description":"Send a message to a Grok Bot bot or group by name or id.","id":"cli:send","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"codexThreadId":{"type":"string"},"correlationId":{"description":"Stable correlation id for multi-hop replies","type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"envelope":{"description":"Prepend the [gbot …] header","type":"boolean"},"expectedCwd":{"type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"hop":{"description":"Hop count; refused at GROK_BOT_MAX_HOPS","type":"number"},"message":{"items":{"type":"string"},"type":"array"},"noHistory":{"description":"Skip local history for this command","type":"boolean"},"replyMode":{"enum":["auto","manual"],"type":"string"},"replyTo":{"description":"Prior message id this send replies to","type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","message"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/send.tsx"},{"contract":"contract:src/cli/skills/add.tsx#inputJsonSchema","description":"Add a SKILL.md to the shared skill library. Every bot sees it.","id":"cli:skills/add","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"path":{"description":"SKILL.md file, or a directory holding one","type":"string"}},"required":["path"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/skills/add.tsx"},{"contract":"contract:src/cli/skills/list.tsx#inputJsonSchema","description":"List the skill library every bot in this Grok Bot shares.","id":"cli:skills/list","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/skills/list.tsx"},{"contract":"contract:src/cli/skills/remove.tsx#inputJsonSchema","description":"Remove a library skill by id or name. Every bot loses it.","id":"cli:skills/remove","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"skill":{"description":"Skill id or name","type":"string"}},"required":["skill"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/skills/remove.tsx"},{"contract":"contract:src/cli/thread.tsx#inputJsonSchema","description":"Read the most recent messages in a Grok Bot bot or group thread.","id":"cli:thread","inputSchema":{"additionalProperties":false,"properties":{"after":{"description":"Return entries after this opaque entry id","type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"full":{"description":"Show full entry text in human output","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"limit":{"default":40,"description":"How many trailing entries to return (1-200)","type":"number"},"noHistory":{"description":"Skip local history for this command","type":"boolean"},"root":{"description":"Read one rooted thread by message id","type":"string"},"target":{"type":"string"}},"required":["target"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/thread.tsx"}]},"contracts":[{"id":"contract:src/cli/approvals/list.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"target":{"type":"string"}},"required":["target"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/approvals/list.tsx"},"routes":["cli:approvals/list"]},{"id":"contract:src/cli/approvals/respond.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"decision":{"enum":["accept","decline"],"type":"string"},"entryId":{"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","entryId","requestId","decision"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/approvals/respond.tsx"},"routes":["cli:approvals/respond"]},{"id":"contract:src/cli/bots/create.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"name":{"type":"string"},"title":{"type":"string"}},"required":["name"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/create.tsx"},"routes":["cli:bots/create"]},{"id":"contract:src/cli/bots/delete.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/delete.tsx"},"routes":["cli:bots/delete"]},{"id":"contract:src/cli/bots/get.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/get.tsx"},"routes":["cli:bots/get"]},{"id":"contract:src/cli/bots/list.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/list.tsx"},"routes":["cli:bots/list"]},{"id":"contract:src/cli/bots/update.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"hidden":{"type":"string"},"name":{"type":"string"},"notify":{"type":"string"},"ref":{"description":"Bot or group id or name","type":"string"},"title":{"type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/update.tsx"},"routes":["cli:bots/update"]},{"id":"contract:src/cli/chatgpt-desktop/hosts.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port","type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/hosts.tsx"},"routes":["cli:chatgpt-desktop/hosts"]},{"id":"contract:src/cli/chatgpt-desktop/read.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior read page","type":"string"},"full":{"default":false,"type":"boolean"},"limit":{"description":"Recent default 100; full default 2000","type":"number"},"openTimeoutMs":{"default":90000,"type":"number"},"port":{"type":"number"},"threadId":{"type":"string"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/read.tsx"},"routes":["cli:chatgpt-desktop/read"]},{"id":"contract:src/cli/chatgpt-desktop/search.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a prior search page","type":"string"},"groupBy":{"description":"Group results by host (grouping mode, not a host id)","enum":["host"],"type":"string"},"host":{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"limit":{"default":50,"description":"Max matches (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"port":{"description":"Local CDP port","type":"number"},"project":{"description":"Project label or projectId filter.","type":"string"},"query":{"type":"string"}},"required":["query"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/search.tsx"},"routes":["cli:chatgpt-desktop/search"]},{"id":"contract:src/cli/chatgpt-desktop/send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"openTimeoutMs":{"type":"number"},"port":{"type":"number"},"project":{"type":"string"},"text":{"items":{"type":"string"},"type":"array"},"threadId":{"type":"string"},"unarchive":{"description":"Explicitly unarchive an existing archived thread before sending.","type":"boolean"}},"required":["text"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/send.tsx"},"routes":["cli:chatgpt-desktop/send"]},{"id":"contract:src/cli/chatgpt-desktop/status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port (default 9222)","type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/status.tsx"},"routes":["cli:chatgpt-desktop/status"]},{"id":"contract:src/cli/chatgpt-desktop/threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a previous page","type":"string"},"groupBy":{"description":"Group results by host (grouping mode, not a host id)","enum":["host"],"type":"string"},"host":{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"limit":{"default":50,"description":"Max threads (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"port":{"description":"Local CDP port","type":"number"},"project":{"description":"Project label or projectId filter.","type":"string"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/threads.tsx"},"routes":["cli:chatgpt-desktop/threads"]},{"id":"contract:src/cli/claude/send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"message":{"type":"string"},"name":{"type":"string"},"timeoutMs":{"type":"number"}},"required":["name","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/claude/send.tsx"},"routes":["cli:claude/send"]},{"id":"contract:src/cli/codex/bridge/respond.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"answersJson":{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","type":"string"},"bindingId":{"type":"string"},"decision":{"enum":["accept","decline","cancel"],"type":"string"},"exchangeId":{"type":"string"},"generation":{"type":"string"},"interactionId":{"type":"string"},"threadId":{"type":"string"},"turnId":{"type":"string"}},"required":["interactionId","generation","threadId","turnId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/respond.tsx"},"routes":["cli:codex/bridge/respond"]},{"id":"contract:src/cli/codex/bridge/run.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"lifetimeMs":{"description":"Foreground lifetime in milliseconds (100..82800000; default 23h).","type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/run.tsx"},"routes":["cli:codex/bridge/run"]},{"id":"contract:src/cli/codex/bridge/start.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"busyPolicy":{"enum":["steer","reject"],"type":"string"},"codexThreadId":{"type":"string"},"expectedCwd":{"type":"string"},"grokTarget":{"type":"string"},"requestId":{"type":"string"}},"required":["grokTarget"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/start.tsx"},"routes":["cli:codex/bridge/start"]},{"id":"contract:src/cli/codex/bridge/status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"limit":{"type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/status.tsx"},"routes":["cli:codex/bridge/status"]},{"id":"contract:src/cli/codex/bridge/stop.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"all":{"type":"boolean"},"bindingId":{"type":"string"},"worker":{"type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/stop.tsx"},"routes":["cli:codex/bridge/stop"]},{"id":"contract:src/cli/codex/desktop-shim.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"action":{"description":"install | uninstall | status","enum":["install","uninstall","status"],"type":"string"}},"required":["action"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/desktop-shim.tsx"},"routes":["cli:codex/desktop-shim"]},{"id":"contract:src/cli/codex/list-threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque pagination cursor from a previous nextCursor (may start with -)","type":"string"},"limit":{"default":20,"description":"Max threads to list (1-200)","type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/list-threads.tsx"},"routes":["cli:codex/list-threads"]},{"id":"contract:src/cli/codex/new.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cwd":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"expectedCwd":{"type":"string"},"message":{"items":{"type":"string"},"type":"array"},"model":{"type":"string"}},"required":["cwd"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/new.tsx"},"routes":["cli:codex/new"]},{"id":"contract:src/cli/codex/queue.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"threadId":{"type":"string"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/queue.tsx"},"routes":["cli:codex/queue"]},{"id":"contract:src/cli/codex/send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"correlationId":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"envelope":{"type":"boolean"},"expectedCwd":{"type":"string"},"expectedTurnId":{"description":"Required active-turn guard for steer; stale guards reject.","type":"string"},"hop":{"type":"number"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"message":{"items":{"type":"string"},"type":"array"},"model":{"type":"string"},"replyTo":{"type":"string"},"replyToGrok":{"type":"string"},"requestId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"wait":{"type":"boolean"},"whenBusy":{"enum":["reject","queue","steer"],"type":"string"}},"required":["threadId","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/send.tsx"},"routes":["cli:codex/send"]},{"id":"contract:src/cli/codex/status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/status.tsx"},"routes":["cli:codex/status"]},{"id":"contract:src/cli/codex/wait.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"messageId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"turnId":{"type":"string"}},"required":["threadId","turnId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/wait.tsx"},"routes":["cli:codex/wait"]},{"id":"contract:src/cli/codex/watch.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxEvents":{"description":"Maximum observed events: 1-500.","type":"number"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-600000 milliseconds.","type":"number"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/watch.tsx"},"routes":["cli:codex/watch"]},{"id":"contract:src/cli/doctor.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/doctor.tsx"},"routes":["cli:doctor"]},{"id":"contract:src/cli/groups/add.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bot":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"}},"required":["group","bot"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/add.tsx"},"routes":["cli:groups/add"]},{"id":"contract:src/cli/groups/create.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"member":{"description":"Member bot id or name (repeatable)","items":{"type":"string"},"type":"array"},"name":{"type":"string"},"title":{"type":"string"}},"required":["name","member"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/create.tsx"},"routes":["cli:groups/create"]},{"id":"contract:src/cli/groups/delete.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/delete.tsx"},"routes":["cli:groups/delete"]},{"id":"contract:src/cli/groups/get.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/get.tsx"},"routes":["cli:groups/get"]},{"id":"contract:src/cli/groups/list.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/list.tsx"},"routes":["cli:groups/list"]},{"id":"contract:src/cli/groups/members.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/members.tsx"},"routes":["cli:groups/members"]},{"id":"contract:src/cli/groups/remove.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bot":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"}},"required":["group","bot"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/remove.tsx"},"routes":["cli:groups/remove"]},{"id":"contract:src/cli/groups/set.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"},"member":{"description":"Member bot id or name (repeatable)","items":{"type":"string"},"type":"array"}},"required":["group","member"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/set.tsx"},"routes":["cli:groups/set"]},{"id":"contract:src/cli/groups/update.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"hidden":{"type":"string"},"name":{"type":"string"},"notify":{"type":"string"},"ref":{"description":"Group id or name","type":"string"},"title":{"type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/update.tsx"},"routes":["cli:groups/update"]},{"id":"contract:src/cli/history.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"limit":{"default":40,"description":"Maximum matching rows (1 or more)","type":"number"},"path":{"description":"Print the history file path","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"},"search":{"description":"Case-insensitive message text filter","type":"string"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/history.tsx"},"routes":["cli:history"]},{"id":"contract:src/cli/send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"codexThreadId":{"type":"string"},"correlationId":{"description":"Stable correlation id for multi-hop replies","type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"envelope":{"description":"Prepend the [gbot …] header","type":"boolean"},"expectedCwd":{"type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"hop":{"description":"Hop count; refused at GROK_BOT_MAX_HOPS","type":"number"},"message":{"items":{"type":"string"},"type":"array"},"noHistory":{"description":"Skip local history for this command","type":"boolean"},"replyMode":{"enum":["auto","manual"],"type":"string"},"replyTo":{"description":"Prior message id this send replies to","type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/send.tsx"},"routes":["cli:send"]},{"id":"contract:src/cli/skills/add.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"path":{"description":"SKILL.md file, or a directory holding one","type":"string"}},"required":["path"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/skills/add.tsx"},"routes":["cli:skills/add"]},{"id":"contract:src/cli/skills/list.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/skills/list.tsx"},"routes":["cli:skills/list"]},{"id":"contract:src/cli/skills/remove.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"skill":{"description":"Skill id or name","type":"string"}},"required":["skill"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/skills/remove.tsx"},"routes":["cli:skills/remove"]},{"id":"contract:src/cli/thread.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"after":{"description":"Return entries after this opaque entry id","type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"full":{"description":"Show full entry text in human output","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"limit":{"default":40,"description":"How many trailing entries to return (1-200)","type":"number"},"noHistory":{"description":"Skip local history for this command","type":"boolean"},"root":{"description":"Read one rooted thread by message id","type":"string"},"target":{"type":"string"}},"required":["target"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/thread.tsx"},"routes":["cli:thread"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"type":"number"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_list_hosts"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior page; keep filters unchanged.","type":"string"},"groupBy":{"description":"When \"host\", also return groups[] keyed by host (grouping mode, not a host id).","enum":["host"],"type":"string"},"host":{"description":"Any string filter for machine/location. Reserved: \"all\" (default), \"local\". Otherwise a hostId or friendly name discovered at runtime — see chatgpt_desktop_list_hosts. Not an enum; new machines/connections appear with no code change.","type":"string"},"limit":{"default":50,"description":"Maximum threads per page.","type":"number"},"modelProvider":{"description":"Any modelProvider id string (passed through to app-server modelProviders). Omit for all providers. Discovered values: see chatgpt_desktop_list_hosts. Not an enum.","type":"string"},"port":{"type":"number"},"project":{"description":"Match a Desktop project label or app-server projectId. Dynamic string, not an enum.","type":"string"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_list_threads"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"openTimeoutMs":{"description":"Maximum time to wait for the requested conversation (1-600000 ms).","type":"number"},"port":{"description":"Local CDP port (default 9222 or CHATGPT_DESKTOP_CDP_PORT).","type":"number"},"threadId":{"description":"local: or bare durable id. Temporary local:client-new-thread:* works only while selected; remote ids require their owning host.","type":"string"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_open_thread"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior read page. Keep threadId and full unchanged.","type":"string"},"full":{"description":"When true, page from the start through the complete history (up to 2000 turns by default); otherwise return the most recent 100 turns by default. Explicit limit bounds either mode.","type":"boolean"},"limit":{"type":"number"},"openTimeoutMs":{"description":"Max wait for Loading task… to clear after opening (default 90000).","type":"number"},"port":{"type":"number"},"threadId":{"description":"local:, bare durable id, or selected local:client-new-thread:* temporary id. Remote ids return REMOTE_THREAD_NOT_LOADED with hostId.","type":"string"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_read_thread"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the previous search page; keep query and filters unchanged.","type":"string"},"groupBy":{"description":"When \"host\", also return groups[] keyed by host (grouping mode, not a host id).","enum":["host"],"type":"string"},"host":{"description":"Any string filter for machine/location. Reserved: \"all\" (default), \"local\". Otherwise a hostId or friendly name discovered at runtime — see chatgpt_desktop_list_hosts. Not an enum; new machines/connections appear with no code change.","type":"string"},"limit":{"default":50,"description":"Maximum matches.","type":"number"},"modelProvider":{"description":"Any modelProvider id string (passed through to app-server modelProviders). Omit for all providers. Discovered values: see chatgpt_desktop_list_hosts. Not an enum.","type":"string"},"port":{"type":"number"},"project":{"description":"Match a Desktop project label or app-server projectId.","type":"string"},"query":{"description":"Case-insensitive substring over thread metadata.","type":"string"}},"required":["query"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_search_threads"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"openTimeoutMs":{"type":"number"},"port":{"type":"number"},"project":{"description":"With threadId omitted, create the new chat inside this project. Omit for a new chat outside projects.","type":"string"},"text":{"type":"string"},"threadId":{"description":"local:, bare durable id, or selected local:client-new-thread:*; omit for a new chat.","type":"string"},"unarchive":{"default":false,"description":"Existing threadId only: explicitly call thread/unarchive after ARCHIVED_THREAD, then retry the send once. Never implicit.","type":"boolean"}},"required":["text"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_send"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port (default 9222 or CHATGPT_DESKTOP_CDP_PORT).","type":"number"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_status"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"type":"number"},"threadId":{"description":"Durable local:, bare id, or selected local:client-new-thread:* from send.","type":"string"},"timeoutMs":{"default":120000,"type":"number"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_wait_reply"]},{"id":"contract:src/mcp/grok-bot/tools/claude_send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"message":{"type":"string"},"name":{"type":"string"},"timeoutMs":{"type":"number"}},"required":["name","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/claude_send.tsx"},"routes":["tool:grok-bot/claude_send"]},{"id":"contract:src/mcp/grok-bot/tools/codex_new.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cwd":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"expectedCwd":{"type":"string"},"message":{"type":"string"},"model":{"type":"string"}},"required":["cwd"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_new.tsx"},"routes":["tool:grok-bot/codex_new"]},{"id":"contract:src/mcp/grok-bot/tools/codex_send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"correlationId":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"envelope":{"type":"boolean"},"expectedCwd":{"type":"string"},"expectedTurnId":{"type":"string"},"hop":{"type":"number"},"maxOutputBytes":{"type":"number"},"message":{"type":"string"},"model":{"type":"string"},"replyTo":{"type":"string"},"replyToGrok":{"type":"string"},"requestId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"type":"number"},"wait":{"default":false,"type":"boolean"},"whenBusy":{"enum":["reject","queue","steer"],"type":"string"}},"required":["threadId","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_send.tsx"},"routes":["tool:grok-bot/codex_send"]},{"id":"contract:src/mcp/grok-bot/tools/codex_threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a previous page.","type":"string"},"limit":{"description":"Maximum threads in this page: 1-200. Pass modelProviders:[] internally so every provider is included; use cursor/nextCursor to page.","type":"number"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_threads.tsx"},"routes":["tool:grok-bot/codex_threads"]},{"id":"contract:src/mcp/grok-bot/tools/codex_wait.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"messageId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"turnId":{"type":"string"}},"required":["threadId","turnId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_wait.tsx"},"routes":["tool:grok-bot/codex_wait"]},{"id":"contract:src/mcp/grok-bot/tools/codex_watch.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxEvents":{"description":"Maximum observed events: 1-500.","type":"number"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-600000 milliseconds.","type":"number"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_watch.tsx"},"routes":["tool:grok-bot/codex_watch"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_bridge_start.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"busyPolicy":{"enum":["steer","reject"],"type":"string"},"codexThreadId":{"type":"string"},"expectedCwd":{"type":"string"},"grokTarget":{"type":"string"},"requestId":{"type":"string"}},"required":["grokTarget"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_bridge_start.tsx"},"routes":["tool:grok-bot/gbot_bridge_start"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_bridge_status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"limit":{"type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_bridge_status.tsx"},"routes":["tool:grok-bot/gbot_bridge_status"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_bridge_stop.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"all":{"type":"boolean"},"bindingId":{"type":"string"},"worker":{"type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_bridge_stop.tsx"},"routes":["tool:grok-bot/gbot_bridge_stop"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_codex_respond.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"answersJson":{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","type":"string"},"bindingId":{"type":"string"},"decision":{"enum":["accept","decline","cancel"],"type":"string"},"exchangeId":{"type":"string"},"generation":{"type":"string"},"interactionId":{"type":"string"},"threadId":{"type":"string"},"turnId":{"type":"string"}},"required":["interactionId","generation","threadId","turnId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_codex_respond.tsx"},"routes":["tool:grok-bot/gbot_codex_respond"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_grok_approvals.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"target":{"type":"string"}},"required":["target"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_grok_approvals.tsx"},"routes":["tool:grok-bot/gbot_grok_approvals"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_grok_respond.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"decision":{"enum":["accept","decline"],"type":"string"},"entryId":{"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","entryId","requestId","decision"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_grok_respond.tsx"},"routes":["tool:grok-bot/gbot_grok_respond"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"codexThreadId":{"type":"string"},"correlationId":{"type":"string"},"expectedCwd":{"type":"string"},"hop":{"description":"Explicit chain hop count, refused at the configured bound.","type":"number"},"message":{"type":"string"},"replyMode":{"enum":["auto","manual"],"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_send.tsx"},"routes":["tool:grok-bot/gbot_send"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_thread.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"after":{"description":"Opaque cursor from the previous call. Returns entries strictly after it; an unknown cursor resets with a bounded snapshot.","type":"string"},"full":{"default":false,"description":"Return entries with text up to bounded budgets (20k chars per entry, 200k total). Every entry reports truncated/fullLength; read any remainder with `gbot thread --full` / `--json` on the machine.","type":"boolean"},"limit":{"default":40,"description":"How many trailing entries to inspect (1-200). Entries are returned only with full:true.","type":"number"},"target":{"description":"Bot or group name or id, for example \"General\".","type":"string"}},"required":["target"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_thread.tsx"},"routes":["tool:grok-bot/gbot_thread"]}],"digest":"c0f041a6aedf5b5e8760c0125a69225707c642edb094259fa080c580fe89668c","events":[],"layouts":[],"providers":[],"scripts":[{"id":"script:gbot-relay","kind":"script","provenance":{"kind":"conventional"},"source":"src/scripts/gbot-relay.ts"}],"servers":[{"id":"mcp:grok-bot","mode":"generated","name":"grok-bot","routes":[{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx#inputJsonSchema","description":"Discover local, remote-control environment ids, managed SSH hosts, and modelProvider ids. hostName is null when Desktop has no real display name. Use hostId or label in list/search filters; remote thread ids must be read on the owning host. warnings report provider discovery failures.","id":"tool:grok-bot/chatgpt_desktop_list_hosts","inputSchema":{"additionalProperties":false,"properties":{"port":{"type":"number"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx#inputJsonSchema","description":"List one sorted Desktop inventory without duplicate rows. Pass nextCursor as cursor with unchanged filters until null; pages fill limit unless the MCP byte budget binds. A changed/expired inventory cursor requires restarting. Display titles are capped at 200 characters with titleTruncated:true. Filter by dynamic hostId/hostName, modelProvider, or Desktop project label/projectId; projectRootPath identifies the resolved workspace. Rows expose local:, location, hostId, and provider; remote rows require their owning host for reading or sending. Backend and warnings identify partial sources.","id":"tool:grok-bot/chatgpt_desktop_list_threads","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior page; keep filters unchanged.","type":"string"},"groupBy":{"description":"When \"host\", also return groups[] keyed by host (grouping mode, not a host id).","enum":["host"],"type":"string"},"host":{"description":"Any string filter for machine/location. Reserved: \"all\" (default), \"local\". Otherwise a hostId or friendly name discovered at runtime — see chatgpt_desktop_list_hosts. Not an enum; new machines/connections appear with no code change.","type":"string"},"limit":{"default":50,"description":"Maximum threads per page.","type":"number"},"modelProvider":{"description":"Any modelProvider id string (passed through to app-server modelProviders). Omit for all providers. Discovered values: see chatgpt_desktop_list_hosts. Not an enum.","type":"string"},"port":{"type":"number"},"project":{"description":"Match a Desktop project label or app-server projectId. Dynamic string, not an enum.","type":"string"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx#inputJsonSchema","description":"Navigate Desktop to an existing local: or bare conversation id, even when the row is absent from the sidebar. Archived routes return archived:true without unarchiving; read them with chatgpt_desktop_read_thread. A remote-control id is owned by its hostId and cannot be opened on this Mac. CDP_UNREACHABLE means Desktop must be reachable locally.","id":"tool:grok-bot/chatgpt_desktop_open_thread","inputSchema":{"additionalProperties":false,"properties":{"openTimeoutMs":{"description":"Maximum time to wait for the requested conversation (1-600000 ms).","type":"number"},"port":{"description":"Local CDP port (default 9222 or CHATGPT_DESKTOP_CDP_PORT).","type":"number"},"threadId":{"description":"local: or bare durable id. Temporary local:client-new-thread:* works only while selected; remote ids require their owning host.","type":"string"}},"required":["threadId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx#inputJsonSchema","description":"Read a local:, bare durable id, or selected temporary local:client-new-thread:* id. Pass nextCursor back as cursor with the same threadId/full mode until complete:true. Pages stop at a byte budget; oversized turns use ordered continuation fragments with stable turnKey and field offsets, without dropping text. Archived threads remain readable. Warnings explain partial pages or app-server errors. REMOTE_THREAD_NOT_LOADED includes the owning hostId: call on that host.","id":"tool:grok-bot/chatgpt_desktop_read_thread","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior read page. Keep threadId and full unchanged.","type":"string"},"full":{"description":"When true, page from the start through the complete history (up to 2000 turns by default); otherwise return the most recent 100 turns by default. Explicit limit bounds either mode.","type":"boolean"},"limit":{"type":"number"},"openTimeoutMs":{"description":"Max wait for Loading task… to clear after opening (default 90000).","type":"number"},"port":{"type":"number"},"threadId":{"description":"local:, bare durable id, or selected local:client-new-thread:* temporary id. Remote ids return REMOTE_THREAD_NOT_LOADED with hostId.","type":"string"}},"required":["threadId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx#inputJsonSchema","description":"Search full Desktop thread metadata by case-insensitive substring. Display titles are capped at 200 characters with titleTruncated:true. Pass nextCursor as cursor with unchanged query and filters to retrieve all matches. Dynamic hostId/hostName, modelProvider, and project filters apply. Remote results identify hostId and cannot be read on this Mac.","id":"tool:grok-bot/chatgpt_desktop_search_threads","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the previous search page; keep query and filters unchanged.","type":"string"},"groupBy":{"description":"When \"host\", also return groups[] keyed by host (grouping mode, not a host id).","enum":["host"],"type":"string"},"host":{"description":"Any string filter for machine/location. Reserved: \"all\" (default), \"local\". Otherwise a hostId or friendly name discovered at runtime — see chatgpt_desktop_list_hosts. Not an enum; new machines/connections appear with no code change.","type":"string"},"limit":{"default":50,"description":"Maximum matches.","type":"number"},"modelProvider":{"description":"Any modelProvider id string (passed through to app-server modelProviders). Omit for all providers. Discovered values: see chatgpt_desktop_list_hosts. Not an enum.","type":"string"},"port":{"type":"number"},"project":{"description":"Match a Desktop project label or app-server projectId.","type":"string"},"query":{"description":"Case-insensitive substring over thread metadata.","type":"string"}},"required":["query"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx#inputJsonSchema","description":"Send once through local Desktop CDP. With threadId, accept local:, bare durable id, or currently selected local:client-new-thread:*; remote ids must be sent on their hostId. Omit threadId and project for a new chat outside projects; omit threadId and set project for a new chat inside it. The empty view and project scope are checked before typing. New-thread receipts include temporaryThreadId when seen and return durable local: once resolved. ARCHIVED_THREAD rejects without sending; unarchive:true explicitly unarchives that existing thread first. PROJECT_UNAVAILABLE identifies a disabled project action or missing configured root; NEW_CHAT_NAVIGATION_FAILED reports an unchanged view promptly. CDP_UNREACHABLE and COMPOSER_HAS_DRAFT require operator inspection, not blind retry.","id":"tool:grok-bot/chatgpt_desktop_send","inputSchema":{"additionalProperties":false,"properties":{"openTimeoutMs":{"type":"number"},"port":{"type":"number"},"project":{"description":"With threadId omitted, create the new chat inside this project. Omit for a new chat outside projects.","type":"string"},"text":{"type":"string"},"threadId":{"description":"local:, bare durable id, or selected local:client-new-thread:*; omit for a new chat.","type":"string"},"unarchive":{"default":false,"description":"Existing threadId only: explicitly call thread/unarchive after ARCHIVED_THREAD, then retry the send once. Never implicit.","type":"boolean"}},"required":["text"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx#inputJsonSchema","description":"Check local ChatGPT Desktop CDP before send, wait, or open. reachable:false and exitCode:1 mean CDP is down even if appServerFallback.reachable is true; list/search/read may still work through app-server. There is no remote CDP transport.","id":"tool:grok-bot/chatgpt_desktop_status","inputSchema":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port (default 9222 or CHATGPT_DESKTOP_CDP_PORT).","type":"number"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx#inputJsonSchema","description":"After chatgpt_desktop_send, wait for the selected Desktop reply over CDP. Accept the returned durable local: or the temporary local:client-new-thread:* while selected; omit threadId only when staying on the same selected chat. Returns reply, durable threadId and conversationId. timeout is not proof the send failed; CDP_UNREACHABLE requires Desktop recovery. Remote ids must be handled on their hostId.","id":"tool:grok-bot/chatgpt_desktop_wait_reply","inputSchema":{"additionalProperties":false,"properties":{"port":{"type":"number"},"threadId":{"description":"Durable local:, bare id, or selected local:client-new-thread:* from send.","type":"string"},"timeoutMs":{"default":120000,"type":"number"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/claude_send.tsx#inputJsonSchema","description":"Send to a named, opted-in live Claude Code channel and wait for its reply. Unknown delivery must not be retried automatically. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.","id":"tool:grok-bot/claude_send","inputSchema":{"additionalProperties":false,"properties":{"message":{"type":"string"},"name":{"type":"string"},"timeoutMs":{"type":"number"}},"required":["name","message"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/claude_send.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_new.tsx#inputJsonSchema","description":"Start a new Codex thread on this machine in cwd, optionally sending its first message. Codex must run locally on the same machine as gbot.","id":"tool:grok-bot/codex_new","inputSchema":{"additionalProperties":false,"properties":{"cwd":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"expectedCwd":{"type":"string"},"message":{"type":"string"},"model":{"type":"string"}},"required":["cwd"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_new.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_send.tsx#inputJsonSchema","description":"Send to a Codex thread. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport. 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.","id":"tool:grok-bot/codex_send","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"correlationId":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"envelope":{"type":"boolean"},"expectedCwd":{"type":"string"},"expectedTurnId":{"type":"string"},"hop":{"type":"number"},"maxOutputBytes":{"type":"number"},"message":{"type":"string"},"model":{"type":"string"},"replyTo":{"type":"string"},"replyToGrok":{"type":"string"},"requestId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"type":"number"},"wait":{"default":false,"type":"boolean"},"whenBusy":{"enum":["reject","queue","steer"],"type":"string"}},"required":["threadId","message"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_send.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_threads.tsx#inputJsonSchema","description":"Discover a bounded page of Codex daemon threads. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.","id":"tool:grok-bot/codex_threads","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a previous page.","type":"string"},"limit":{"description":"Maximum threads in this page: 1-200. Pass modelProviders:[] internally so every provider is included; use cursor/nextCursor to page.","type":"number"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_threads.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_wait.tsx#inputJsonSchema","description":"Explicit diagnostic observation of one Codex turn; returns execution and final reply without interrupting it. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.","id":"tool:grok-bot/codex_wait","inputSchema":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"messageId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"turnId":{"type":"string"}},"required":["threadId","turnId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_wait.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_watch.tsx#inputJsonSchema","description":"Watch bounded Codex thread events for diagnostics without answering approvals. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.","id":"tool:grok-bot/codex_watch","inputSchema":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxEvents":{"description":"Maximum observed events: 1-500.","type":"number"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-600000 milliseconds.","type":"number"}},"required":["threadId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_watch.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_bridge_start.tsx#inputJsonSchema","description":"Link a Grok conversation to Codex once. New visible Grok messages arrive automatically and Codex final answers return to Grok.","id":"tool:grok-bot/gbot_bridge_start","inputSchema":{"additionalProperties":false,"properties":{"busyPolicy":{"enum":["steer","reject"],"type":"string"},"codexThreadId":{"type":"string"},"expectedCwd":{"type":"string"},"grokTarget":{"type":"string"},"requestId":{"type":"string"}},"required":["grokTarget"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_bridge_start.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_bridge_status.tsx#inputJsonSchema","description":"Inspect worker health, route coverage, bounded receipts and scoped pending operator interactions.","id":"tool:grok-bot/gbot_bridge_status","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"limit":{"type":"number"}},"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_bridge_status.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_bridge_stop.tsx#inputJsonSchema","description":"Stop a binding without deleting receipts or interrupting Codex. all stops all bindings; worker explicitly shuts down the worker.","id":"tool:grok-bot/gbot_bridge_stop","inputSchema":{"additionalProperties":false,"properties":{"all":{"type":"boolean"},"bindingId":{"type":"string"},"worker":{"type":"boolean"}},"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_bridge_stop.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_codex_respond.tsx#inputJsonSchema","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.","id":"tool:grok-bot/gbot_codex_respond","inputSchema":{"additionalProperties":false,"properties":{"answersJson":{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","type":"string"},"bindingId":{"type":"string"},"decision":{"enum":["accept","decline","cancel"],"type":"string"},"exchangeId":{"type":"string"},"generation":{"type":"string"},"interactionId":{"type":"string"},"threadId":{"type":"string"},"turnId":{"type":"string"}},"required":["interactionId","generation","threadId","turnId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_codex_respond.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_grok_approvals.tsx#inputJsonSchema","description":"List pending auto-review and local-tool approval cards in the latest 200 entries for a Grok bot. Older or unsupported requests require the owning Grok UI.","id":"tool:grok-bot/gbot_grok_approvals","inputSchema":{"additionalProperties":false,"properties":{"target":{"type":"string"}},"required":["target"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_grok_approvals.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_grok_respond.tsx#inputJsonSchema","description":"Only after an explicit user decision: accept one current Grok approval once or decline it. Exact target, entryId and approval requestId required. Never auto-approve or grant persistent permissions. Success acknowledges response delivery, not execution.","id":"tool:grok-bot/gbot_grok_respond","inputSchema":{"additionalProperties":false,"properties":{"decision":{"enum":["accept","decline"],"type":"string"},"entryId":{"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","entryId","requestId","decision"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_grok_respond.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_send.tsx#inputJsonSchema","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.","id":"tool:grok-bot/gbot_send","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"codexThreadId":{"type":"string"},"correlationId":{"type":"string"},"expectedCwd":{"type":"string"},"hop":{"description":"Explicit chain hop count, refused at the configured bound.","type":"number"},"message":{"type":"string"},"replyMode":{"enum":["auto","manual"],"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","message"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_send.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_thread.tsx#inputJsonSchema","description":"Read a bounded Grok Bot thread tail. Returns a small receipt by default; pass the last cursor as after for an exclusive client-side delta, or full:true to include bounded entry text.","id":"tool:grok-bot/gbot_thread","inputSchema":{"additionalProperties":false,"properties":{"after":{"description":"Opaque cursor from the previous call. Returns entries strictly after it; an unknown cursor resets with a bounded snapshot.","type":"string"},"full":{"default":false,"description":"Return entries with text up to bounded budgets (20k chars per entry, 200k total). Every entry reports truncated/fullLength; read any remainder with `gbot thread --full` / `--json` on the machine.","type":"boolean"},"limit":{"default":40,"description":"How many trailing entries to inspect (1-200). Entries are returned only with full:true.","type":"number"},"target":{"description":"Bot or group name or id, for example \"General\".","type":"string"}},"required":["target"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_thread.tsx"}]}]},"runtime":{"node":"22.19.0"}} +{"application":{"description":"Message Grok Bot from Codex, Claude Code, and Cursor. Codex/Claude tools use local sockets on the user's registered machines only (no remote transport); from the Grok Bot box, run gbot via Grok Bot Shell with a machineId.","id":"plugin:gbot","name":"gbot","version":"0.11.3"},"compiler":{"adapters":[{"adapterRevision":"1.28.0","host":"claude","observedVersion":"2.1.260","schemas":[{"name":"hooks","revision":"2.1.260","sha256":"0cdfc5eb5201f2c3091768559ac82f4c563ccb1b7bce7a39d5f99e5f404654cb"},{"name":"lsp","revision":"2.1.260","sha256":"b4419c5d857267c7e2b21e3e1eb98b4fdc302c87109007190d3258e6ba7096e4"},{"name":"marketplace","revision":"2.1.260","sha256":"31ee4cc43ba5ce2be248030a69da2d31171550b2cc51c1fcb9f788a8ab92783d"},{"name":"mcp","revision":"2.1.260","sha256":"edd4770e41d6aee5beae1ff918d33139613a243e454ecbd52b72fa824be4a662"},{"name":"monitors","revision":"2.1.260","sha256":"6378d94b51fb7c784eaee178237008a03da0f889d0520d57486784954a1d484c"},{"name":"plugin","revision":"2.1.260","sha256":"2a976091b81ad07ae8eca57f6f9c5749efeba17fa089a0c12b6ca84d6e70f118"},{"name":"settings","revision":"2.1.260","sha256":"2bbca553621dbf9433a9b7d1ff7952543a368434f2d999a4e4e360b95b6d4c3d"},{"name":"theme","revision":"2.1.260","sha256":"9931264e6f5a1d4b3b854ce7a17d602c9ba1b57cc1991f1d3991b316eaa81ac2"}]},{"adapterRevision":"1.13.0","host":"codex","observedVersion":"0.147.0","schemas":[{"name":"app","revision":"0.147.0","sha256":"01c720a645e437bf0c4f8c26fd4cb5a13988e5649e4a8562ee23a1d4b7355c6a"},{"name":"hooks","revision":"0.147.0","sha256":"175b859eb8e85bd287d85ee840d97c3f5c2d0dda3223507a796d158e3770eeba"},{"name":"marketplace","revision":"0.147.0","sha256":"fbccce3ade39e1b077fcb440e60260de6e811e8c2d222b2ae0fe8fe47706b470"},{"name":"mcp","revision":"0.147.0","sha256":"75bd50f9fcb85c2e8d43bc132d61c172a02f28ea8bb77389816ae77b14a4257e"},{"name":"plugin","revision":"0.147.0","sha256":"074c6c71966a3e6560ccbceb8d82ec6a40cb1eccee2f2d863fb4ef1e2276a814"}]},{"adapterRevision":"1.13.0","host":"cursor","observedVersion":"2026-08-28","schemas":[{"name":"hooks","revision":"2026-08-28","sha256":"06154b7afa0861df462130b988912b897e7ccf962b8dd20c09193100bcde5d81"},{"name":"marketplace","revision":"2026-08-28","sha256":"1aae96a24c2796419933bc8bfe3a1255394e7199c35740b36325e0ce6dbc253d"},{"name":"mcp","revision":"2026-08-28","sha256":"f3fa4615afefe004c4fbcc09e635d890df0f1ec0cb39540feab72cbd3a31d844"},{"name":"plugin","revision":"2026-08-28","sha256":"a393b758901803fcf5cfe0d77bda8a83e987d32c3377dfce2d9edf445af884ed"}]},{"adapterRevision":"1.10.0","host":"portable","observedVersion":"1.0.0","schemas":[{"name":"mcp","revision":"1.0.0","sha256":"6539175bfcdf43085855183e86da40ea94b166547a72b47ae9a0a390516d3acb"},{"name":"plugin","revision":"1.0.0","sha256":"0a4aad95ce337878ad38802ebf0daa3fde76abe3f65400c86bcbb1ec0b3ab883"}]}],"agentSkills":{"schemaSha256":"6d06b61e423317421de2295ea1fd0c7b4491bfa36c5b7705c28616dfe76d4047","sourceRevision":"69ef37e9424c0a7ea9dd2293b559e43ec8176379","specification":"https://raw.githubusercontent.com/agentskills/agentskills/69ef37e9424c0a7ea9dd2293b559e43ec8176379/docs/specification.mdx"},"producer":{"name":"agent-bundle","version":"0.3.2"},"project":{"configDigest":"7718be28a54eb7ec9e28b9653ef671683604436af21e1eda99c11098f43e278f","configPath":"agent-bundle.config.ts","modelDigest":"3eb665db7a32ea2486558bfbaad275e1051f7ec59599eceaae856bc50d2fb8dc","packageName":"grok-bot-cli","packageVersion":"0.11.3","revision":"f8c67a6ba57d33d5ffeb12ce8388586450125b172ca91b1d59f35f7e37f5cb3e","sourceInputs":[{"executable":false,"path":".changeset/codex-sender-prefix-thread-search.md","sha256":"3ac235fedb28006900d3375c0eb4448a9eced1301093ecd2c0b8c2c18909f987"},{"executable":false,"path":".changeset/config.json","sha256":"0a97ce5d0488bada887ee9ea3726edecc727454b7da0294f1b5fe4947f48ee7c"},{"executable":false,"path":".changeset/README.md","sha256":"495bd4805f8362853bce99689c1cd75db8c475dfa38930619d2e197d7554db27"},{"executable":false,"path":".github/workflows/changeset.yml","sha256":"0139beb8a3dc0e95126c9701d09251a879331b1e8c5540bbfc69848525b40f23"},{"executable":false,"path":".github/workflows/ci.yml","sha256":"17a58cf5ceff03b7922d15c9b0eea11ae3e0fd00a581ff6881f69cf795f3ec0b"},{"executable":false,"path":".github/workflows/release.yml","sha256":"9c97360a2221fca9317edcac0eb343298c765e3b34bd048f916c47533dd90311"},{"executable":false,"path":".gitignore","sha256":"30aaeac24084f0a642d811aa493fc51b0fd3eddff322d359c39c573d8394ff3e"},{"executable":false,"path":".npmrc","sha256":"da47110e4c2d7cd216cd495b604ca78bd0f5caaca32da4837ec0efa6f967bba0"},{"executable":false,"path":"agent-bundle.config.ts","sha256":"7718be28a54eb7ec9e28b9653ef671683604436af21e1eda99c11098f43e278f"},{"executable":false,"path":"AGENTS.md","sha256":"e18ce90a031c533e7226789b97f6bce4aa7994b672544e0f425d20cc3bc15d29"},{"executable":false,"path":"CHANGELOG.md","sha256":"b6c5da29bce3a450517ce7bf023f48ccd10d2b627898c78f87b1ea486393871d"},{"executable":false,"path":"demo/grok-bot-cli-demo.gif","sha256":"0fe01e15fd2abbbc5cc3313e42931d404d3a320764e22fdcfb995f1a45dd73cd"},{"executable":false,"path":"demo/grok-bot-cli-demo.mp4","sha256":"b6ed66e43616674096c2f0a4a4da46fe4693c681833eab013f872a66b9ff933c"},{"executable":false,"path":"docs/chatgpt-desktop-cdp.md","sha256":"6dd6cfe00e9a888c1ced79f1db85744f9c92affef8a78126e22ea5205e76b732"},{"executable":false,"path":"docs/codex-busy-threads.md","sha256":"42509e8e4c2b519949f06d4e7028b8973d56f8fc0cd98decdb231375bb49d38d"},{"executable":false,"path":"docs/codex-duplex-architecture.md","sha256":"792f1be8bad508b042c5813c1fc3b7ea5ac87032803227830666727306e55fa2"},{"executable":false,"path":"docs/verification/2026-09-15-duplex.md","sha256":"c7d97f709a3c2d851c0a24690321bbda161ec925b4143a456b9951e174bf75df"},{"executable":false,"path":"LICENSE","sha256":"bc48c8a0f6b6e45842e574c79a6b955fe683ed13f48a50cc08bcccdb1a59fe59"},{"executable":false,"path":"package-lock.json","sha256":"b78a19ed744a3a7c91a1357a7ccd51c0f9d125919abc7d239316fc03ddce98bb"},{"executable":false,"path":"package.json","sha256":"b273cd753bb56a470c0b7ac145ac84d06a54cbcd794811ad460395228c5ba20d"},{"executable":false,"path":"README.md","sha256":"aaa6ac323105acb3f78afbaf4e7fde97dc8fab2276fdad9446ba783a0a2589e9"},{"executable":false,"path":"renovate.json","sha256":"e80b4e42a3043bc12fa0640db4bac392d2bf770acf841360d7c8ceeeac2ec1a9"},{"executable":false,"path":"rstest.route-unit.config.ts","sha256":"7286e20dc3d4162673e7c3dfe824db00307e1fda178410f23044a97286d141f2"},{"executable":false,"path":"scripts/run-unit-tests.mjs","sha256":"483f91b4856ce294a483dd2e62ca53bf09301adbc4c5fc9571da0e1d28049bc6"},{"executable":false,"path":"src/cli/_shared.ts","sha256":"555210759d9b2e2e60a01452c137abd73bad42bfab8b2311b66a3ab97f4ee5e9"},{"executable":false,"path":"src/cli/approvals/list.tsx","sha256":"8d21320b6cd9d6b2a266fd30196b8a439960f865a6f0a5dacf5845d64ed7388c"},{"executable":false,"path":"src/cli/approvals/respond.tsx","sha256":"7d9fe6e641deb08f444684733daac6da47fb472d90ed0e9ff77892f376a87255"},{"executable":false,"path":"src/cli/bots/create.tsx","sha256":"9f7a73a0595b642dd77f008ad596bcafd00fc5846ec1abff2ce62819d983eb84"},{"executable":false,"path":"src/cli/bots/delete.tsx","sha256":"126b53ac1da4a657f22d1a6770ddbab2cc66715c811de0873d50016bbe39cbf2"},{"executable":false,"path":"src/cli/bots/get.tsx","sha256":"f0c752a3b498819083a8ee5aa918d275727f1cc94d8774d8c84ac74db66e8a71"},{"executable":false,"path":"src/cli/bots/list.tsx","sha256":"21c0f7e39005860dfc2514b71f745bb4cab29d409ef2cff26f8759bb0fd261c1"},{"executable":false,"path":"src/cli/bots/update.tsx","sha256":"33b7f5aafbf931cf3cb5ecf423a76dacd09adb117a7d5490050639ae7f4210dd"},{"executable":false,"path":"src/cli/chatgpt-desktop/hosts.tsx","sha256":"64e3e873115a4f5c2b6a7fd68236dbf2ca4e4a880ba97bdd7409b48931bca632"},{"executable":false,"path":"src/cli/chatgpt-desktop/read.tsx","sha256":"11c86f604c2ee405f7544394db60ee1b36917d0b90769d441fcd361b5f0fe038"},{"executable":false,"path":"src/cli/chatgpt-desktop/search.tsx","sha256":"0dc3acdea178ff14d6c1c4b8b3bf1e18af47984f63b8ed8c41483e4da4b72f08"},{"executable":false,"path":"src/cli/chatgpt-desktop/send.tsx","sha256":"b801a028980e60fe37dca56e86887a1e2b0b8ce80ce77b379e7375d2e4544d5e"},{"executable":false,"path":"src/cli/chatgpt-desktop/status.tsx","sha256":"141b7b6db6d6f9236dd5343ca9495200752937b05764ad7fa7261631c2db5bbc"},{"executable":false,"path":"src/cli/chatgpt-desktop/threads.tsx","sha256":"d0a33935d992af349c52ef448622da5e460b4af1a9474aac60994295245b43ad"},{"executable":false,"path":"src/cli/claude/send.tsx","sha256":"d650caadec248aa59530d124ca6186c45d9f9fe1fb0f9c805e9eef6dc9f06d92"},{"executable":false,"path":"src/cli/codex/bridge/respond.tsx","sha256":"9d3a6af4904af6e44583dfb4ef317b3fe1045a78e765fc27406eaca9bcadcd13"},{"executable":false,"path":"src/cli/codex/bridge/run.tsx","sha256":"a49d334bebb00db62ad2c54370a47ec2c9119b4c07eb6ba11fc4bba4dd8e4217"},{"executable":false,"path":"src/cli/codex/bridge/start.tsx","sha256":"9e423cf5d65168606f6235baa2bcd127eb949647f7a4dee284d75f831474524d"},{"executable":false,"path":"src/cli/codex/bridge/status.tsx","sha256":"c801f69080985c87025429fb136487acdfac093acb07241b3417ea9a83915a18"},{"executable":false,"path":"src/cli/codex/bridge/stop.tsx","sha256":"6710e298a21d124c442d5aa1a3744280e5cd4df93213797f2ea3c0654174184a"},{"executable":false,"path":"src/cli/codex/desktop-shim.tsx","sha256":"fa3d88d11895bc4a15700bd590c055aa392b2b0e0c1185c52da233a23589aba0"},{"executable":false,"path":"src/cli/codex/list-threads.tsx","sha256":"6675fb6ef19acb63375bf47d302083d4bde055ce3dfc8c9db39664f3ec68b0f1"},{"executable":false,"path":"src/cli/codex/new.tsx","sha256":"11d0658c1a3e7173d53b71446b184fccccd867baefc6f733e43a9d543ca26ec9"},{"executable":false,"path":"src/cli/codex/queue.tsx","sha256":"7993ac5b827042cd95041775b183fde2d112b5ba7d5c82098e778a44e473826d"},{"executable":false,"path":"src/cli/codex/send.tsx","sha256":"a1b30f053a9e65bac561cd04d1361e292e2c672bbf69a6d76d2bdda441c46757"},{"executable":false,"path":"src/cli/codex/status.tsx","sha256":"b8c31001cb2892c1bfccf502f9776ee06998eac4fc0356f92936fa2c34f272d8"},{"executable":false,"path":"src/cli/codex/wait.tsx","sha256":"0a4cc6c440ad496682031658bda375fee29f5c346d833618d4f143de29b351cd"},{"executable":false,"path":"src/cli/codex/watch.tsx","sha256":"3280f42d15941cfd00b3727d9e271972c39165bd28db8f56acca5664d777cb4d"},{"executable":false,"path":"src/cli/doctor.tsx","sha256":"c30ce4e57fe707d36de29700abf5a2c56834bb4fb3adf2a70bb1089b4150ddc8"},{"executable":false,"path":"src/cli/groups/add.tsx","sha256":"2a5de115852f0ca6a6638300bd5006862a02a2f1e2f527b6fd680f610c1d777a"},{"executable":false,"path":"src/cli/groups/create.tsx","sha256":"da3f2539f338063daf51b80d86c27b2752f0e4a0334078d11508e27981590fa3"},{"executable":false,"path":"src/cli/groups/delete.tsx","sha256":"2d4e91113a2c24cefefcfd464513918791592b5e8734a4ef901eabe42c9c7289"},{"executable":false,"path":"src/cli/groups/get.tsx","sha256":"efed88fb3ab7292d60d6532f1f966f784ba3376b7826c9f3e5028467f86241e9"},{"executable":false,"path":"src/cli/groups/list.tsx","sha256":"f3cd229d41dd389b767447a04267700ab2293eae87a878f7d88149cb5798f4a6"},{"executable":false,"path":"src/cli/groups/members.tsx","sha256":"9b9eaecb65ea995006eff1b24a287110d16bf4830a0b0d07221c2f1317853641"},{"executable":false,"path":"src/cli/groups/remove.tsx","sha256":"96dd85d1b9732681ce9dc126ac3ae562d3f287f4c28e36b9a8f8c301dc93f63d"},{"executable":false,"path":"src/cli/groups/set.tsx","sha256":"4f9d90db612f14ddbb6d2afa5e45b66f044aed661ff95415e567e1be3b6108c6"},{"executable":false,"path":"src/cli/groups/update.tsx","sha256":"f44305815ddb6e27286f97ef68c04cfa5548acd5f04b1aba10ee7ce3cdbfc851"},{"executable":false,"path":"src/cli/history.tsx","sha256":"5151b48113b4ba0516bacabfabcd48e3256ead807c34d914deb84f31ded0b062"},{"executable":false,"path":"src/cli/send.tsx","sha256":"47297793ba98380300c45951d4d36e68b0f74e2933a5b6ac6634c4b6708f5ce7"},{"executable":false,"path":"src/cli/skills/add.tsx","sha256":"fbde237d172c026d7912174e705c03cbc9d74dad7806fc58c6ceb43127c69ba6"},{"executable":false,"path":"src/cli/skills/list.tsx","sha256":"34f255687c69aaf598a1dc54220453b57c46ed9ab4a168648d9c7eca6535ebae"},{"executable":false,"path":"src/cli/skills/remove.tsx","sha256":"21662c80a62f276c2dfd840a328e9665c0c5f63959a239d4dd877372c46f60d0"},{"executable":false,"path":"src/cli/thread.tsx","sha256":"29ab775936fa2987cb789754a44888fc52bdaad07180c5471122dda508cfd0c2"},{"executable":false,"path":"src/commands/codex-send.md","sha256":"1f88961a6656ae94a5cadd86e25eeaae111ee4c6aaad64f32917ac0c9d8410b8"},{"executable":false,"path":"src/commands/codex-threads.md","sha256":"e17b90cb8b0115a53161f83797ec55ca65e81600396cf3ea896b6306d2fb2dd2"},{"executable":false,"path":"src/commands/codex-wait.md","sha256":"acd0aaf00329256b874ec59666d2d803bbaf86b1d249d996a5f226b559619530"},{"executable":false,"path":"src/core/app-session.js","sha256":"2b2eb53ec3f4c7ea0dccf269fa9720af6f1ce36b8ca36e889d2bb271a092717d"},{"executable":false,"path":"src/core/chatgpt-desktop/adapter.ts","sha256":"5a0a4f2cea9f1fc1a739c534aed3979c28e0bd9c057b8475e6251974ad44ed7a"},{"executable":false,"path":"src/core/chatgpt-desktop/app-server-fallback.ts","sha256":"44002096eea29b5ea26d5b3d186b5616fcdab570888e3cb86fd4b5c5804af04c"},{"executable":false,"path":"src/core/chatgpt-desktop/cdp-adapter.ts","sha256":"db60fdd3be0259a6c76cad7d8ff86eddc6acbbd21c5f20d6aeffff5390063efa"},{"executable":false,"path":"src/core/chatgpt-desktop/cdp-dom.ts","sha256":"a122fb76626006fa8dedb7088f9b5533a8058c3a58838692b168e0753b7c89eb"},{"executable":false,"path":"src/core/chatgpt-desktop/cdp-session.ts","sha256":"8d6512ee80b179eedf54504110c1e88c5233b0b922667b00f87751452164cc00"},{"executable":false,"path":"src/core/chatgpt-desktop/errors.ts","sha256":"941ce4a9148fc53086cce64336dba473c1f7e4138774fd50a8ae524dcc05d34d"},{"executable":false,"path":"src/core/chatgpt-desktop/facade.ts","sha256":"bc9ac3bfd24db8458af6d20893fb3ab2ed701778f709aadbd141d61ed6c6c29b"},{"executable":false,"path":"src/core/chatgpt-desktop/index.ts","sha256":"591e6968c008cc75827da94b91c0ea15e573640876814e35e2470342dc8bccf9"},{"executable":false,"path":"src/core/chatgpt-desktop/loopback.ts","sha256":"b746681e5c45c67445e6620f850eff7c4627e13979747a7f686374c10a51f52f"},{"executable":false,"path":"src/core/chatgpt-desktop/payload-budget.ts","sha256":"89410474315b3769bad58d3ab61999e169410b7d1fdc20819efb4ee9c82fe1ac"},{"executable":false,"path":"src/core/chatgpt-desktop/project-state.ts","sha256":"b33e55b6d6abf15f3d7d1489b8b178d4e907ea83ed1a47d88f8f178a574709f8"},{"executable":false,"path":"src/core/chatgpt-desktop/relaunch.ts","sha256":"14851e115de7c45e256c4b9c3829dc4e796f1d989cf67d65115701a30b6d3a81"},{"executable":false,"path":"src/core/chatgpt-desktop/remote-threads.ts","sha256":"ed93418ff5d2bb51016783e7b0a458805e709b212974a66be804ddb9f7038033"},{"executable":false,"path":"src/core/chatgpt-desktop/routes.ts","sha256":"ccf8cde780da6e6e03f11e4dcc0d9d6bc4a6a3fd20d3210e74f0217e3660b7e1"},{"executable":false,"path":"src/core/chatgpt-desktop/thread-ids.ts","sha256":"0fe25e9d32c078bd9e7a171ab4bc4ee0b15190cd6d6c4d3b345926b3c608e082"},{"executable":false,"path":"src/core/chatgpt-desktop/types.ts","sha256":"59f89694eed34206e32db2a0afb48670bb164a4ffffacb907c8629bb0ce4bcca"},{"executable":false,"path":"src/core/claude-channel.js","sha256":"01ac7daef748a11bc99e132950ed7c59f50442e417eecf894b59cb4bb484202f"},{"executable":false,"path":"src/core/claude-routes.ts","sha256":"d34ddf25b8634ef86d46ab663f30a49aaedf87f8dc98e4036f84c1c88efa4083"},{"executable":false,"path":"src/core/codex-bridge.js","sha256":"b62ddd7833a937f66f7557fdd44e67d43e65f7babd1ecb36f029d3e068c7c32d"},{"executable":false,"path":"src/core/codex/contract.js","sha256":"16bcbd0fc09844166c52694ebb1075e60b91296a8f04fb02ad061c30b0e9c591"},{"executable":false,"path":"src/core/codex/conversation.js","sha256":"05abb2253480d0793bf5f6b3db17c47e7d154973747074c7c76a79e6f61b7deb"},{"executable":false,"path":"src/core/codex/remote-control.js","sha256":"52565007799e98c3bff4297287d8e53005e285a95bab9e4e4d0a088bded4fa8e"},{"executable":false,"path":"src/core/codex/routes.ts","sha256":"4fd73b060ee7bc6ac00abe552b1e39baca5e9aba0bb1a095267148c00d0526cc"},{"executable":false,"path":"src/core/codex/thread-id.js","sha256":"4eb6c1929c2e7687ed6c1422789fa01c3e1c556ead7d16355eafbae46a7126f4"},{"executable":false,"path":"src/core/commands.js","sha256":"3ad8fafb86744a57992da93ad838ade0e9acb1b7ca09b829cefadbf2781be0c9"},{"executable":false,"path":"src/core/desktop-shim-bridge.js","sha256":"58f3f39b8527adf58f57313e02e34322b203b8c38d1acfbad419a8b9af214443"},{"executable":false,"path":"src/core/desktop-shim.js","sha256":"500b8617bade6fa1a9c395826e197892fb864067044cac80ab025849f8fd6f82"},{"executable":false,"path":"src/core/format.js","sha256":"2febec5c6b7d1c8e7b3a3af2bf400f13653364a42492291b63678200fd05748e"},{"executable":false,"path":"src/core/gateway.js","sha256":"3a4f838ee423600d29e05f58060dcaf81cdcea4ac93b36dd6108363ac24bc606"},{"executable":false,"path":"src/core/grok-approval-routes.ts","sha256":"a33daa4d05e0c2594c795bd7654c22f3e1003e4aaad41cd70034d03651dd01f9"},{"executable":false,"path":"src/core/grok-approvals.js","sha256":"6b651a65bdd17241dd5b7a01d94a318ece9356c1c9b965b0578e08250d74e8fe"},{"executable":false,"path":"src/core/headers.js","sha256":"e229f2826ebdfb52949dab500798c0fa8a5ff7c4e63de91a63103bf45d2ae3cc"},{"executable":false,"path":"src/core/history.js","sha256":"38ca8e8f8dcd2ad42952c424ea9f00be5972d8751e4c0ac87214171903d82d89"},{"executable":false,"path":"src/core/relay/codex.js","sha256":"ff6e8f3158d171911a35b829cd76e1f5fd8319f8143f727a4854448fc09edeec"},{"executable":false,"path":"src/core/relay/completion.js","sha256":"c35b2090617ec2e2311089d1a5b470781045d71a5d53dc49f2ec101650e58a58"},{"executable":false,"path":"src/core/relay/control.js","sha256":"3645540f9f799b8742e0d5782b6324454a1486a780f6cb97260b96ef62411771"},{"executable":false,"path":"src/core/relay/engine.js","sha256":"650fd67bc68a2a502a7321d982eeee465032b6ebdd864a810d9bcfd98bdf6598"},{"executable":false,"path":"src/core/relay/intake.js","sha256":"b31146fe3c9edd2f09323a454687403666591b6c12483a55b07ac610d2e3610a"},{"executable":false,"path":"src/core/relay/interactions.js","sha256":"6b576ed3a5b6659bc17e384d26e40d6ccb41b118b3a91cf5c902e9758ccbc1b1"},{"executable":false,"path":"src/core/relay/managed.js","sha256":"dbe03ed964bd09739e580de73b7e9f90508062fa2e53b8244c6ca7f78fc7a60d"},{"executable":false,"path":"src/core/relay/ownership.js","sha256":"74805f04f6a8bc02b2951614c4814aa42f54aaa3abca027a2413ed5a54814caf"},{"executable":false,"path":"src/core/relay/profile.js","sha256":"3347d1d493d3470d82722468d31571464d8e11aa0b4deac5bda75f574078dfe5"},{"executable":false,"path":"src/core/relay/records.js","sha256":"5b80f7dfe7e438811d9f27c1f9038d7631f8c73266d2ec7b1108c1ce9ecbbb47"},{"executable":false,"path":"src/core/relay/routes.ts","sha256":"41a5ee29532ab961bd1e0f12e069e776a3ab2dd00fc5210b493243095a93b8eb"},{"executable":false,"path":"src/core/relay/state.js","sha256":"c18eda2f956944d0f318910de5239b954090eab81f7c77b4683e326a6d34b2b8"},{"executable":false,"path":"src/core/relay/worker.js","sha256":"4176ad91872f36f7ea6565d9f30d23d9d7a80ef27d7af975af760457132ba148"},{"executable":false,"path":"src/core/sender-prefix.js","sha256":"8c7f8f665b8f3a8739071e7a64cb248069ddcc9a01c1aedc9c64d1cd6cc14550"},{"executable":false,"path":"src/core/store.js","sha256":"caefeeebf686cecd37ef19585ef0a5d3acba9dbf1564fe128c3afe4de067305c"},{"executable":false,"path":"src/core/transcript.js","sha256":"0355f0978d2d126b90858e3f661130243fc4730ee81ba13080af1dfa39d8b081"},{"executable":false,"path":"src/core/url-policy.js","sha256":"62bf6d3c8af1f5840d5e2d682d8f2e52fcbfbee6695728b47ed31816f1736089"},{"executable":false,"path":"src/core/user-machine-guidance.js","sha256":"c8409ae9679246d8f907f1e0d16ec1c415d6697f2ce048fb64a599734486b9a6"},{"executable":false,"path":"src/gbot-install.ts","sha256":"e3c833d7662610e70e65232e541017229fb9a049eacee0bdf31e2c33c6ab7189"},{"executable":false,"path":"src/gbot.ts","sha256":"c89a37b764956ceacb2917a991a6d82d987ed8d8e453c8d553485bbd7f3edcc0"},{"executable":false,"path":"src/mcp/claude-channel.ts","sha256":"2d52e0d862a492026b6cb408e3177c994996e2b4292903da5bbf5bc191019913"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","sha256":"86334421686350ea044fb1160c19b6f5889425feb78fd608675feb8137492090"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx","sha256":"5f24cfdace92522891dfbaed0bd90e74b7de6bb8d193e0ef3bd5582c05a06914"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx","sha256":"b415d5bd303693649abae96b6b9d2920d29c797f5367ae8fbb2b62b635528e37"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx","sha256":"6adc4318f4b6c90b1d3970046266197348f79757c0d52ffe991d6338eb1fed6c"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx","sha256":"1d50db88cf7d06a74524c8937ed9045eaaf2560f6766d6c411b3bb55575d1d3f"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx","sha256":"9e1b93735b9a38216c7e9aac4c5b62bc2ac20b60e1979a19c4610f0208961af5"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx","sha256":"681e50ae6c7d3a04a76ad8eadf865ab9d793b5eb3c78f961a42d0902adacc306"},{"executable":false,"path":"src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx","sha256":"2786b62ff2a1a4e68229199935ac63c15614a0f0bdbef74b2d06e0c405516272"},{"executable":false,"path":"src/mcp/grok-bot/tools/claude_send.tsx","sha256":"c02924049f370d9cb5ae459d6275c6cae2c9f4f1328cb5fa8e2f3e6d12a6d656"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_new.tsx","sha256":"556c8d6f5f2b07b20e9daae7aa8008ee3775582a4d034415fc86fecda0c63866"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_send.tsx","sha256":"5c02dc335a0354850d05e5827f6124d0ddc08b9b654059984887c55e4cd778c9"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_threads.tsx","sha256":"c35cae75d1a46d098173cab6f1e401b51d695f40d4bc307afae9dd4a62a6bd1a"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_wait.tsx","sha256":"cb08b094860f3a09c937eb8339108015fe0de57d9f6c6886aea2028cd33ef207"},{"executable":false,"path":"src/mcp/grok-bot/tools/codex_watch.tsx","sha256":"1bc603d36ea7542468e7e3eadbb86072990282e09e209f13ebfc64389d207c49"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_bridge_start.tsx","sha256":"c75c5c8a30ec43709a4d32baa8c3bc9796595381bb04fd2499ca30cd515c5a0b"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_bridge_status.tsx","sha256":"486ce643b35cfa2eabf78f0deeabce7198adc66133669eec630e1d12206ad642"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_bridge_stop.tsx","sha256":"371428a6e4b4e1312dd95d9681c29e765aec55e65d80d7c474535df838a43457"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_codex_respond.tsx","sha256":"030e9c2081ed4ed40732b098c929022af3083f609f10934b35e1f428d33ae637"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_grok_approvals.tsx","sha256":"17f164acdc48d6bc79a4c5044c7082760dd2a1646e5b56f6bff54c53fed96451"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_grok_respond.tsx","sha256":"41964bb8cf0eb0f8493afa1dde16cd94c4f589d1a7e410577d1ed63ec4648542"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_send.tsx","sha256":"2101d279a0e6bda2d57ba3da5366411df460a95692d4e64a1096880a89121d9a"},{"executable":false,"path":"src/mcp/grok-bot/tools/gbot_thread.tsx","sha256":"ef4aefec7243efaad18335e8508c7c17af0cd9b0f8a4b3693a7af9f666807fd6"},{"executable":false,"path":"src/rules/codex-claude-on-user-machines.mdc","sha256":"a50ec93d021a807e0a18bf9311cdf103bc0ae3947e4c6a0bd78cbb941e8e5b24"},{"executable":false,"path":"src/scripts/gbot-relay.ts","sha256":"6690e316189ed8ebba43ea67a495338c927e4c0c21a9f896b7b2fecc8c6eb656"},{"executable":false,"path":"src/skills/chatgpt-desktop/SKILL.md","sha256":"0fe2560037f761203a317bf8755b0476ce864b7b1b13708559448d300aa4635c"},{"executable":false,"path":"src/skills/codex-dot/SKILL.md","sha256":"7e910c3e9e74800c09c9643983cf51cd090ff6ba448800d2702968cd89c6a005"},{"executable":false,"path":"src/skills/talk-to-grok-bot/references/bridge-administration.md","sha256":"7826da7680d2557bd6e1a1d8692e49a4b751a5c5bc90e984f1f2d6309f56c846"},{"executable":false,"path":"src/skills/talk-to-grok-bot/SKILL.md","sha256":"8343e9ca6c3e176bb423ac154054949e8c660b9fa1fc4f3d0125f490a41b6d6c"},{"executable":false,"path":"test/app-session.test.js","sha256":"0756b691703dd8c84bf0823f2afab16c6b158398e4ce6be229db6f459a0bbdb1"},{"executable":false,"path":"test/claude-channel.test.js","sha256":"c63337698001b9739414203d70b6d54d0794ec5970bd90d327923f50ab2355dc"},{"executable":false,"path":"test/codex-bridge.test.js","sha256":"59442d6cb3552c1b6c3c7a8ceab1ae35f418af1b4d71a414c91e5cf894622d1a"},{"executable":false,"path":"test/codex-commands.test.js","sha256":"d07355741037270a82f9319ef615ace388585c44cff5586868330b6811847d2c"},{"executable":false,"path":"test/codex-contract.test.js","sha256":"926c7609679d8b6ac3b568d56ba5efa20df86d016a9031f085d19adbfb0e9064"},{"executable":false,"path":"test/codex-conversation.test.js","sha256":"789d0245a8d470860f7535c6ef3849313205097f6df517ab9946e47a789f8534"},{"executable":false,"path":"test/codex-session.test.js","sha256":"b39fe6afe0784b16e37b208089279dea01095d33e06ae26a1b60871796c7738a"},{"executable":false,"path":"test/codex-surfaces.test.js","sha256":"56d1b6550cc69d462a05e892cf82aa6a41495857b753215104e03207db514c81"},{"executable":false,"path":"test/connect-gateway.test.js","sha256":"5fabd87640b39e75c218300ca6be278268f248f3ff75e8cb72f9fade9eb0f7f3"},{"executable":false,"path":"test/desktop-shim.test.js","sha256":"89fb6c38a5fca5d41a96434cf9e8d51ae1d9992cf4f7930df0cc5840ef985705"},{"executable":false,"path":"test/doctor.test.js","sha256":"9685885df9e7363d3e077d246b1a17803c8899e9613b4a4d52ee4b9275e20694"},{"executable":false,"path":"test/gateway-groups.test.js","sha256":"14e227453e3e28c7cb60f91dba55733834c023ce9a914e40e22c68c899512bdc"},{"executable":false,"path":"test/gateway-send.test.js","sha256":"d059166153dde975f457e4e8c32ea08b0fc857b58fd48eab7da1959638e4fb05"},{"executable":false,"path":"test/gateway-skills.test.js","sha256":"feed62a884d1b7d12e358a27d73fb5587bcf761d4867ab1755d8bc34a4380069"},{"executable":false,"path":"test/gateway.test.js","sha256":"e5a7acd7ae347c82ef1e2a6000562767168e56d6f9d86aca8da46141731d1309"},{"executable":false,"path":"test/grok-approvals.test.js","sha256":"5ad4c548060a08dbe57949ab5ae240383fdb1709cd3694a909f5e1354fee3f73"},{"executable":false,"path":"test/helpers/codex-server.js","sha256":"432b4570601e94cf08c4861133d328404a97066642edb7ec0dbc314411a4d848"},{"executable":false,"path":"test/history.test.js","sha256":"eac4811f1b12d427df66996f33dd46bc3cbe31fc9fa030b3f32c571d5379f8dd"},{"executable":false,"path":"test/host-tool-inventory.test.js","sha256":"fa44f15f46d0cae486c13be3fae09568f17f8581001ec50a61478bec03f4c28c"},{"executable":false,"path":"test/pr69-integration.test.js","sha256":"a5dc99c11e2d3fcf18233c595f9c28301e5939f4b3657125eb3f970df2598840"},{"executable":false,"path":"test/relay-auth-recovery.test.js","sha256":"399c064f550fe33e166187a51da527728a97946d213377c8fcc8231378f5bbab"},{"executable":false,"path":"test/relay-codex.test.js","sha256":"43cb313e748e187f798a8a0bce5a01cce9ba360a52985b05ecededee9ad10581"},{"executable":false,"path":"test/relay-completion.test.js","sha256":"a8cc2402f82ce4b458074eafd32c8fa18f7ced7d85fdb6b7fa68f7b18b6a8c2e"},{"executable":false,"path":"test/relay-engine.test.js","sha256":"7c24d0f6387d3ce5865a467d1c5b3edbd12e8e4031a4fee4908ef0be3326c866"},{"executable":false,"path":"test/relay-gateway-lifecycle.test.js","sha256":"e16e7a34f7b6bb07965003e3018aa3a43ff192602db1c177bec9b6268fddb78b"},{"executable":false,"path":"test/relay-interactions.test.js","sha256":"83d70b1a813923fc6bae02b18d328107d0d04a6a761ab73b2051e3d114c7eaa5"},{"executable":false,"path":"test/relay-lifecycle.test.js","sha256":"e90130e1f609839bfd3f74c3edc333a22f37fe20dcde0146daa8d497133da4b7"},{"executable":false,"path":"test/relay-state.test.js","sha256":"c9143d5fa150b1ebcef9d515e161e25af3370b71eaf800a7b2bb1da1678b0bd3"},{"executable":false,"path":"test/relay-surfaces.test.js","sha256":"ba17ac4f1ffc02d4e06cd73eda143422a3d4d2f750630af9ed4e828dc9d7d2be"},{"executable":false,"path":"test/relay-worker.test.js","sha256":"6bd1bdaaaae59997132f289f822b6c4b8c9616c268fb2b45861e03f697c08197"},{"executable":false,"path":"test/release-config.test.js","sha256":"f3078277086d722f21d07e4134e10b89d2e849a94a0fa40f30025a5cb6fa6a15"},{"executable":false,"path":"test/store.test.js","sha256":"5d4ae4295287539ef4b7f98d0ca0cd42a931a3c7b25b092fbd2b8f1a08ca4bac"},{"executable":false,"path":"test/test-runner.test.js","sha256":"966ff3b67edb8e1f03b50120d4d820ab0f871121e9b359609e73faae8446454f"},{"executable":false,"path":"test/transcript.test.js","sha256":"28795d9cc8e42653ac430d18e17ff1e6bc2feb1b7935fe5c69b336d58e1793ae"},{"executable":false,"path":"test/url-policy.test.js","sha256":"dacfe322e0cbff178c0d67a5f76b6bd8d9fef14aa57c09c697eb69fa0019629c"},{"executable":false,"path":"tests/fixtures/codex-global-state-remote.json","sha256":"e59377d0f03cb24d57b55558e9c91dd363619a8a92566835f1ad49b639f99525"},{"executable":false,"path":"tests/route-unit/chatgpt-desktop-e2e-regressions.test.ts","sha256":"9cfc7f538899954970fe643c13571f03d417450c519525e91d382a0b5f0b086a"},{"executable":false,"path":"tests/route-unit/chatgpt-desktop-mcp-followup.test.ts","sha256":"4a2db11a642b8daef05285f096ce026ca5b9b6394c31c0966d7e5f8c1d49f4ca"},{"executable":false,"path":"tests/route-unit/chatgpt-desktop-review.test.ts","sha256":"208dfdea18ccc408a279666a521d2f70fdce9bdaf28f86bc5d053f7ad09a7dd2"},{"executable":false,"path":"tests/route-unit/chatgpt-desktop.test.ts","sha256":"5cf61e174b1d4a7c0f2209d6746bb1880a96fe550f7d2c4ea94e849dd7f21299"},{"executable":false,"path":"tests/route-unit/tools.test.ts","sha256":"38ab1dc0146a3b6838361bb3ad5ae58f85aca9362dcd363e472e03c4ced9a312"},{"executable":false,"path":"tsconfig.json","sha256":"fa2ced6d1721e8280a6aed615717cffcef25f6e2d16e15889b2be2a9df4fc226"}]},"provenance":[{"path":".agents/plugins/marketplace.json","sourceInputs":["agent-bundle.config.ts"]},{"path":".claude-plugin/marketplace.json","sourceInputs":["agent-bundle.config.ts","package.json"]},{"path":".claude-plugin/plugin.json","sourceInputs":["agent-bundle.config.ts","src/mcp/claude-channel.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/skills/chatgpt-desktop/SKILL.md","src/skills/codex-dot/SKILL.md","src/skills/talk-to-grok-bot/SKILL.md"]},{"path":".codex-plugin/mcp.json","sourceInputs":["agent-bundle.config.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"]},{"path":".codex-plugin/plugin.json","sourceInputs":["agent-bundle.config.ts","package.json","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/skills/chatgpt-desktop/SKILL.md","src/skills/codex-dot/SKILL.md","src/skills/talk-to-grok-bot/SKILL.md"]},{"path":".cursor-plugin/marketplace.json","sourceInputs":["agent-bundle.config.ts"]},{"path":".cursor-plugin/mcp.json","sourceInputs":["agent-bundle.config.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"]},{"path":".cursor-plugin/plugin.json","sourceInputs":["agent-bundle.config.ts","package.json","src/commands/codex-send.md","src/commands/codex-threads.md","src/commands/codex-wait.md","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/rules/codex-claude-on-user-machines.mdc","src/skills/chatgpt-desktop/SKILL.md","src/skills/codex-dot/SKILL.md","src/skills/talk-to-grok-bot/SKILL.md"]},{"path":".mcp.json","sourceInputs":["agent-bundle.config.ts","src/mcp/claude-channel.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"]},{"path":"agent-bundle.compile-evidence.json","sourceInputs":["agent-bundle.config.ts"]},{"path":"bin/gbot-flight.mjs","sourceInputs":["agent-bundle.config.ts","package.json","src/cli/_shared.ts","src/cli/approvals/list.tsx","src/cli/approvals/respond.tsx","src/cli/bots/create.tsx","src/cli/bots/delete.tsx","src/cli/bots/get.tsx","src/cli/bots/list.tsx","src/cli/bots/update.tsx","src/cli/chatgpt-desktop/hosts.tsx","src/cli/chatgpt-desktop/read.tsx","src/cli/chatgpt-desktop/search.tsx","src/cli/chatgpt-desktop/send.tsx","src/cli/chatgpt-desktop/status.tsx","src/cli/chatgpt-desktop/threads.tsx","src/cli/claude/send.tsx","src/cli/codex/bridge/respond.tsx","src/cli/codex/bridge/run.tsx","src/cli/codex/bridge/start.tsx","src/cli/codex/bridge/status.tsx","src/cli/codex/bridge/stop.tsx","src/cli/codex/desktop-shim.tsx","src/cli/codex/list-threads.tsx","src/cli/codex/new.tsx","src/cli/codex/queue.tsx","src/cli/codex/send.tsx","src/cli/codex/status.tsx","src/cli/codex/wait.tsx","src/cli/codex/watch.tsx","src/cli/doctor.tsx","src/cli/groups/add.tsx","src/cli/groups/create.tsx","src/cli/groups/delete.tsx","src/cli/groups/get.tsx","src/cli/groups/list.tsx","src/cli/groups/members.tsx","src/cli/groups/remove.tsx","src/cli/groups/set.tsx","src/cli/groups/update.tsx","src/cli/history.tsx","src/cli/send.tsx","src/cli/skills/add.tsx","src/cli/skills/list.tsx","src/cli/skills/remove.tsx","src/cli/thread.tsx","src/core/app-session.js","src/core/chatgpt-desktop/app-server-fallback.ts","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/chatgpt-desktop/cdp-dom.ts","src/core/chatgpt-desktop/cdp-session.ts","src/core/chatgpt-desktop/errors.ts","src/core/chatgpt-desktop/facade.ts","src/core/chatgpt-desktop/loopback.ts","src/core/chatgpt-desktop/payload-budget.ts","src/core/chatgpt-desktop/project-state.ts","src/core/chatgpt-desktop/remote-threads.ts","src/core/chatgpt-desktop/routes.ts","src/core/chatgpt-desktop/thread-ids.ts","src/core/claude-channel.js","src/core/claude-routes.ts","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/routes.ts","src/core/codex/thread-id.js","src/core/commands.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/format.js","src/core/gateway.js","src/core/grok-approval-routes.ts","src/core/grok-approvals.js","src/core/headers.js","src/core/history.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/relay/routes.ts","src/core/sender-prefix.js","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/gbot.ts"]},{"path":"bin/gbot.mjs","sourceInputs":["agent-bundle.config.ts","package.json","src/cli/_shared.ts","src/cli/approvals/list.tsx","src/cli/approvals/respond.tsx","src/cli/bots/create.tsx","src/cli/bots/delete.tsx","src/cli/bots/get.tsx","src/cli/bots/list.tsx","src/cli/bots/update.tsx","src/cli/chatgpt-desktop/hosts.tsx","src/cli/chatgpt-desktop/read.tsx","src/cli/chatgpt-desktop/search.tsx","src/cli/chatgpt-desktop/send.tsx","src/cli/chatgpt-desktop/status.tsx","src/cli/chatgpt-desktop/threads.tsx","src/cli/claude/send.tsx","src/cli/codex/bridge/respond.tsx","src/cli/codex/bridge/run.tsx","src/cli/codex/bridge/start.tsx","src/cli/codex/bridge/status.tsx","src/cli/codex/bridge/stop.tsx","src/cli/codex/desktop-shim.tsx","src/cli/codex/list-threads.tsx","src/cli/codex/new.tsx","src/cli/codex/queue.tsx","src/cli/codex/send.tsx","src/cli/codex/status.tsx","src/cli/codex/wait.tsx","src/cli/codex/watch.tsx","src/cli/doctor.tsx","src/cli/groups/add.tsx","src/cli/groups/create.tsx","src/cli/groups/delete.tsx","src/cli/groups/get.tsx","src/cli/groups/list.tsx","src/cli/groups/members.tsx","src/cli/groups/remove.tsx","src/cli/groups/set.tsx","src/cli/groups/update.tsx","src/cli/history.tsx","src/cli/send.tsx","src/cli/skills/add.tsx","src/cli/skills/list.tsx","src/cli/skills/remove.tsx","src/cli/thread.tsx","src/core/app-session.js","src/core/chatgpt-desktop/app-server-fallback.ts","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/chatgpt-desktop/cdp-dom.ts","src/core/chatgpt-desktop/cdp-session.ts","src/core/chatgpt-desktop/errors.ts","src/core/chatgpt-desktop/facade.ts","src/core/chatgpt-desktop/loopback.ts","src/core/chatgpt-desktop/payload-budget.ts","src/core/chatgpt-desktop/project-state.ts","src/core/chatgpt-desktop/remote-threads.ts","src/core/chatgpt-desktop/routes.ts","src/core/chatgpt-desktop/thread-ids.ts","src/core/claude-channel.js","src/core/claude-routes.ts","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/routes.ts","src/core/codex/thread-id.js","src/core/commands.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/format.js","src/core/gateway.js","src/core/grok-approval-routes.ts","src/core/grok-approvals.js","src/core/headers.js","src/core/history.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/relay/routes.ts","src/core/sender-prefix.js","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/gbot.ts"]},{"path":"commands/codex-send.md","sourceInputs":["src/commands/codex-send.md"]},{"path":"commands/codex-threads.md","sourceInputs":["src/commands/codex-threads.md"]},{"path":"commands/codex-wait.md","sourceInputs":["src/commands/codex-wait.md"]},{"path":"INSTALL.md","sourceInputs":["agent-bundle.config.ts"]},{"path":"install.mjs","sourceInputs":["agent-bundle.config.ts"]},{"path":"mcp.json","sourceInputs":["src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"]},{"path":"mcp/mcp-claude-channel-8029413c.mjs","sourceInputs":["src/core/claude-channel.js","src/core/user-machine-guidance.js","src/mcp/claude-channel.ts"]},{"path":"mcp/mcp-grok-bot-b8c2461e-flight.mjs","sourceInputs":["package.json","src/core/app-session.js","src/core/chatgpt-desktop/app-server-fallback.ts","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/chatgpt-desktop/cdp-dom.ts","src/core/chatgpt-desktop/cdp-session.ts","src/core/chatgpt-desktop/errors.ts","src/core/chatgpt-desktop/facade.ts","src/core/chatgpt-desktop/loopback.ts","src/core/chatgpt-desktop/payload-budget.ts","src/core/chatgpt-desktop/project-state.ts","src/core/chatgpt-desktop/remote-threads.ts","src/core/chatgpt-desktop/routes.ts","src/core/chatgpt-desktop/thread-ids.ts","src/core/claude-channel.js","src/core/claude-routes.ts","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/routes.ts","src/core/codex/thread-id.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/format.js","src/core/gateway.js","src/core/grok-approval-routes.ts","src/core/grok-approvals.js","src/core/headers.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/relay/routes.ts","src/core/sender-prefix.js","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/gbot.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx","src/mcp/grok-bot/tools/claude_send.tsx","src/mcp/grok-bot/tools/codex_new.tsx","src/mcp/grok-bot/tools/codex_send.tsx","src/mcp/grok-bot/tools/codex_threads.tsx","src/mcp/grok-bot/tools/codex_wait.tsx","src/mcp/grok-bot/tools/codex_watch.tsx","src/mcp/grok-bot/tools/gbot_bridge_start.tsx","src/mcp/grok-bot/tools/gbot_bridge_status.tsx","src/mcp/grok-bot/tools/gbot_bridge_stop.tsx","src/mcp/grok-bot/tools/gbot_codex_respond.tsx","src/mcp/grok-bot/tools/gbot_grok_approvals.tsx","src/mcp/grok-bot/tools/gbot_grok_respond.tsx","src/mcp/grok-bot/tools/gbot_send.tsx","src/mcp/grok-bot/tools/gbot_thread.tsx"]},{"path":"mcp/mcp-grok-bot-b8c2461e.mjs","sourceInputs":["package.json","src/core/app-session.js","src/core/chatgpt-desktop/app-server-fallback.ts","src/core/chatgpt-desktop/cdp-adapter.ts","src/core/chatgpt-desktop/cdp-dom.ts","src/core/chatgpt-desktop/cdp-session.ts","src/core/chatgpt-desktop/errors.ts","src/core/chatgpt-desktop/facade.ts","src/core/chatgpt-desktop/loopback.ts","src/core/chatgpt-desktop/payload-budget.ts","src/core/chatgpt-desktop/project-state.ts","src/core/chatgpt-desktop/remote-threads.ts","src/core/chatgpt-desktop/routes.ts","src/core/chatgpt-desktop/thread-ids.ts","src/core/claude-channel.js","src/core/claude-routes.ts","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/routes.ts","src/core/codex/thread-id.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/format.js","src/core/gateway.js","src/core/grok-approval-routes.ts","src/core/grok-approvals.js","src/core/headers.js","src/core/relay/control.js","src/core/relay/managed.js","src/core/relay/profile.js","src/core/relay/routes.ts","src/core/sender-prefix.js","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/gbot.ts","src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx","src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx","src/mcp/grok-bot/tools/claude_send.tsx","src/mcp/grok-bot/tools/codex_new.tsx","src/mcp/grok-bot/tools/codex_send.tsx","src/mcp/grok-bot/tools/codex_threads.tsx","src/mcp/grok-bot/tools/codex_wait.tsx","src/mcp/grok-bot/tools/codex_watch.tsx","src/mcp/grok-bot/tools/gbot_bridge_start.tsx","src/mcp/grok-bot/tools/gbot_bridge_status.tsx","src/mcp/grok-bot/tools/gbot_bridge_stop.tsx","src/mcp/grok-bot/tools/gbot_codex_respond.tsx","src/mcp/grok-bot/tools/gbot_grok_approvals.tsx","src/mcp/grok-bot/tools/gbot_grok_respond.tsx","src/mcp/grok-bot/tools/gbot_send.tsx","src/mcp/grok-bot/tools/gbot_thread.tsx"]},{"path":"plugin.json","sourceInputs":["agent-bundle.config.ts","package.json"]},{"path":"rules/codex-claude-on-user-machines.mdc","sourceInputs":["src/rules/codex-claude-on-user-machines.mdc"]},{"path":"scripts/gbot-relay.mjs","sourceInputs":["package.json","src/core/app-session.js","src/core/codex-bridge.js","src/core/codex/contract.js","src/core/codex/conversation.js","src/core/codex/remote-control.js","src/core/codex/thread-id.js","src/core/desktop-shim-bridge.js","src/core/desktop-shim.js","src/core/gateway.js","src/core/grok-approvals.js","src/core/headers.js","src/core/relay/codex.js","src/core/relay/completion.js","src/core/relay/control.js","src/core/relay/engine.js","src/core/relay/intake.js","src/core/relay/interactions.js","src/core/relay/ownership.js","src/core/relay/profile.js","src/core/relay/records.js","src/core/relay/state.js","src/core/relay/worker.js","src/core/sender-prefix.js","src/core/store.js","src/core/transcript.js","src/core/url-policy.js","src/core/user-machine-guidance.js","src/scripts/gbot-relay.ts"]},{"path":"skills/chatgpt-desktop/SKILL.md","sourceInputs":["src/skills/chatgpt-desktop/SKILL.md"]},{"path":"skills/codex-dot/SKILL.md","sourceInputs":["src/skills/codex-dot/SKILL.md"]},{"path":"skills/talk-to-grok-bot/references/bridge-administration.md","sourceInputs":["src/skills/talk-to-grok-bot/references/bridge-administration.md","src/skills/talk-to-grok-bot/SKILL.md"]},{"path":"skills/talk-to-grok-bot/SKILL.md","sourceInputs":["src/skills/talk-to-grok-bot/SKILL.md"]}],"recordVersion":1,"validation":{"artifact":{"status":"passed"},"projections":[{"host":"claude","status":"passed"},{"host":"codex","status":"passed"},{"host":"cursor","status":"passed"},{"host":"portable","status":"passed"}],"source":{"status":"passed"}}},"distribution":{"channels":["local","npm"],"install":{"instructions":"INSTALL.md","script":"install.mjs"},"payloads":[]},"executables":{"bins":[{"hosts":["claude","codex","cursor","portable"],"name":"gbot","path":"bin/gbot.mjs","worker":"bin/gbot-flight.mjs"}],"hooks":[],"mcpServers":[{"apps":[],"hosts":["claude"],"id":"mcp:claude-channel","kind":"compiled","launch":{"args":[],"entry":"mcp/mcp-claude-channel-8029413c.mjs","env":{}},"name":"claude-channel","transport":"stdio"},{"apps":[],"hosts":["claude","codex","cursor","portable"],"id":"mcp:grok-bot","kind":"compiled","launch":{"args":[],"entry":"mcp/mcp-grok-bot-b8c2461e.mjs","env":{},"worker":"mcp/mcp-grok-bot-b8c2461e-flight.mjs"},"name":"grok-bot","transport":"stdio"}],"scripts":[{"hosts":["claude","codex","cursor","portable"],"id":"script:gbot-relay","mode":"bundle","name":"gbot-relay","path":"scripts/gbot-relay.mjs"}]},"files":[{"bytes":225,"kind":"generated","path":".agents/plugins/marketplace.json","sha256":"54d575719e003eb71ba2d7fb7379e12098243e701646e0ca83dba38ef2a78b1d"},{"bytes":926,"kind":"generated","path":".claude-plugin/marketplace.json","sha256":"2006da147ad6fc10cb0e713d6f0556cd7c6fcd5de04ac9f9a0ad5e00073cff35"},{"bytes":339,"kind":"generated","path":".claude-plugin/plugin.json","sha256":"b449e763e51308ac3c0f60000528712743181e067737e5148b461aa3a2536274"},{"bytes":156,"kind":"generated","path":".codex-plugin/mcp.json","sha256":"4b442017d0d30ec207cef7a4e5d2cd9dca246080008633459a27e3a5f2f7935b"},{"bytes":1310,"kind":"generated","path":".codex-plugin/plugin.json","sha256":"8cbecfa2707913ac72558a9852a69ac6e1a15c577cf6724bf5be8f864f11c143"},{"bytes":332,"kind":"generated","path":".cursor-plugin/marketplace.json","sha256":"297ba8aebcdb8bcac814b520bf21d9d6acc9c8c94a1ecf3ca442a49d834aab59"},{"bytes":169,"kind":"generated","path":".cursor-plugin/mcp.json","sha256":"95c87d0f2ed3a4f6df7d0e519454b1234672eca030db3b8cd8776ef0f35dee74"},{"bytes":694,"kind":"generated","path":".cursor-plugin/plugin.json","sha256":"78c77772a4f0ca0c2fa4afbfd39e401f00e860c1164d474bc54a1097bccb847d"},{"bytes":363,"kind":"generated","path":".mcp.json","sha256":"5c56ac183c3d4fcbfa9386a73ab805495c6ab613b96bf71dbd5be80093e1a10b"},{"bytes":22732,"kind":"generated","path":"agent-bundle.compile-evidence.json","sha256":"48ff156a28baf5b384a49ba721753746ed677fe5633c044c0a12881419624b2c"},{"bytes":1604986,"kind":"bundle","path":"bin/gbot-flight.mjs","sha256":"0836c81ba857d4a33727ba4c1d4a7ca9c81324ac22b198c8062751dfa5e5b14f"},{"bytes":2479650,"kind":"bundle","mode":493,"path":"bin/gbot.mjs","sha256":"7a7e23153fa84d0e1bcc2e40d7d8e213ea129c709d000268cfa7b19425389073"},{"bytes":375,"kind":"generated","path":"commands/codex-send.md","sha256":"622af5d2945c3dc9fe3035b4e35a63cd6041e0b7a9570a5f5648ba857eae9074"},{"bytes":250,"kind":"generated","path":"commands/codex-threads.md","sha256":"a763a6e1d378d012cdf6f52bd5962cf8b3a0806ef5be88472ea199d250cf6a4b"},{"bytes":267,"kind":"generated","path":"commands/codex-wait.md","sha256":"f203f7e33ad2dd59723b1117fb65a5de062a16f8b7edda1b034f02e635c96f9a"},{"bytes":22762,"kind":"generated","path":"INSTALL.md","sha256":"f9525af2bbb64d13e003ffaab376daac03f6a1167405f6726a8aff15e2696e83"},{"bytes":78590,"kind":"generated","path":"install.mjs","sha256":"248c9642984cb95b2b6c13aa005dc3a5c002a61272754ffdf98868568ef111f1"},{"bytes":246,"kind":"generated","path":"mcp.json","sha256":"c06a01fa851792f42e0cc807a444e454c3ea2fd164dc1c2adef455acc93879e2"},{"bytes":2275669,"kind":"bundle","path":"mcp/mcp-claude-channel-8029413c.mjs","sha256":"46c0e5abb42f0dcd1152ec9d6bf5fed42c3bcb109f89312bfaa9870ecc059fe3"},{"bytes":1546469,"kind":"bundle","path":"mcp/mcp-grok-bot-b8c2461e-flight.mjs","sha256":"b7ca9c0235dbde3ebddf98b4c7b024e9872b529f42b84a70370bdba8d429568d"},{"bytes":3374314,"kind":"bundle","path":"mcp/mcp-grok-bot-b8c2461e.mjs","sha256":"0195717cbb211454a6b36694d8c3e620298585cbadeece3ae73f9539b0ce52f5"},{"bytes":681,"kind":"generated","path":"plugin.json","sha256":"050f61f0459e9d78cf318bf6a6d6fc8b6c1d2dae3cab2ab3f873b49337bbe456"},{"bytes":953,"kind":"generated","path":"rules/codex-claude-on-user-machines.mdc","sha256":"a50ec93d021a807e0a18bf9311cdf103bc0ae3947e4c6a0bd78cbb941e8e5b24"},{"bytes":1314526,"kind":"bundle","path":"scripts/gbot-relay.mjs","sha256":"e9e91cfa084e23dadd45846ba74bab064e693ee68b4c76bcaef9a9091489fcb4"},{"bytes":4856,"kind":"copy","path":"skills/chatgpt-desktop/SKILL.md","sha256":"0fe2560037f761203a317bf8755b0476ce864b7b1b13708559448d300aa4635c"},{"bytes":2134,"kind":"copy","path":"skills/codex-dot/SKILL.md","sha256":"7e910c3e9e74800c09c9643983cf51cd090ff6ba448800d2702968cd89c6a005"},{"bytes":6228,"kind":"copy","path":"skills/talk-to-grok-bot/references/bridge-administration.md","sha256":"7826da7680d2557bd6e1a1d8692e49a4b751a5c5bc90e984f1f2d6309f56c846"},{"bytes":5095,"kind":"copy","path":"skills/talk-to-grok-bot/SKILL.md","sha256":"8343e9ca6c3e176bb423ac154054949e8c660b9fa1fc4f3d0125f490a41b6d6c"}],"manifestVersion":6,"projections":[{"builtInHost":"claude","documents":{"marketplace":".claude-plugin/marketplace.json","mcp":".mcp.json","plugin":".claude-plugin/plugin.json"},"host":"claude","marketplace":{"name":"gbot-marketplace"}},{"builtInHost":"codex","documents":{"marketplace":".agents/plugins/marketplace.json","mcp":".codex-plugin/mcp.json","plugin":".codex-plugin/plugin.json"},"host":"codex","marketplace":{"name":"gbot-marketplace"}},{"builtInHost":"cursor","documents":{"marketplace":".cursor-plugin/marketplace.json","mcp":".cursor-plugin/mcp.json","plugin":".cursor-plugin/plugin.json"},"host":"cursor","marketplace":{"name":"gbot-marketplace"}},{"builtInHost":"portable","documents":{"mcp":"mcp.json","plugin":"plugin.json"},"host":"portable"}],"routes":{"cli":{"commands":[{"aliases":[],"description":"List current Grok approval cards (latest 200 entries).","exitCode":"zero","options":[{"key":"target","kind":"string","option":"target","positional":0,"repeated":false,"required":true}],"path":["approvals","list"],"routeId":"cli:approvals/list"},{"aliases":[],"description":"Explicit user decision: accept a Grok request once or decline; never grant persistent permissions.","exitCode":"zero","options":[{"choices":["accept","decline"],"key":"decision","kind":"enum","option":"decision","repeated":false,"required":true},{"key":"entryId","kind":"string","option":"entry-id","repeated":false,"required":true},{"key":"requestId","kind":"string","option":"request-id","repeated":false,"required":true},{"key":"target","kind":"string","option":"target","repeated":false,"required":true}],"path":["approvals","respond"],"routeId":"cli:approvals/respond"},{"aliases":[],"description":"Create a Grok Bot bot.","exitCode":"zero","options":[{"key":"avatarColor","kind":"string","option":"avatar-color","repeated":false,"required":false},{"key":"avatarShape","kind":"string","option":"avatar-shape","repeated":false,"required":false},{"key":"description","kind":"string","option":"description","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"name","kind":"string","option":"name","repeated":false,"required":true},{"key":"title","kind":"string","option":"title","repeated":false,"required":false}],"path":["bots","create"],"routeId":"cli:bots/create"},{"aliases":[],"description":"Delete a bot or group by id or name.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Bot or group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["bots","delete"],"routeId":"cli:bots/delete"},{"aliases":[],"description":"Show one bot or group by id or name.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Bot or group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["bots","get"],"routeId":"cli:bots/get"},{"aliases":[],"description":"List Grok Bot bots (not groups).","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false}],"path":["bots","list"],"routeId":"cli:bots/list"},{"aliases":[],"description":"Update a bot or group profile.","exitCode":"zero","options":[{"key":"avatarColor","kind":"string","option":"avatar-color","repeated":false,"required":false},{"key":"avatarShape","kind":"string","option":"avatar-shape","repeated":false,"required":false},{"key":"description","kind":"string","option":"description","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"hidden","kind":"string","option":"hidden","repeated":false,"required":false},{"key":"name","kind":"string","option":"name","repeated":false,"required":false},{"key":"notify","kind":"string","option":"notify","repeated":false,"required":false},{"description":"Bot or group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true},{"key":"title","kind":"string","option":"title","repeated":false,"required":false}],"path":["bots","update"],"routeId":"cli:bots/update"},{"aliases":[],"description":"Discover ChatGPT Desktop hosts and modelProviders at runtime (never hardcode). Always includes local plus every remote-thread-summaries-v3:; Providers come from distinct thread/list and remote-summary values.","exitCode":"result","options":[{"description":"Local CDP port","key":"port","kind":"number","option":"port","repeated":false,"required":false}],"path":["chatgpt-desktop","hosts"],"routeId":"cli:chatgpt-desktop/hosts"},{"aliases":[],"description":"Read a ChatGPT Desktop thread via app-server (turns/list); CDP DOM is fallback only.","exitCode":"result","options":[{"description":"Opaque nextCursor from the prior read page","key":"cursor","kind":"string","option":"cursor","repeated":false,"required":false},{"key":"full","kind":"boolean","option":"full","repeated":false,"required":false},{"description":"Recent default 100; full default 2000","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"key":"openTimeoutMs","kind":"number","option":"open-timeout-ms","repeated":false,"required":false},{"key":"port","kind":"number","option":"port","repeated":false,"required":false},{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true}],"path":["chatgpt-desktop","read"],"routeId":"cli:chatgpt-desktop/read"},{"aliases":[],"description":"Search ChatGPT Desktop threads. --host and --model-provider accept any string (see gbot chatgpt-desktop hosts); not enums.","exitCode":"result","options":[{"description":"Opaque nextCursor from a prior search page","key":"cursor","kind":"string","option":"cursor","repeated":false,"required":false},{"choices":["host"],"description":"Group results by host (grouping mode, not a host id)","key":"groupBy","kind":"enum","option":"group-by","repeated":false,"required":false},{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","key":"host","kind":"string","option":"host","repeated":false,"required":false},{"description":"Max matches (1-200)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","key":"modelProvider","kind":"string","option":"model-provider","repeated":false,"required":false},{"description":"Local CDP port","key":"port","kind":"number","option":"port","repeated":false,"required":false},{"description":"Project label or projectId filter.","key":"project","kind":"string","option":"project","repeated":false,"required":false},{"key":"query","kind":"string","option":"query","positional":0,"repeated":false,"required":true}],"path":["chatgpt-desktop","search"],"routeId":"cli:chatgpt-desktop/search"},{"aliases":[],"description":"Send to ChatGPT Desktop via CDP composer. Omit --thread-id for a new chat; --project prefers Start new chat in .","exitCode":"result","options":[{"key":"openTimeoutMs","kind":"number","option":"open-timeout-ms","repeated":false,"required":false},{"key":"port","kind":"number","option":"port","repeated":false,"required":false},{"key":"project","kind":"string","option":"project","repeated":false,"required":false},{"key":"text","kind":"string","option":"text","positional":0,"repeated":true,"required":true},{"key":"threadId","kind":"string","option":"thread-id","repeated":false,"required":false},{"description":"Explicitly unarchive an existing archived thread before sending.","key":"unarchive","kind":"boolean","option":"unarchive","repeated":false,"required":false}],"path":["chatgpt-desktop","send"],"routeId":"cli:chatgpt-desktop/send"},{"aliases":[],"description":"Probe local ChatGPT Desktop CDP on 127.0.0.1 and report app-server availability for list/deep-read.","exitCode":"result","options":[{"description":"Local CDP port (default 9222)","key":"port","kind":"number","option":"port","repeated":false,"required":false}],"path":["chatgpt-desktop","status"],"routeId":"cli:chatgpt-desktop/status"},{"aliases":[],"description":"List local + remote-control ChatGPT Desktop threads. --host and --model-provider accept any string (see gbot chatgpt-desktop hosts); not enums.","exitCode":"result","options":[{"description":"Opaque nextCursor from a previous page","key":"cursor","kind":"string","option":"cursor","repeated":false,"required":false},{"choices":["host"],"description":"Group results by host (grouping mode, not a host id)","key":"groupBy","kind":"enum","option":"group-by","repeated":false,"required":false},{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","key":"host","kind":"string","option":"host","repeated":false,"required":false},{"description":"Max threads (1-200)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","key":"modelProvider","kind":"string","option":"model-provider","repeated":false,"required":false},{"description":"Local CDP port","key":"port","kind":"number","option":"port","repeated":false,"required":false},{"description":"Project label or projectId filter.","key":"project","kind":"string","option":"project","repeated":false,"required":false}],"path":["chatgpt-desktop","threads"],"routeId":"cli:chatgpt-desktop/threads"},{"aliases":[],"description":"Send to an explicitly enabled live Claude Code channel and wait for its reply.","exitCode":"result","options":[{"key":"message","kind":"string","option":"message","positional":1,"repeated":false,"required":true},{"key":"name","kind":"string","option":"name","positional":0,"repeated":false,"required":true},{"key":"timeoutMs","kind":"number","option":"timeout-ms","repeated":false,"required":false}],"path":["claude","send"],"routeId":"cli:claude/send"},{"aliases":[],"description":"Managed Grok/Codex bridge respond.","exitCode":"result","options":[{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","key":"answersJson","kind":"string","option":"answers-json","repeated":false,"required":false},{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"choices":["accept","decline","cancel"],"key":"decision","kind":"enum","option":"decision","repeated":false,"required":false},{"key":"exchangeId","kind":"string","option":"exchange-id","repeated":false,"required":false},{"key":"generation","kind":"string","option":"generation","repeated":false,"required":true},{"key":"interactionId","kind":"string","option":"interaction-id","repeated":false,"required":true},{"key":"threadId","kind":"string","option":"thread-id","repeated":false,"required":true},{"key":"turnId","kind":"string","option":"turn-id","repeated":false,"required":true}],"path":["codex","bridge","respond"],"routeId":"cli:codex/bridge/respond"},{"aliases":[],"description":"Run a bounded foreground relay (up to 23 hours). Use the packaged gbot-relay.mjs script for unlimited service lifetime.","exitCode":"result","options":[{"description":"Foreground lifetime in milliseconds (100..82800000; default 23h).","key":"lifetimeMs","kind":"number","option":"lifetime-ms","repeated":false,"required":false}],"path":["codex","bridge","run"],"routeId":"cli:codex/bridge/run"},{"aliases":[],"description":"Managed Grok/Codex bridge start.","exitCode":"result","options":[{"choices":["steer","reject"],"key":"busyPolicy","kind":"enum","option":"busy-policy","repeated":false,"required":false},{"key":"codexThreadId","kind":"string","option":"codex-thread-id","repeated":false,"required":false},{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"key":"grokTarget","kind":"string","option":"grok-target","positional":0,"repeated":false,"required":true},{"key":"requestId","kind":"string","option":"request-id","repeated":false,"required":false}],"path":["codex","bridge","start"],"routeId":"cli:codex/bridge/start"},{"aliases":[],"description":"Managed Grok/Codex bridge status.","exitCode":"result","options":[{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"key":"limit","kind":"number","option":"limit","repeated":false,"required":false}],"path":["codex","bridge","status"],"routeId":"cli:codex/bridge/status"},{"aliases":[],"description":"Managed Grok/Codex bridge stop.","exitCode":"result","options":[{"key":"all","kind":"boolean","option":"all","repeated":false,"required":false},{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"key":"worker","kind":"boolean","option":"worker","repeated":false,"required":false}],"path":["codex","bridge","stop"],"routeId":"cli:codex/bridge/stop"},{"aliases":[],"description":"Install, remove, or check the ChatGPT Desktop shim: a CODEX_CLI_PATH wrapper that bridges Desktop stdio onto the managed Codex daemon (stock app-server proxy hangs). macOS persists via LaunchAgent; always fails open to real Codex.","exitCode":"result","options":[{"choices":["install","uninstall","status"],"description":"install | uninstall | status","key":"action","kind":"enum","option":"action","positional":0,"repeated":false,"required":true}],"path":["codex","desktop-shim"],"routeId":"cli:codex/desktop-shim"},{"aliases":[],"description":"List Codex daemon-managed threads, newest activity first (all modelProviders; pages via --cursor / nextCursor). Find old threads with --query (name/title/id prefix, all pages), --active-within 7d, --since, --sort created.","exitCode":"result","options":[{"description":"Only threads updated within 90s, 30m, 12h, 7d, 2w","key":"activeWithin","kind":"string","option":"active-within","repeated":false,"required":false},{"description":"Archived threads only","key":"archived","kind":"boolean","option":"archived","repeated":false,"required":false},{"description":"Opaque pagination cursor from a previous nextCursor (may start with -)","key":"cursor","kind":"string","option":"cursor","repeated":false,"required":false},{"description":"Exact session cwd","key":"cwd","kind":"string","option":"cwd","repeated":false,"required":false},{"description":"Max threads to list (1-200)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"description":"Any modelProvider id; omit for all","key":"modelProvider","kind":"string","option":"model-provider","repeated":false,"required":false},{"choices":["desc","asc"],"key":"order","kind":"enum","option":"order","repeated":false,"required":false},{"description":"Case-insensitive substring of name/title, preview or id (id prefix works); scans every page","key":"query","kind":"string","option":"query","repeated":false,"required":false},{"description":"Only threads updated at/after this ISO date/time or epoch seconds","key":"since","kind":"string","option":"since","repeated":false,"required":false},{"choices":["updated","created","recency"],"description":"updated (last activity, default) | created | recency","key":"sort","kind":"enum","option":"sort","repeated":false,"required":false},{"description":"Any app-server source kind; omit for interactive sources","key":"sourceKind","kind":"string","option":"source-kind","repeated":false,"required":false}],"path":["codex","list-threads"],"routeId":"cli:codex/list-threads"},{"aliases":[],"description":"Start a new Codex thread in --cwd, optionally with --model, --effort and a message.","exitCode":"result","options":[{"key":"cwd","kind":"string","option":"cwd","repeated":false,"required":true},{"choices":["none","minimal","low","medium","high","xhigh"],"key":"effort","kind":"enum","option":"effort","repeated":false,"required":false},{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"key":"message","kind":"string","option":"message","positional":0,"repeated":true,"required":false},{"key":"model","kind":"string","option":"model","repeated":false,"required":false}],"path":["codex","new"],"routeId":"cli:codex/new"},{"aliases":[],"description":"List the experimental Codex thread queue (GROK_BOT_CODEX_EXPERIMENTAL=1).","exitCode":"result","options":[{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true}],"path":["codex","queue"],"routeId":"cli:codex/queue"},{"aliases":[],"description":"Send to Codex; acceptance is distinct from completion. Options precede threadId.","exitCode":"result","options":[{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"key":"correlationId","kind":"string","option":"correlation-id","repeated":false,"required":false},{"choices":["none","minimal","low","medium","high","xhigh"],"key":"effort","kind":"enum","option":"effort","repeated":false,"required":false},{"key":"envelope","kind":"boolean","option":"envelope","repeated":false,"required":false},{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"description":"Required active-turn guard for steer; stale guards reject.","key":"expectedTurnId","kind":"string","option":"expected-turn-id","repeated":false,"required":false},{"key":"hop","kind":"number","option":"hop","repeated":false,"required":false},{"description":"Reply budget: 1-4194304 bytes.","key":"maxOutputBytes","kind":"number","option":"max-output-bytes","repeated":false,"required":false},{"key":"message","kind":"string","option":"message","positional":1,"repeated":true,"required":true},{"key":"model","kind":"string","option":"model","repeated":false,"required":false},{"key":"replyTo","kind":"string","option":"reply-to","repeated":false,"required":false},{"key":"replyToGrok","kind":"string","option":"reply-to-grok","repeated":false,"required":false},{"key":"requestId","kind":"string","option":"request-id","repeated":false,"required":false},{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true},{"description":"Observation timeout: 1-7200000 milliseconds.","key":"timeoutMs","kind":"number","option":"timeout-ms","repeated":false,"required":false},{"key":"wait","kind":"boolean","option":"wait","repeated":false,"required":false},{"choices":["reject","queue","steer"],"key":"whenBusy","kind":"enum","option":"when-busy","repeated":false,"required":false}],"path":["codex","send"],"routeId":"cli:codex/send"},{"aliases":[],"description":"Probe the local Codex app-server daemon. Exit 0 only when it is usable.","exitCode":"result","options":[],"path":["codex","status"],"routeId":"cli:codex/status"},{"aliases":[],"description":"Bounded Codex wait observation; never interrupts execution.","exitCode":"result","options":[{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"description":"Reply budget: 1-4194304 bytes.","key":"maxOutputBytes","kind":"number","option":"max-output-bytes","repeated":false,"required":false},{"key":"messageId","kind":"string","option":"message-id","repeated":false,"required":false},{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true},{"description":"Observation timeout: 1-7200000 milliseconds.","key":"timeoutMs","kind":"number","option":"timeout-ms","repeated":false,"required":false},{"key":"turnId","kind":"string","option":"turn-id","positional":1,"repeated":false,"required":true}],"path":["codex","wait"],"routeId":"cli:codex/wait"},{"aliases":[],"description":"Bounded Codex watch observation; never interrupts execution.","exitCode":"result","options":[{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"description":"Maximum observed events: 1-500.","key":"maxEvents","kind":"number","option":"max-events","repeated":false,"required":false},{"key":"threadId","kind":"string","option":"thread-id","positional":0,"repeated":false,"required":true},{"description":"Observation timeout: 1-600000 milliseconds.","key":"timeoutMs","kind":"number","option":"timeout-ms","repeated":false,"required":false}],"path":["codex","watch"],"routeId":"cli:codex/watch"},{"aliases":[],"description":"Show which agents root and auth sources gbot can see.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false}],"path":["doctor"],"routeId":"cli:doctor"},{"aliases":[],"description":"Add a bot to a group.","exitCode":"zero","options":[{"key":"bot","kind":"string","option":"bot","positional":1,"repeated":false,"required":true},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"group","kind":"string","option":"group","positional":0,"repeated":false,"required":true}],"path":["groups","add"],"routeId":"cli:groups/add"},{"aliases":[],"description":"Create a Grok Bot group.","exitCode":"zero","options":[{"key":"avatarColor","kind":"string","option":"avatar-color","repeated":false,"required":false},{"key":"avatarShape","kind":"string","option":"avatar-shape","repeated":false,"required":false},{"key":"description","kind":"string","option":"description","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Member bot id or name (repeatable)","key":"member","kind":"string","option":"member","repeated":true,"required":true},{"key":"name","kind":"string","option":"name","repeated":false,"required":true},{"key":"title","kind":"string","option":"title","repeated":false,"required":false}],"path":["groups","create"],"routeId":"cli:groups/create"},{"aliases":[],"description":"Delete a group by id or name.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["groups","delete"],"routeId":"cli:groups/delete"},{"aliases":[],"description":"Show one group by id or name.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["groups","get"],"routeId":"cli:groups/get"},{"aliases":[],"description":"List Grok Bot groups.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false}],"path":["groups","list"],"routeId":"cli:groups/list"},{"aliases":[],"description":"Show members of a group (same payload as groups get).","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true}],"path":["groups","members"],"routeId":"cli:groups/members"},{"aliases":[],"description":"Remove a bot from a group.","exitCode":"zero","options":[{"key":"bot","kind":"string","option":"bot","positional":1,"repeated":false,"required":true},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"group","kind":"string","option":"group","positional":0,"repeated":false,"required":true}],"path":["groups","remove"],"routeId":"cli:groups/remove"},{"aliases":[],"description":"Replace a group's member list.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"group","kind":"string","option":"group","positional":0,"repeated":false,"required":true},{"description":"Member bot id or name (repeatable)","key":"member","kind":"string","option":"member","repeated":true,"required":true}],"path":["groups","set"],"routeId":"cli:groups/set"},{"aliases":[],"description":"Update a group profile (members stay on set/add/remove).","exitCode":"zero","options":[{"key":"avatarColor","kind":"string","option":"avatar-color","repeated":false,"required":false},{"key":"avatarShape","kind":"string","option":"avatar-shape","repeated":false,"required":false},{"key":"description","kind":"string","option":"description","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"key":"hidden","kind":"string","option":"hidden","repeated":false,"required":false},{"key":"name","kind":"string","option":"name","repeated":false,"required":false},{"key":"notify","kind":"string","option":"notify","repeated":false,"required":false},{"description":"Group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":true},{"key":"title","kind":"string","option":"title","repeated":false,"required":false}],"path":["groups","update"],"routeId":"cli:groups/update"},{"aliases":[],"description":"Read the opt-in local JSONL history without contacting the gateway.","exitCode":"zero","options":[{"description":"Directory containing history.jsonl","key":"historyDir","kind":"string","option":"history-dir","repeated":false,"required":false},{"description":"Maximum matching rows (1 or more)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"description":"Print the history file path","key":"path","kind":"boolean","option":"path","repeated":false,"required":false},{"description":"Bot or group id or name","key":"ref","kind":"string","option":"ref","positional":0,"repeated":false,"required":false},{"description":"Case-insensitive message text filter","key":"search","kind":"string","option":"search","repeated":false,"required":false}],"path":["history"],"routeId":"cli:history"},{"aliases":[],"description":"Send a message to a Grok Bot bot or group by name or id.","exitCode":"result","options":[{"key":"bindingId","kind":"string","option":"binding-id","repeated":false,"required":false},{"key":"codexThreadId","kind":"string","option":"codex-thread-id","repeated":false,"required":false},{"description":"Stable correlation id for multi-hop replies","key":"correlationId","kind":"string","option":"correlation-id","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Prepend the [gbot …] header","key":"envelope","kind":"boolean","option":"envelope","repeated":false,"required":false},{"key":"expectedCwd","kind":"string","option":"expected-cwd","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Directory containing history.jsonl","key":"historyDir","kind":"string","option":"history-dir","repeated":false,"required":false},{"description":"Hop count; refused at GROK_BOT_MAX_HOPS","key":"hop","kind":"number","option":"hop","repeated":false,"required":false},{"key":"message","kind":"string","option":"message","positional":1,"repeated":true,"required":true},{"description":"Skip local history for this command","key":"noHistory","kind":"boolean","option":"no-history","repeated":false,"required":false},{"choices":["auto","manual"],"key":"replyMode","kind":"enum","option":"reply-mode","repeated":false,"required":false},{"description":"Prior message id this send replies to","key":"replyTo","kind":"string","option":"reply-to","repeated":false,"required":false},{"key":"requestId","kind":"string","option":"request-id","repeated":false,"required":false},{"key":"target","kind":"string","option":"target","positional":0,"repeated":false,"required":true}],"path":["send"],"routeId":"cli:send"},{"aliases":[],"description":"Add a SKILL.md to the shared skill library. Every bot sees it.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"SKILL.md file, or a directory holding one","key":"path","kind":"string","option":"path","positional":0,"repeated":false,"required":true}],"path":["skills","add"],"routeId":"cli:skills/add"},{"aliases":[],"description":"List the skill library every bot in this Grok Bot shares.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false}],"path":["skills","list"],"routeId":"cli:skills/list"},{"aliases":[],"description":"Remove a library skill by id or name. Every bot loses it.","exitCode":"zero","options":[{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Skill id or name","key":"skill","kind":"string","option":"skill","positional":0,"repeated":false,"required":true}],"path":["skills","remove"],"routeId":"cli:skills/remove"},{"aliases":[],"description":"Read the most recent messages in a Grok Bot bot or group thread.","exitCode":"zero","options":[{"description":"Return entries after this opaque entry id","key":"after","kind":"string","option":"after","repeated":false,"required":false},{"description":"Agents directory for --files mode","key":"dir","kind":"string","option":"dir","repeated":false,"required":false},{"description":"Force the on-disk agents store","key":"files","kind":"boolean","option":"files","repeated":false,"required":false},{"description":"Show full entry text in human output","key":"full","kind":"boolean","option":"full","repeated":false,"required":false},{"description":"Force the live gateway","key":"gateway","kind":"boolean","option":"gateway","repeated":false,"required":false},{"description":"Directory containing history.jsonl","key":"historyDir","kind":"string","option":"history-dir","repeated":false,"required":false},{"description":"How many trailing entries to return (1-200)","key":"limit","kind":"number","option":"limit","repeated":false,"required":false},{"description":"Skip local history for this command","key":"noHistory","kind":"boolean","option":"no-history","repeated":false,"required":false},{"description":"Read one rooted thread by message id","key":"root","kind":"string","option":"root","repeated":false,"required":false},{"key":"target","kind":"string","option":"target","positional":0,"repeated":false,"required":true}],"path":["thread"],"routeId":"cli:thread"}],"mode":"generated","routes":[{"contract":"contract:src/cli/approvals/list.tsx#inputJsonSchema","description":"List current Grok approval cards (latest 200 entries).","id":"cli:approvals/list","inputSchema":{"additionalProperties":false,"properties":{"target":{"type":"string"}},"required":["target"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/approvals/list.tsx"},{"contract":"contract:src/cli/approvals/respond.tsx#inputJsonSchema","description":"Explicit user decision: accept a Grok request once or decline; never grant persistent permissions.","id":"cli:approvals/respond","inputSchema":{"additionalProperties":false,"properties":{"decision":{"enum":["accept","decline"],"type":"string"},"entryId":{"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","entryId","requestId","decision"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/approvals/respond.tsx"},{"contract":"contract:src/cli/bots/create.tsx#inputJsonSchema","description":"Create a Grok Bot bot.","id":"cli:bots/create","inputSchema":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"name":{"type":"string"},"title":{"type":"string"}},"required":["name"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/create.tsx"},{"contract":"contract:src/cli/bots/delete.tsx#inputJsonSchema","description":"Delete a bot or group by id or name.","id":"cli:bots/delete","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/delete.tsx"},{"contract":"contract:src/cli/bots/get.tsx#inputJsonSchema","description":"Show one bot or group by id or name.","id":"cli:bots/get","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/get.tsx"},{"contract":"contract:src/cli/bots/list.tsx#inputJsonSchema","description":"List Grok Bot bots (not groups).","id":"cli:bots/list","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/list.tsx"},{"contract":"contract:src/cli/bots/update.tsx#inputJsonSchema","description":"Update a bot or group profile.","id":"cli:bots/update","inputSchema":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"hidden":{"type":"string"},"name":{"type":"string"},"notify":{"type":"string"},"ref":{"description":"Bot or group id or name","type":"string"},"title":{"type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/bots/update.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/hosts.tsx#inputJsonSchema","description":"Discover ChatGPT Desktop hosts and modelProviders at runtime (never hardcode). Always includes local plus every remote-thread-summaries-v3:; Providers come from distinct thread/list and remote-summary values.","id":"cli:chatgpt-desktop/hosts","inputSchema":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port","type":"number"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/hosts.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/read.tsx#inputJsonSchema","description":"Read a ChatGPT Desktop thread via app-server (turns/list); CDP DOM is fallback only.","id":"cli:chatgpt-desktop/read","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior read page","type":"string"},"full":{"default":false,"type":"boolean"},"limit":{"description":"Recent default 100; full default 2000","type":"number"},"openTimeoutMs":{"default":90000,"type":"number"},"port":{"type":"number"},"threadId":{"type":"string"}},"required":["threadId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/read.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/search.tsx#inputJsonSchema","description":"Search ChatGPT Desktop threads. --host and --model-provider accept any string (see gbot chatgpt-desktop hosts); not enums.","id":"cli:chatgpt-desktop/search","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a prior search page","type":"string"},"groupBy":{"description":"Group results by host (grouping mode, not a host id)","enum":["host"],"type":"string"},"host":{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"limit":{"default":50,"description":"Max matches (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"port":{"description":"Local CDP port","type":"number"},"project":{"description":"Project label or projectId filter.","type":"string"},"query":{"type":"string"}},"required":["query"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/search.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/send.tsx#inputJsonSchema","description":"Send to ChatGPT Desktop via CDP composer. Omit --thread-id for a new chat; --project prefers Start new chat in .","id":"cli:chatgpt-desktop/send","inputSchema":{"additionalProperties":false,"properties":{"openTimeoutMs":{"type":"number"},"port":{"type":"number"},"project":{"type":"string"},"text":{"items":{"type":"string"},"type":"array"},"threadId":{"type":"string"},"unarchive":{"description":"Explicitly unarchive an existing archived thread before sending.","type":"boolean"}},"required":["text"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/send.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/status.tsx#inputJsonSchema","description":"Probe local ChatGPT Desktop CDP on 127.0.0.1 and report app-server availability for list/deep-read.","id":"cli:chatgpt-desktop/status","inputSchema":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port (default 9222)","type":"number"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/status.tsx"},{"contract":"contract:src/cli/chatgpt-desktop/threads.tsx#inputJsonSchema","description":"List local + remote-control ChatGPT Desktop threads. --host and --model-provider accept any string (see gbot chatgpt-desktop hosts); not enums.","id":"cli:chatgpt-desktop/threads","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a previous page","type":"string"},"groupBy":{"description":"Group results by host (grouping mode, not a host id)","enum":["host"],"type":"string"},"host":{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"limit":{"default":50,"description":"Max threads (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"port":{"description":"Local CDP port","type":"number"},"project":{"description":"Project label or projectId filter.","type":"string"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/chatgpt-desktop/threads.tsx"},{"contract":"contract:src/cli/claude/send.tsx#inputJsonSchema","description":"Send to an explicitly enabled live Claude Code channel and wait for its reply.","id":"cli:claude/send","inputSchema":{"additionalProperties":false,"properties":{"message":{"type":"string"},"name":{"type":"string"},"timeoutMs":{"type":"number"}},"required":["name","message"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/claude/send.tsx"},{"contract":"contract:src/cli/codex/bridge/respond.tsx#inputJsonSchema","description":"Managed Grok/Codex bridge respond.","id":"cli:codex/bridge/respond","inputSchema":{"additionalProperties":false,"properties":{"answersJson":{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","type":"string"},"bindingId":{"type":"string"},"decision":{"enum":["accept","decline","cancel"],"type":"string"},"exchangeId":{"type":"string"},"generation":{"type":"string"},"interactionId":{"type":"string"},"threadId":{"type":"string"},"turnId":{"type":"string"}},"required":["interactionId","generation","threadId","turnId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/respond.tsx"},{"contract":"contract:src/cli/codex/bridge/run.tsx#inputJsonSchema","description":"Run a bounded foreground relay (up to 23 hours). Use the packaged gbot-relay.mjs script for unlimited service lifetime.","id":"cli:codex/bridge/run","inputSchema":{"additionalProperties":false,"properties":{"lifetimeMs":{"description":"Foreground lifetime in milliseconds (100..82800000; default 23h).","type":"number"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/run.tsx"},{"contract":"contract:src/cli/codex/bridge/start.tsx#inputJsonSchema","description":"Managed Grok/Codex bridge start.","id":"cli:codex/bridge/start","inputSchema":{"additionalProperties":false,"properties":{"busyPolicy":{"enum":["steer","reject"],"type":"string"},"codexThreadId":{"type":"string"},"expectedCwd":{"type":"string"},"grokTarget":{"type":"string"},"requestId":{"type":"string"}},"required":["grokTarget"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/start.tsx"},{"contract":"contract:src/cli/codex/bridge/status.tsx#inputJsonSchema","description":"Managed Grok/Codex bridge status.","id":"cli:codex/bridge/status","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"limit":{"type":"number"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/status.tsx"},{"contract":"contract:src/cli/codex/bridge/stop.tsx#inputJsonSchema","description":"Managed Grok/Codex bridge stop.","id":"cli:codex/bridge/stop","inputSchema":{"additionalProperties":false,"properties":{"all":{"type":"boolean"},"bindingId":{"type":"string"},"worker":{"type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/bridge/stop.tsx"},{"contract":"contract:src/cli/codex/desktop-shim.tsx#inputJsonSchema","description":"Install, remove, or check the ChatGPT Desktop shim: a CODEX_CLI_PATH wrapper that bridges Desktop stdio onto the managed Codex daemon (stock app-server proxy hangs). macOS persists via LaunchAgent; always fails open to real Codex.","id":"cli:codex/desktop-shim","inputSchema":{"additionalProperties":false,"properties":{"action":{"description":"install | uninstall | status","enum":["install","uninstall","status"],"type":"string"}},"required":["action"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/desktop-shim.tsx"},{"contract":"contract:src/cli/codex/list-threads.tsx#inputJsonSchema","description":"List Codex daemon-managed threads, newest activity first (all modelProviders; pages via --cursor / nextCursor). Find old threads with --query (name/title/id prefix, all pages), --active-within 7d, --since, --sort created.","id":"cli:codex/list-threads","inputSchema":{"additionalProperties":false,"properties":{"activeWithin":{"description":"Only threads updated within 90s, 30m, 12h, 7d, 2w","type":"string"},"archived":{"description":"Archived threads only","type":"boolean"},"cursor":{"description":"Opaque pagination cursor from a previous nextCursor (may start with -)","type":"string"},"cwd":{"description":"Exact session cwd","type":"string"},"limit":{"default":20,"description":"Max threads to list (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id; omit for all","type":"string"},"order":{"default":"desc","enum":["desc","asc"],"type":"string"},"query":{"description":"Case-insensitive substring of name/title, preview or id (id prefix works); scans every page","type":"string"},"since":{"description":"Only threads updated at/after this ISO date/time or epoch seconds","type":"string"},"sort":{"default":"updated","description":"updated (last activity, default) | created | recency","enum":["updated","created","recency"],"type":"string"},"sourceKind":{"description":"Any app-server source kind; omit for interactive sources","type":"string"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/list-threads.tsx"},{"contract":"contract:src/cli/codex/new.tsx#inputJsonSchema","description":"Start a new Codex thread in --cwd, optionally with --model, --effort and a message.","id":"cli:codex/new","inputSchema":{"additionalProperties":false,"properties":{"cwd":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"expectedCwd":{"type":"string"},"message":{"items":{"type":"string"},"type":"array"},"model":{"type":"string"}},"required":["cwd"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/new.tsx"},{"contract":"contract:src/cli/codex/queue.tsx#inputJsonSchema","description":"List the experimental Codex thread queue (GROK_BOT_CODEX_EXPERIMENTAL=1).","id":"cli:codex/queue","inputSchema":{"additionalProperties":false,"properties":{"threadId":{"type":"string"}},"required":["threadId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/queue.tsx"},{"contract":"contract:src/cli/codex/send.tsx#inputJsonSchema","description":"Send to Codex; acceptance is distinct from completion. Options precede threadId.","id":"cli:codex/send","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"correlationId":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"envelope":{"type":"boolean"},"expectedCwd":{"type":"string"},"expectedTurnId":{"description":"Required active-turn guard for steer; stale guards reject.","type":"string"},"hop":{"type":"number"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"message":{"items":{"type":"string"},"type":"array"},"model":{"type":"string"},"replyTo":{"type":"string"},"replyToGrok":{"type":"string"},"requestId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"wait":{"type":"boolean"},"whenBusy":{"enum":["reject","queue","steer"],"type":"string"}},"required":["threadId","message"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/send.tsx"},{"contract":"contract:src/cli/codex/status.tsx#inputJsonSchema","description":"Probe the local Codex app-server daemon. Exit 0 only when it is usable.","id":"cli:codex/status","inputSchema":{"additionalProperties":false,"properties":{},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/status.tsx"},{"contract":"contract:src/cli/codex/wait.tsx#inputJsonSchema","description":"Bounded Codex wait observation; never interrupts execution.","id":"cli:codex/wait","inputSchema":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"messageId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"turnId":{"type":"string"}},"required":["threadId","turnId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/wait.tsx"},{"contract":"contract:src/cli/codex/watch.tsx#inputJsonSchema","description":"Bounded Codex watch observation; never interrupts execution.","id":"cli:codex/watch","inputSchema":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxEvents":{"description":"Maximum observed events: 1-500.","type":"number"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-600000 milliseconds.","type":"number"}},"required":["threadId"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/codex/watch.tsx"},{"contract":"contract:src/cli/doctor.tsx#inputJsonSchema","description":"Show which agents root and auth sources gbot can see.","id":"cli:doctor","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/doctor.tsx"},{"contract":"contract:src/cli/groups/add.tsx#inputJsonSchema","description":"Add a bot to a group.","id":"cli:groups/add","inputSchema":{"additionalProperties":false,"properties":{"bot":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"}},"required":["group","bot"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/add.tsx"},{"contract":"contract:src/cli/groups/create.tsx#inputJsonSchema","description":"Create a Grok Bot group.","id":"cli:groups/create","inputSchema":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"member":{"description":"Member bot id or name (repeatable)","items":{"type":"string"},"type":"array"},"name":{"type":"string"},"title":{"type":"string"}},"required":["name","member"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/create.tsx"},{"contract":"contract:src/cli/groups/delete.tsx#inputJsonSchema","description":"Delete a group by id or name.","id":"cli:groups/delete","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/delete.tsx"},{"contract":"contract:src/cli/groups/get.tsx#inputJsonSchema","description":"Show one group by id or name.","id":"cli:groups/get","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/get.tsx"},{"contract":"contract:src/cli/groups/list.tsx#inputJsonSchema","description":"List Grok Bot groups.","id":"cli:groups/list","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/list.tsx"},{"contract":"contract:src/cli/groups/members.tsx#inputJsonSchema","description":"Show members of a group (same payload as groups get).","id":"cli:groups/members","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/members.tsx"},{"contract":"contract:src/cli/groups/remove.tsx#inputJsonSchema","description":"Remove a bot from a group.","id":"cli:groups/remove","inputSchema":{"additionalProperties":false,"properties":{"bot":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"}},"required":["group","bot"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/remove.tsx"},{"contract":"contract:src/cli/groups/set.tsx#inputJsonSchema","description":"Replace a group's member list.","id":"cli:groups/set","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"},"member":{"description":"Member bot id or name (repeatable)","items":{"type":"string"},"type":"array"}},"required":["group","member"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/set.tsx"},{"contract":"contract:src/cli/groups/update.tsx#inputJsonSchema","description":"Update a group profile (members stay on set/add/remove).","id":"cli:groups/update","inputSchema":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"hidden":{"type":"string"},"name":{"type":"string"},"notify":{"type":"string"},"ref":{"description":"Group id or name","type":"string"},"title":{"type":"string"}},"required":["ref"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/groups/update.tsx"},{"contract":"contract:src/cli/history.tsx#inputJsonSchema","description":"Read the opt-in local JSONL history without contacting the gateway.","id":"cli:history","inputSchema":{"additionalProperties":false,"properties":{"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"limit":{"default":40,"description":"Maximum matching rows (1 or more)","type":"number"},"path":{"description":"Print the history file path","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"},"search":{"description":"Case-insensitive message text filter","type":"string"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/history.tsx"},{"contract":"contract:src/cli/send.tsx#inputJsonSchema","description":"Send a message to a Grok Bot bot or group by name or id.","id":"cli:send","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"codexThreadId":{"type":"string"},"correlationId":{"description":"Stable correlation id for multi-hop replies","type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"envelope":{"description":"Prepend the [gbot …] header","type":"boolean"},"expectedCwd":{"type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"hop":{"description":"Hop count; refused at GROK_BOT_MAX_HOPS","type":"number"},"message":{"items":{"type":"string"},"type":"array"},"noHistory":{"description":"Skip local history for this command","type":"boolean"},"replyMode":{"enum":["auto","manual"],"type":"string"},"replyTo":{"description":"Prior message id this send replies to","type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","message"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/send.tsx"},{"contract":"contract:src/cli/skills/add.tsx#inputJsonSchema","description":"Add a SKILL.md to the shared skill library. Every bot sees it.","id":"cli:skills/add","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"path":{"description":"SKILL.md file, or a directory holding one","type":"string"}},"required":["path"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/skills/add.tsx"},{"contract":"contract:src/cli/skills/list.tsx#inputJsonSchema","description":"List the skill library every bot in this Grok Bot shares.","id":"cli:skills/list","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/skills/list.tsx"},{"contract":"contract:src/cli/skills/remove.tsx#inputJsonSchema","description":"Remove a library skill by id or name. Every bot loses it.","id":"cli:skills/remove","inputSchema":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"skill":{"description":"Skill id or name","type":"string"}},"required":["skill"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/skills/remove.tsx"},{"contract":"contract:src/cli/thread.tsx#inputJsonSchema","description":"Read the most recent messages in a Grok Bot bot or group thread.","id":"cli:thread","inputSchema":{"additionalProperties":false,"properties":{"after":{"description":"Return entries after this opaque entry id","type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"full":{"description":"Show full entry text in human output","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"limit":{"default":40,"description":"How many trailing entries to return (1-200)","type":"number"},"noHistory":{"description":"Skip local history for this command","type":"boolean"},"root":{"description":"Read one rooted thread by message id","type":"string"},"target":{"type":"string"}},"required":["target"],"type":"object"},"kind":"cli","provenance":{"kind":"conventional"},"source":"src/cli/thread.tsx"}]},"contracts":[{"id":"contract:src/cli/approvals/list.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"target":{"type":"string"}},"required":["target"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/approvals/list.tsx"},"routes":["cli:approvals/list"]},{"id":"contract:src/cli/approvals/respond.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"decision":{"enum":["accept","decline"],"type":"string"},"entryId":{"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","entryId","requestId","decision"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/approvals/respond.tsx"},"routes":["cli:approvals/respond"]},{"id":"contract:src/cli/bots/create.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"name":{"type":"string"},"title":{"type":"string"}},"required":["name"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/create.tsx"},"routes":["cli:bots/create"]},{"id":"contract:src/cli/bots/delete.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/delete.tsx"},"routes":["cli:bots/delete"]},{"id":"contract:src/cli/bots/get.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/get.tsx"},"routes":["cli:bots/get"]},{"id":"contract:src/cli/bots/list.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/list.tsx"},"routes":["cli:bots/list"]},{"id":"contract:src/cli/bots/update.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"hidden":{"type":"string"},"name":{"type":"string"},"notify":{"type":"string"},"ref":{"description":"Bot or group id or name","type":"string"},"title":{"type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/bots/update.tsx"},"routes":["cli:bots/update"]},{"id":"contract:src/cli/chatgpt-desktop/hosts.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port","type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/hosts.tsx"},"routes":["cli:chatgpt-desktop/hosts"]},{"id":"contract:src/cli/chatgpt-desktop/read.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior read page","type":"string"},"full":{"default":false,"type":"boolean"},"limit":{"description":"Recent default 100; full default 2000","type":"number"},"openTimeoutMs":{"default":90000,"type":"number"},"port":{"type":"number"},"threadId":{"type":"string"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/read.tsx"},"routes":["cli:chatgpt-desktop/read"]},{"id":"contract:src/cli/chatgpt-desktop/search.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a prior search page","type":"string"},"groupBy":{"description":"Group results by host (grouping mode, not a host id)","enum":["host"],"type":"string"},"host":{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"limit":{"default":50,"description":"Max matches (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"port":{"description":"Local CDP port","type":"number"},"project":{"description":"Project label or projectId filter.","type":"string"},"query":{"type":"string"}},"required":["query"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/search.tsx"},"routes":["cli:chatgpt-desktop/search"]},{"id":"contract:src/cli/chatgpt-desktop/send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"openTimeoutMs":{"type":"number"},"port":{"type":"number"},"project":{"type":"string"},"text":{"items":{"type":"string"},"type":"array"},"threadId":{"type":"string"},"unarchive":{"description":"Explicitly unarchive an existing archived thread before sending.","type":"boolean"}},"required":["text"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/send.tsx"},"routes":["cli:chatgpt-desktop/send"]},{"id":"contract:src/cli/chatgpt-desktop/status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port (default 9222)","type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/status.tsx"},"routes":["cli:chatgpt-desktop/status"]},{"id":"contract:src/cli/chatgpt-desktop/threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from a previous page","type":"string"},"groupBy":{"description":"Group results by host (grouping mode, not a host id)","enum":["host"],"type":"string"},"host":{"description":"Any string: all (default), local, or a hostId/friendly name from `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"limit":{"default":50,"description":"Max threads (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id (app-server modelProviders pass-through). Omit = all. See `gbot chatgpt-desktop hosts`. Not an enum.","type":"string"},"port":{"description":"Local CDP port","type":"number"},"project":{"description":"Project label or projectId filter.","type":"string"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/chatgpt-desktop/threads.tsx"},"routes":["cli:chatgpt-desktop/threads"]},{"id":"contract:src/cli/claude/send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"message":{"type":"string"},"name":{"type":"string"},"timeoutMs":{"type":"number"}},"required":["name","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/claude/send.tsx"},"routes":["cli:claude/send"]},{"id":"contract:src/cli/codex/bridge/respond.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"answersJson":{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","type":"string"},"bindingId":{"type":"string"},"decision":{"enum":["accept","decline","cancel"],"type":"string"},"exchangeId":{"type":"string"},"generation":{"type":"string"},"interactionId":{"type":"string"},"threadId":{"type":"string"},"turnId":{"type":"string"}},"required":["interactionId","generation","threadId","turnId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/respond.tsx"},"routes":["cli:codex/bridge/respond"]},{"id":"contract:src/cli/codex/bridge/run.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"lifetimeMs":{"description":"Foreground lifetime in milliseconds (100..82800000; default 23h).","type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/run.tsx"},"routes":["cli:codex/bridge/run"]},{"id":"contract:src/cli/codex/bridge/start.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"busyPolicy":{"enum":["steer","reject"],"type":"string"},"codexThreadId":{"type":"string"},"expectedCwd":{"type":"string"},"grokTarget":{"type":"string"},"requestId":{"type":"string"}},"required":["grokTarget"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/start.tsx"},"routes":["cli:codex/bridge/start"]},{"id":"contract:src/cli/codex/bridge/status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"limit":{"type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/status.tsx"},"routes":["cli:codex/bridge/status"]},{"id":"contract:src/cli/codex/bridge/stop.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"all":{"type":"boolean"},"bindingId":{"type":"string"},"worker":{"type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/bridge/stop.tsx"},"routes":["cli:codex/bridge/stop"]},{"id":"contract:src/cli/codex/desktop-shim.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"action":{"description":"install | uninstall | status","enum":["install","uninstall","status"],"type":"string"}},"required":["action"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/desktop-shim.tsx"},"routes":["cli:codex/desktop-shim"]},{"id":"contract:src/cli/codex/list-threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"activeWithin":{"description":"Only threads updated within 90s, 30m, 12h, 7d, 2w","type":"string"},"archived":{"description":"Archived threads only","type":"boolean"},"cursor":{"description":"Opaque pagination cursor from a previous nextCursor (may start with -)","type":"string"},"cwd":{"description":"Exact session cwd","type":"string"},"limit":{"default":20,"description":"Max threads to list (1-200)","type":"number"},"modelProvider":{"description":"Any modelProvider id; omit for all","type":"string"},"order":{"default":"desc","enum":["desc","asc"],"type":"string"},"query":{"description":"Case-insensitive substring of name/title, preview or id (id prefix works); scans every page","type":"string"},"since":{"description":"Only threads updated at/after this ISO date/time or epoch seconds","type":"string"},"sort":{"default":"updated","description":"updated (last activity, default) | created | recency","enum":["updated","created","recency"],"type":"string"},"sourceKind":{"description":"Any app-server source kind; omit for interactive sources","type":"string"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/list-threads.tsx"},"routes":["cli:codex/list-threads"]},{"id":"contract:src/cli/codex/new.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cwd":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"expectedCwd":{"type":"string"},"message":{"items":{"type":"string"},"type":"array"},"model":{"type":"string"}},"required":["cwd"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/new.tsx"},"routes":["cli:codex/new"]},{"id":"contract:src/cli/codex/queue.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"threadId":{"type":"string"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/queue.tsx"},"routes":["cli:codex/queue"]},{"id":"contract:src/cli/codex/send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"correlationId":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"envelope":{"type":"boolean"},"expectedCwd":{"type":"string"},"expectedTurnId":{"description":"Required active-turn guard for steer; stale guards reject.","type":"string"},"hop":{"type":"number"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"message":{"items":{"type":"string"},"type":"array"},"model":{"type":"string"},"replyTo":{"type":"string"},"replyToGrok":{"type":"string"},"requestId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"wait":{"type":"boolean"},"whenBusy":{"enum":["reject","queue","steer"],"type":"string"}},"required":["threadId","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/send.tsx"},"routes":["cli:codex/send"]},{"id":"contract:src/cli/codex/status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/status.tsx"},"routes":["cli:codex/status"]},{"id":"contract:src/cli/codex/wait.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"messageId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"turnId":{"type":"string"}},"required":["threadId","turnId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/wait.tsx"},"routes":["cli:codex/wait"]},{"id":"contract:src/cli/codex/watch.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxEvents":{"description":"Maximum observed events: 1-500.","type":"number"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-600000 milliseconds.","type":"number"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/codex/watch.tsx"},"routes":["cli:codex/watch"]},{"id":"contract:src/cli/doctor.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/doctor.tsx"},"routes":["cli:doctor"]},{"id":"contract:src/cli/groups/add.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bot":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"}},"required":["group","bot"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/add.tsx"},"routes":["cli:groups/add"]},{"id":"contract:src/cli/groups/create.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"member":{"description":"Member bot id or name (repeatable)","items":{"type":"string"},"type":"array"},"name":{"type":"string"},"title":{"type":"string"}},"required":["name","member"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/create.tsx"},"routes":["cli:groups/create"]},{"id":"contract:src/cli/groups/delete.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/delete.tsx"},"routes":["cli:groups/delete"]},{"id":"contract:src/cli/groups/get.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/get.tsx"},"routes":["cli:groups/get"]},{"id":"contract:src/cli/groups/list.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/list.tsx"},"routes":["cli:groups/list"]},{"id":"contract:src/cli/groups/members.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"ref":{"description":"Group id or name","type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/members.tsx"},"routes":["cli:groups/members"]},{"id":"contract:src/cli/groups/remove.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bot":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"}},"required":["group","bot"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/remove.tsx"},"routes":["cli:groups/remove"]},{"id":"contract:src/cli/groups/set.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"group":{"type":"string"},"member":{"description":"Member bot id or name (repeatable)","items":{"type":"string"},"type":"array"}},"required":["group","member"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/set.tsx"},"routes":["cli:groups/set"]},{"id":"contract:src/cli/groups/update.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"avatarColor":{"type":"string"},"avatarShape":{"type":"string"},"description":{"type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"hidden":{"type":"string"},"name":{"type":"string"},"notify":{"type":"string"},"ref":{"description":"Group id or name","type":"string"},"title":{"type":"string"}},"required":["ref"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/groups/update.tsx"},"routes":["cli:groups/update"]},{"id":"contract:src/cli/history.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"limit":{"default":40,"description":"Maximum matching rows (1 or more)","type":"number"},"path":{"description":"Print the history file path","type":"boolean"},"ref":{"description":"Bot or group id or name","type":"string"},"search":{"description":"Case-insensitive message text filter","type":"string"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/history.tsx"},"routes":["cli:history"]},{"id":"contract:src/cli/send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"codexThreadId":{"type":"string"},"correlationId":{"description":"Stable correlation id for multi-hop replies","type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"envelope":{"description":"Prepend the [gbot …] header","type":"boolean"},"expectedCwd":{"type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"hop":{"description":"Hop count; refused at GROK_BOT_MAX_HOPS","type":"number"},"message":{"items":{"type":"string"},"type":"array"},"noHistory":{"description":"Skip local history for this command","type":"boolean"},"replyMode":{"enum":["auto","manual"],"type":"string"},"replyTo":{"description":"Prior message id this send replies to","type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/send.tsx"},"routes":["cli:send"]},{"id":"contract:src/cli/skills/add.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"path":{"description":"SKILL.md file, or a directory holding one","type":"string"}},"required":["path"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/skills/add.tsx"},"routes":["cli:skills/add"]},{"id":"contract:src/cli/skills/list.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/skills/list.tsx"},"routes":["cli:skills/list"]},{"id":"contract:src/cli/skills/remove.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"skill":{"description":"Skill id or name","type":"string"}},"required":["skill"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/skills/remove.tsx"},"routes":["cli:skills/remove"]},{"id":"contract:src/cli/thread.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"after":{"description":"Return entries after this opaque entry id","type":"string"},"dir":{"description":"Agents directory for --files mode","type":"string"},"files":{"description":"Force the on-disk agents store","type":"boolean"},"full":{"description":"Show full entry text in human output","type":"boolean"},"gateway":{"description":"Force the live gateway","type":"boolean"},"historyDir":{"description":"Directory containing history.jsonl","type":"string"},"limit":{"default":40,"description":"How many trailing entries to return (1-200)","type":"number"},"noHistory":{"description":"Skip local history for this command","type":"boolean"},"root":{"description":"Read one rooted thread by message id","type":"string"},"target":{"type":"string"}},"required":["target"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/cli/thread.tsx"},"routes":["cli:thread"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"type":"number"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_list_hosts"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior page; keep filters unchanged.","type":"string"},"groupBy":{"description":"When \"host\", also return groups[] keyed by host (grouping mode, not a host id).","enum":["host"],"type":"string"},"host":{"description":"Any string filter for machine/location. Reserved: \"all\" (default), \"local\". Otherwise a hostId or friendly name discovered at runtime — see chatgpt_desktop_list_hosts. Not an enum; new machines/connections appear with no code change.","type":"string"},"limit":{"default":50,"description":"Maximum threads per page.","type":"number"},"modelProvider":{"description":"Any modelProvider id string (passed through to app-server modelProviders). Omit for all providers. Discovered values: see chatgpt_desktop_list_hosts. Not an enum.","type":"string"},"port":{"type":"number"},"project":{"description":"Match a Desktop project label or app-server projectId. Dynamic string, not an enum.","type":"string"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_list_threads"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"openTimeoutMs":{"description":"Maximum time to wait for the requested conversation (1-600000 ms).","type":"number"},"port":{"description":"Local CDP port (default 9222 or CHATGPT_DESKTOP_CDP_PORT).","type":"number"},"threadId":{"description":"local: or bare durable id. Temporary local:client-new-thread:* works only while selected; remote ids require their owning host.","type":"string"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_open_thread"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior read page. Keep threadId and full unchanged.","type":"string"},"full":{"description":"When true, page from the start through the complete history (up to 2000 turns by default); otherwise return the most recent 100 turns by default. Explicit limit bounds either mode.","type":"boolean"},"limit":{"type":"number"},"openTimeoutMs":{"description":"Max wait for Loading task… to clear after opening (default 90000).","type":"number"},"port":{"type":"number"},"threadId":{"description":"local:, bare durable id, or selected local:client-new-thread:* temporary id. Remote ids return REMOTE_THREAD_NOT_LOADED with hostId.","type":"string"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_read_thread"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the previous search page; keep query and filters unchanged.","type":"string"},"groupBy":{"description":"When \"host\", also return groups[] keyed by host (grouping mode, not a host id).","enum":["host"],"type":"string"},"host":{"description":"Any string filter for machine/location. Reserved: \"all\" (default), \"local\". Otherwise a hostId or friendly name discovered at runtime — see chatgpt_desktop_list_hosts. Not an enum; new machines/connections appear with no code change.","type":"string"},"limit":{"default":50,"description":"Maximum matches.","type":"number"},"modelProvider":{"description":"Any modelProvider id string (passed through to app-server modelProviders). Omit for all providers. Discovered values: see chatgpt_desktop_list_hosts. Not an enum.","type":"string"},"port":{"type":"number"},"project":{"description":"Match a Desktop project label or app-server projectId.","type":"string"},"query":{"description":"Case-insensitive substring over thread metadata.","type":"string"}},"required":["query"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_search_threads"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"openTimeoutMs":{"type":"number"},"port":{"type":"number"},"project":{"description":"With threadId omitted, create the new chat inside this project. Omit for a new chat outside projects.","type":"string"},"text":{"type":"string"},"threadId":{"description":"local:, bare durable id, or selected local:client-new-thread:*; omit for a new chat.","type":"string"},"unarchive":{"default":false,"description":"Existing threadId only: explicitly call thread/unarchive after ARCHIVED_THREAD, then retry the send once. Never implicit.","type":"boolean"}},"required":["text"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_send"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port (default 9222 or CHATGPT_DESKTOP_CDP_PORT).","type":"number"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_status"]},{"id":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"port":{"type":"number"},"threadId":{"description":"Durable local:, bare id, or selected local:client-new-thread:* from send.","type":"string"},"timeoutMs":{"default":120000,"type":"number"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx"},"routes":["tool:grok-bot/chatgpt_desktop_wait_reply"]},{"id":"contract:src/mcp/grok-bot/tools/claude_send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"message":{"type":"string"},"name":{"type":"string"},"timeoutMs":{"type":"number"}},"required":["name","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/claude_send.tsx"},"routes":["tool:grok-bot/claude_send"]},{"id":"contract:src/mcp/grok-bot/tools/codex_new.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"cwd":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"expectedCwd":{"type":"string"},"message":{"type":"string"},"model":{"type":"string"}},"required":["cwd"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_new.tsx"},"routes":["tool:grok-bot/codex_new"]},{"id":"contract:src/mcp/grok-bot/tools/codex_send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"correlationId":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"envelope":{"type":"boolean"},"expectedCwd":{"type":"string"},"expectedTurnId":{"type":"string"},"hop":{"type":"number"},"maxOutputBytes":{"type":"number"},"message":{"type":"string"},"model":{"type":"string"},"replyTo":{"type":"string"},"replyToGrok":{"type":"string"},"requestId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"type":"number"},"wait":{"default":false,"type":"boolean"},"whenBusy":{"enum":["reject","queue","steer"],"type":"string"}},"required":["threadId","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_send.tsx"},"routes":["tool:grok-bot/codex_send"]},{"id":"contract:src/mcp/grok-bot/tools/codex_threads.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"activeWithin":{"description":"Only threads updated within this long: 90s, 30m, 12h, 7d, 2w.","type":"string"},"archived":{"description":"true = archived threads only.","type":"boolean"},"cursor":{"description":"Opaque nextCursor from a previous page.","type":"string"},"cwd":{"description":"Exact session working directory.","type":"string"},"limit":{"description":"Maximum threads in this page: 1-200 (default 20). Every provider is included; use cursor/nextCursor to page.","type":"number"},"modelProvider":{"description":"Any modelProvider id; omit for all.","type":"string"},"order":{"default":"desc","enum":["desc","asc"],"type":"string"},"query":{"description":"Case-insensitive substring of thread name/title, preview or id (id prefix works). Scans all pages.","type":"string"},"since":{"description":"Only threads updated at or after this ISO date/time or epoch seconds.","type":"string"},"sort":{"default":"updated","description":"updated = last activity (default), created = creation time, recency = daemon recency order.","enum":["updated","created","recency"],"type":"string"},"sourceKind":{"description":"Any app-server source kind (cli, vscode, exec, appServer, subAgent...); omit for interactive sources.","type":"string"}},"required":[],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_threads.tsx"},"routes":["tool:grok-bot/codex_threads"]},{"id":"contract:src/mcp/grok-bot/tools/codex_wait.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"messageId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"turnId":{"type":"string"}},"required":["threadId","turnId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_wait.tsx"},"routes":["tool:grok-bot/codex_wait"]},{"id":"contract:src/mcp/grok-bot/tools/codex_watch.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxEvents":{"description":"Maximum observed events: 1-500.","type":"number"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-600000 milliseconds.","type":"number"}},"required":["threadId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/codex_watch.tsx"},"routes":["tool:grok-bot/codex_watch"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_bridge_start.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"busyPolicy":{"enum":["steer","reject"],"type":"string"},"codexThreadId":{"type":"string"},"expectedCwd":{"type":"string"},"grokTarget":{"type":"string"},"requestId":{"type":"string"}},"required":["grokTarget"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_bridge_start.tsx"},"routes":["tool:grok-bot/gbot_bridge_start"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_bridge_status.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"limit":{"type":"number"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_bridge_status.tsx"},"routes":["tool:grok-bot/gbot_bridge_status"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_bridge_stop.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"all":{"type":"boolean"},"bindingId":{"type":"string"},"worker":{"type":"boolean"}},"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_bridge_stop.tsx"},"routes":["tool:grok-bot/gbot_bridge_stop"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_codex_respond.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"answersJson":{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","type":"string"},"bindingId":{"type":"string"},"decision":{"enum":["accept","decline","cancel"],"type":"string"},"exchangeId":{"type":"string"},"generation":{"type":"string"},"interactionId":{"type":"string"},"threadId":{"type":"string"},"turnId":{"type":"string"}},"required":["interactionId","generation","threadId","turnId"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_codex_respond.tsx"},"routes":["tool:grok-bot/gbot_codex_respond"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_grok_approvals.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"target":{"type":"string"}},"required":["target"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_grok_approvals.tsx"},"routes":["tool:grok-bot/gbot_grok_approvals"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_grok_respond.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"decision":{"enum":["accept","decline"],"type":"string"},"entryId":{"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","entryId","requestId","decision"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_grok_respond.tsx"},"routes":["tool:grok-bot/gbot_grok_respond"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_send.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"codexThreadId":{"type":"string"},"correlationId":{"type":"string"},"expectedCwd":{"type":"string"},"hop":{"description":"Explicit chain hop count, refused at the configured bound.","type":"number"},"message":{"type":"string"},"replyMode":{"enum":["auto","manual"],"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","message"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_send.tsx"},"routes":["tool:grok-bot/gbot_send"]},{"id":"contract:src/mcp/grok-bot/tools/gbot_thread.tsx#inputJsonSchema","input":{"additionalProperties":false,"properties":{"after":{"description":"Opaque cursor from the previous call. Returns entries strictly after it; an unknown cursor resets with a bounded snapshot.","type":"string"},"full":{"default":false,"description":"Return entries with text up to bounded budgets (20k chars per entry, 200k total). Every entry reports truncated/fullLength; read any remainder with `gbot thread --full` / `--json` on the machine.","type":"boolean"},"limit":{"default":40,"description":"How many trailing entries to inspect (1-200). Entries are returned only with full:true.","type":"number"},"target":{"description":"Bot or group name or id, for example \"General\".","type":"string"}},"required":["target"],"type":"object"},"origin":{"binding":"inputJsonSchema","module":"src/mcp/grok-bot/tools/gbot_thread.tsx"},"routes":["tool:grok-bot/gbot_thread"]}],"digest":"bc29982af3710b2b65dd33190d3d1c7f8a92e2425e9d015d74e0cf698ceca8c2","events":[],"layouts":[],"providers":[],"scripts":[{"id":"script:gbot-relay","kind":"script","provenance":{"kind":"conventional"},"source":"src/scripts/gbot-relay.ts"}],"servers":[{"id":"mcp:grok-bot","mode":"generated","name":"grok-bot","routes":[{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx#inputJsonSchema","description":"Discover local, remote-control environment ids, managed SSH hosts, and modelProvider ids. hostName is null when Desktop has no real display name. Use hostId or label in list/search filters; remote thread ids must be read on the owning host. warnings report provider discovery failures.","id":"tool:grok-bot/chatgpt_desktop_list_hosts","inputSchema":{"additionalProperties":false,"properties":{"port":{"type":"number"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_list_hosts.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx#inputJsonSchema","description":"List one sorted Desktop inventory without duplicate rows. Pass nextCursor as cursor with unchanged filters until null; pages fill limit unless the MCP byte budget binds. A changed/expired inventory cursor requires restarting. Display titles are capped at 200 characters with titleTruncated:true. Filter by dynamic hostId/hostName, modelProvider, or Desktop project label/projectId; projectRootPath identifies the resolved workspace. Rows expose local:, location, hostId, and provider; remote rows require their owning host for reading or sending. Backend and warnings identify partial sources.","id":"tool:grok-bot/chatgpt_desktop_list_threads","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior page; keep filters unchanged.","type":"string"},"groupBy":{"description":"When \"host\", also return groups[] keyed by host (grouping mode, not a host id).","enum":["host"],"type":"string"},"host":{"description":"Any string filter for machine/location. Reserved: \"all\" (default), \"local\". Otherwise a hostId or friendly name discovered at runtime — see chatgpt_desktop_list_hosts. Not an enum; new machines/connections appear with no code change.","type":"string"},"limit":{"default":50,"description":"Maximum threads per page.","type":"number"},"modelProvider":{"description":"Any modelProvider id string (passed through to app-server modelProviders). Omit for all providers. Discovered values: see chatgpt_desktop_list_hosts. Not an enum.","type":"string"},"port":{"type":"number"},"project":{"description":"Match a Desktop project label or app-server projectId. Dynamic string, not an enum.","type":"string"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_list_threads.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx#inputJsonSchema","description":"Navigate Desktop to an existing local: or bare conversation id, even when the row is absent from the sidebar. Archived routes return archived:true without unarchiving; read them with chatgpt_desktop_read_thread. A remote-control id is owned by its hostId and cannot be opened on this Mac. CDP_UNREACHABLE means Desktop must be reachable locally.","id":"tool:grok-bot/chatgpt_desktop_open_thread","inputSchema":{"additionalProperties":false,"properties":{"openTimeoutMs":{"description":"Maximum time to wait for the requested conversation (1-600000 ms).","type":"number"},"port":{"description":"Local CDP port (default 9222 or CHATGPT_DESKTOP_CDP_PORT).","type":"number"},"threadId":{"description":"local: or bare durable id. Temporary local:client-new-thread:* works only while selected; remote ids require their owning host.","type":"string"}},"required":["threadId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_open_thread.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx#inputJsonSchema","description":"Read a local:, bare durable id, or selected temporary local:client-new-thread:* id. Pass nextCursor back as cursor with the same threadId/full mode until complete:true. Pages stop at a byte budget; oversized turns use ordered continuation fragments with stable turnKey and field offsets, without dropping text. Archived threads remain readable. Warnings explain partial pages or app-server errors. REMOTE_THREAD_NOT_LOADED includes the owning hostId: call on that host.","id":"tool:grok-bot/chatgpt_desktop_read_thread","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the prior read page. Keep threadId and full unchanged.","type":"string"},"full":{"description":"When true, page from the start through the complete history (up to 2000 turns by default); otherwise return the most recent 100 turns by default. Explicit limit bounds either mode.","type":"boolean"},"limit":{"type":"number"},"openTimeoutMs":{"description":"Max wait for Loading task… to clear after opening (default 90000).","type":"number"},"port":{"type":"number"},"threadId":{"description":"local:, bare durable id, or selected local:client-new-thread:* temporary id. Remote ids return REMOTE_THREAD_NOT_LOADED with hostId.","type":"string"}},"required":["threadId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_read_thread.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx#inputJsonSchema","description":"Search full Desktop thread metadata by case-insensitive substring. Display titles are capped at 200 characters with titleTruncated:true. Pass nextCursor as cursor with unchanged query and filters to retrieve all matches. Dynamic hostId/hostName, modelProvider, and project filters apply. Remote results identify hostId and cannot be read on this Mac.","id":"tool:grok-bot/chatgpt_desktop_search_threads","inputSchema":{"additionalProperties":false,"properties":{"cursor":{"description":"Opaque nextCursor from the previous search page; keep query and filters unchanged.","type":"string"},"groupBy":{"description":"When \"host\", also return groups[] keyed by host (grouping mode, not a host id).","enum":["host"],"type":"string"},"host":{"description":"Any string filter for machine/location. Reserved: \"all\" (default), \"local\". Otherwise a hostId or friendly name discovered at runtime — see chatgpt_desktop_list_hosts. Not an enum; new machines/connections appear with no code change.","type":"string"},"limit":{"default":50,"description":"Maximum matches.","type":"number"},"modelProvider":{"description":"Any modelProvider id string (passed through to app-server modelProviders). Omit for all providers. Discovered values: see chatgpt_desktop_list_hosts. Not an enum.","type":"string"},"port":{"type":"number"},"project":{"description":"Match a Desktop project label or app-server projectId.","type":"string"},"query":{"description":"Case-insensitive substring over thread metadata.","type":"string"}},"required":["query"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_search_threads.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx#inputJsonSchema","description":"Send once through local Desktop CDP. With threadId, accept local:, bare durable id, or currently selected local:client-new-thread:*; remote ids must be sent on their hostId. Omit threadId and project for a new chat outside projects; omit threadId and set project for a new chat inside it. The empty view and project scope are checked before typing. New-thread receipts include temporaryThreadId when seen and return durable local: once resolved. ARCHIVED_THREAD rejects without sending; unarchive:true explicitly unarchives that existing thread first. PROJECT_UNAVAILABLE identifies a disabled project action or missing configured root; NEW_CHAT_NAVIGATION_FAILED reports an unchanged view promptly. CDP_UNREACHABLE and COMPOSER_HAS_DRAFT require operator inspection, not blind retry.","id":"tool:grok-bot/chatgpt_desktop_send","inputSchema":{"additionalProperties":false,"properties":{"openTimeoutMs":{"type":"number"},"port":{"type":"number"},"project":{"description":"With threadId omitted, create the new chat inside this project. Omit for a new chat outside projects.","type":"string"},"text":{"type":"string"},"threadId":{"description":"local:, bare durable id, or selected local:client-new-thread:*; omit for a new chat.","type":"string"},"unarchive":{"default":false,"description":"Existing threadId only: explicitly call thread/unarchive after ARCHIVED_THREAD, then retry the send once. Never implicit.","type":"boolean"}},"required":["text"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_send.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx#inputJsonSchema","description":"Check local ChatGPT Desktop CDP before send, wait, or open. reachable:false and exitCode:1 mean CDP is down even if appServerFallback.reachable is true; list/search/read may still work through app-server. There is no remote CDP transport.","id":"tool:grok-bot/chatgpt_desktop_status","inputSchema":{"additionalProperties":false,"properties":{"port":{"description":"Local CDP port (default 9222 or CHATGPT_DESKTOP_CDP_PORT).","type":"number"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_status.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx#inputJsonSchema","description":"After chatgpt_desktop_send, wait for the selected Desktop reply over CDP. Accept the returned durable local: or the temporary local:client-new-thread:* while selected; omit threadId only when staying on the same selected chat. Returns reply, durable threadId and conversationId. timeout is not proof the send failed; CDP_UNREACHABLE requires Desktop recovery. Remote ids must be handled on their hostId.","id":"tool:grok-bot/chatgpt_desktop_wait_reply","inputSchema":{"additionalProperties":false,"properties":{"port":{"type":"number"},"threadId":{"description":"Durable local:, bare id, or selected local:client-new-thread:* from send.","type":"string"},"timeoutMs":{"default":120000,"type":"number"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/chatgpt_desktop_wait_reply.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/claude_send.tsx#inputJsonSchema","description":"Send to a named, opted-in live Claude Code channel and wait for its reply. Unknown delivery must not be retried automatically. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.","id":"tool:grok-bot/claude_send","inputSchema":{"additionalProperties":false,"properties":{"message":{"type":"string"},"name":{"type":"string"},"timeoutMs":{"type":"number"}},"required":["name","message"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/claude_send.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_new.tsx#inputJsonSchema","description":"Start a new Codex thread on this machine in cwd, optionally sending its first message. Codex must run locally on the same machine as gbot.","id":"tool:grok-bot/codex_new","inputSchema":{"additionalProperties":false,"properties":{"cwd":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"expectedCwd":{"type":"string"},"message":{"type":"string"},"model":{"type":"string"}},"required":["cwd"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_new.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_send.tsx#inputJsonSchema","description":"Send to a Codex thread. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport. 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.","id":"tool:grok-bot/codex_send","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"correlationId":{"type":"string"},"effort":{"enum":["none","minimal","low","medium","high","xhigh"],"type":"string"},"envelope":{"type":"boolean"},"expectedCwd":{"type":"string"},"expectedTurnId":{"type":"string"},"hop":{"type":"number"},"maxOutputBytes":{"type":"number"},"message":{"type":"string"},"model":{"type":"string"},"replyTo":{"type":"string"},"replyToGrok":{"type":"string"},"requestId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"type":"number"},"wait":{"default":false,"type":"boolean"},"whenBusy":{"enum":["reject","queue","steer"],"type":"string"}},"required":["threadId","message"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_send.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_threads.tsx#inputJsonSchema","description":"Discover Codex daemon threads on the user's registered machine (local socket, not the Grok Bot box; from the box run gbot there through Shell with a machineId after codex app-server daemon start or bootstrap). Newest activity first by default (sort:\"updated\"), so old-but-active threads surface; sort:\"created\" restores creation order. Find one thread with query (case-insensitive substring of name/title, preview or id, so an id prefix works) - it scans every page, not just the first 100. Narrow with activeWithin (\"30m\", \"12h\", \"7d\", \"2w\") or since (ISO/epoch seconds), cwd, modelProvider, sourceKind, archived. limit is the page size (1-200); pass nextCursor back as cursor for more.","id":"tool:grok-bot/codex_threads","inputSchema":{"additionalProperties":false,"properties":{"activeWithin":{"description":"Only threads updated within this long: 90s, 30m, 12h, 7d, 2w.","type":"string"},"archived":{"description":"true = archived threads only.","type":"boolean"},"cursor":{"description":"Opaque nextCursor from a previous page.","type":"string"},"cwd":{"description":"Exact session working directory.","type":"string"},"limit":{"description":"Maximum threads in this page: 1-200 (default 20). Every provider is included; use cursor/nextCursor to page.","type":"number"},"modelProvider":{"description":"Any modelProvider id; omit for all.","type":"string"},"order":{"default":"desc","enum":["desc","asc"],"type":"string"},"query":{"description":"Case-insensitive substring of thread name/title, preview or id (id prefix works). Scans all pages.","type":"string"},"since":{"description":"Only threads updated at or after this ISO date/time or epoch seconds.","type":"string"},"sort":{"default":"updated","description":"updated = last activity (default), created = creation time, recency = daemon recency order.","enum":["updated","created","recency"],"type":"string"},"sourceKind":{"description":"Any app-server source kind (cli, vscode, exec, appServer, subAgent...); omit for interactive sources.","type":"string"}},"required":[],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_threads.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_wait.tsx#inputJsonSchema","description":"Explicit diagnostic observation of one Codex turn; returns execution and final reply without interrupting it. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.","id":"tool:grok-bot/codex_wait","inputSchema":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxOutputBytes":{"description":"Reply budget: 1-4194304 bytes.","type":"number"},"messageId":{"type":"string"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-7200000 milliseconds.","type":"number"},"turnId":{"type":"string"}},"required":["threadId","turnId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_wait.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/codex_watch.tsx#inputJsonSchema","description":"Watch bounded Codex thread events for diagnostics without answering approvals. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.","id":"tool:grok-bot/codex_watch","inputSchema":{"additionalProperties":false,"properties":{"expectedCwd":{"type":"string"},"maxEvents":{"description":"Maximum observed events: 1-500.","type":"number"},"threadId":{"type":"string"},"timeoutMs":{"description":"Observation timeout: 1-600000 milliseconds.","type":"number"}},"required":["threadId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/codex_watch.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_bridge_start.tsx#inputJsonSchema","description":"Link a Grok conversation to Codex once. New visible Grok messages arrive automatically and Codex final answers return to Grok.","id":"tool:grok-bot/gbot_bridge_start","inputSchema":{"additionalProperties":false,"properties":{"busyPolicy":{"enum":["steer","reject"],"type":"string"},"codexThreadId":{"type":"string"},"expectedCwd":{"type":"string"},"grokTarget":{"type":"string"},"requestId":{"type":"string"}},"required":["grokTarget"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_bridge_start.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_bridge_status.tsx#inputJsonSchema","description":"Inspect worker health, route coverage, bounded receipts and scoped pending operator interactions.","id":"tool:grok-bot/gbot_bridge_status","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"limit":{"type":"number"}},"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_bridge_status.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_bridge_stop.tsx#inputJsonSchema","description":"Stop a binding without deleting receipts or interrupting Codex. all stops all bindings; worker explicitly shuts down the worker.","id":"tool:grok-bot/gbot_bridge_stop","inputSchema":{"additionalProperties":false,"properties":{"all":{"type":"boolean"},"bindingId":{"type":"string"},"worker":{"type":"boolean"}},"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_bridge_stop.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_codex_respond.tsx#inputJsonSchema","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.","id":"tool:grok-bot/gbot_codex_respond","inputSchema":{"additionalProperties":false,"properties":{"answersJson":{"description":"JSON object mapping each advertised question ID to {\"answers\":[\"answer\"]}; exact IDs required.","type":"string"},"bindingId":{"type":"string"},"decision":{"enum":["accept","decline","cancel"],"type":"string"},"exchangeId":{"type":"string"},"generation":{"type":"string"},"interactionId":{"type":"string"},"threadId":{"type":"string"},"turnId":{"type":"string"}},"required":["interactionId","generation","threadId","turnId"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_codex_respond.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_grok_approvals.tsx#inputJsonSchema","description":"List pending auto-review and local-tool approval cards in the latest 200 entries for a Grok bot. Older or unsupported requests require the owning Grok UI.","id":"tool:grok-bot/gbot_grok_approvals","inputSchema":{"additionalProperties":false,"properties":{"target":{"type":"string"}},"required":["target"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_grok_approvals.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_grok_respond.tsx#inputJsonSchema","description":"Only after an explicit user decision: accept one current Grok approval once or decline it. Exact target, entryId and approval requestId required. Never auto-approve or grant persistent permissions. Success acknowledges response delivery, not execution.","id":"tool:grok-bot/gbot_grok_respond","inputSchema":{"additionalProperties":false,"properties":{"decision":{"enum":["accept","decline"],"type":"string"},"entryId":{"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","entryId","requestId","decision"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_grok_respond.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_send.tsx#inputJsonSchema","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.","id":"tool:grok-bot/gbot_send","inputSchema":{"additionalProperties":false,"properties":{"bindingId":{"type":"string"},"codexThreadId":{"type":"string"},"correlationId":{"type":"string"},"expectedCwd":{"type":"string"},"hop":{"description":"Explicit chain hop count, refused at the configured bound.","type":"number"},"message":{"type":"string"},"replyMode":{"enum":["auto","manual"],"type":"string"},"requestId":{"type":"string"},"target":{"type":"string"}},"required":["target","message"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_send.tsx"},{"contract":"contract:src/mcp/grok-bot/tools/gbot_thread.tsx#inputJsonSchema","description":"Read a bounded Grok Bot thread tail. Returns a small receipt by default; pass the last cursor as after for an exclusive client-side delta, or full:true to include bounded entry text.","id":"tool:grok-bot/gbot_thread","inputSchema":{"additionalProperties":false,"properties":{"after":{"description":"Opaque cursor from the previous call. Returns entries strictly after it; an unknown cursor resets with a bounded snapshot.","type":"string"},"full":{"default":false,"description":"Return entries with text up to bounded budgets (20k chars per entry, 200k total). Every entry reports truncated/fullLength; read any remainder with `gbot thread --full` / `--json` on the machine.","type":"boolean"},"limit":{"default":40,"description":"How many trailing entries to inspect (1-200). Entries are returned only with full:true.","type":"number"},"target":{"description":"Bot or group name or id, for example \"General\".","type":"string"}},"required":["target"],"type":"object"},"kind":"tool","provenance":{"kind":"conventional"},"serverId":"mcp:grok-bot","source":"src/mcp/grok-bot/tools/gbot_thread.tsx"}]}]},"runtime":{"node":"22.19.0"}} diff --git a/artifact/bin/gbot-flight.mjs b/artifact/bin/gbot-flight.mjs index 37d1acc..565f5fd 100644 --- a/artifact/bin/gbot-flight.mjs +++ b/artifact/bin/gbot-flight.mjs @@ -9529,14 +9529,15 @@ var __webpack_modules__ = { "./src/cli/codex/list-threads.tsx" (__unused_rspack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.react-server.js"); - var _agent_bundle_runtime__rspack_import_5 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js"); - var zod__rspack_import_4 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); + var _agent_bundle_runtime__rspack_import_6 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js"); + var zod__rspack_import_5 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); var _core_codex_bridge_js__rspack_import_1 = __webpack_require__("./src/core/codex-bridge.js"); var _core_codex_contract_js__rspack_import_2 = __webpack_require__("./src/core/codex/contract.js"); - var _core_format_js__rspack_import_6 = __webpack_require__("./src/core/format.js"); + var _core_format_js__rspack_import_7 = __webpack_require__("./src/core/format.js"); var _shared_js__rspack_import_3 = __webpack_require__("./src/cli/_shared.ts"); + var _core_codex_routes_js__rspack_import_4 = __webpack_require__("./src/core/codex/routes.ts"); const config = { - description: 'List Codex daemon-managed threads (all modelProviders; pages via --cursor / nextCursor).', + description: 'List Codex daemon-managed threads, newest activity first (all modelProviders; pages via --cursor / nextCursor). Find old threads with --query (name/title/id prefix, all pages), --active-within 7d, --since, --sort created.', exitCode: 'result', inputJsonSchema: { additionalProperties: false, @@ -9549,49 +9550,100 @@ var __webpack_modules__ = { default: 20, description: 'Max threads to list (1-200)', type: 'number' + }, + sort: { + default: 'updated', + description: 'updated (last activity, default) | created | recency', + enum: [ + 'updated', + 'created', + 'recency' + ], + type: 'string' + }, + order: { + default: 'desc', + enum: [ + 'desc', + 'asc' + ], + type: 'string' + }, + query: { + description: 'Case-insensitive substring of name/title, preview or id (id prefix works); scans every page', + type: 'string' + }, + activeWithin: { + description: 'Only threads updated within 90s, 30m, 12h, 7d, 2w', + type: 'string' + }, + since: { + description: 'Only threads updated at/after this ISO date/time or epoch seconds', + type: 'string' + }, + cwd: { + description: 'Exact session cwd', + type: 'string' + }, + modelProvider: { + description: 'Any modelProvider id; omit for all', + type: 'string' + }, + sourceKind: { + description: 'Any app-server source kind; omit for interactive sources', + type: 'string' + }, + archived: { + description: 'Archived threads only', + type: 'boolean' } }, type: 'object' } }; - const inputSchema = zod__rspack_import_4.Ikc({ - cursor: zod__rspack_import_4.YjP().min(1).optional(), - limit: zod__rspack_import_4.aig().int().min(1).max(200).default(20) - }).strict(); - const resultSchema = zod__rspack_import_4.KCZ([ - zod__rspack_import_4.Ikc({ - exitCode: zod__rspack_import_4.euz(0), - limit: zod__rspack_import_4.aig().int().min(1).max(200), - nextCursor: zod__rspack_import_4.YjP().nullable(), - threads: zod__rspack_import_4.YOg(zod__rspack_import_4.g1P(zod__rspack_import_4.YjP(), zod__rspack_import_4.Pq9())), - useStateDbOnly: zod__rspack_import_4.zMY().optional() + const inputSchema = _core_codex_routes_js__rspack_import_4.P3; + const resultSchema = zod__rspack_import_5.KCZ([ + zod__rspack_import_5.Ikc({ + exitCode: zod__rspack_import_5.euz(0), + limit: zod__rspack_import_5.aig().int().min(1).max(200), + sort: zod__rspack_import_5.YjP().optional(), + order: zod__rspack_import_5.YjP().optional(), + scanned: zod__rspack_import_5.aig().int().min(0).optional(), + nextCursor: zod__rspack_import_5.YjP().nullable(), + threads: zod__rspack_import_5.YOg(zod__rspack_import_5.g1P(zod__rspack_import_5.YjP(), zod__rspack_import_5.Pq9())), + useStateDbOnly: zod__rspack_import_5.zMY().optional() }).strict(), _shared_js__rspack_import_3.R9 ]); async function codexListThreads({ input }) { let out; try { + const { sourceKind, ...rest } = input; out = await (0, _core_codex_bridge_js__rspack_import_1.X$)({ - cursor: input.cursor, - limit: input.limit + ...rest, + ...sourceKind ? { + sourceKinds: [ + sourceKind + ] + } : {} }); } catch (error) { const failure = (0, _core_codex_contract_js__rspack_import_2.DG)(error); - return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_5.g.Result, { + return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6.g.Result, { value: failure, - children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_5.g.Text, { + children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6.g.Text, { children: failure.error }) }); } const more = out.nextCursor ? `\n\nmore: --cursor ${JSON.stringify((0, _core_codex_bridge_js__rspack_import_1.pF)(out.nextCursor))}` : ''; - const text = out.threads.length === 0 ? 'No Codex threads.' : out.threads.map(_core_format_js__rspack_import_6.nz).join('\n\n') + more; - return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_5.g.Result, { + const text = out.threads.length === 0 ? 'No Codex threads.' : out.threads.map(_core_format_js__rspack_import_7.nz).join('\n\n') + more; + return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6.g.Result, { value: { ...out, exitCode: 0 }, - children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_5.g.Text, { + children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6.g.Text, { children: text }) }); @@ -10874,14 +10926,15 @@ var __webpack_modules__ = { "./src/cli/send.tsx" (__unused_rspack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.react-server.js"); - var _agent_bundle_runtime__rspack_import_7 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js"); - var _agent_bundle_runtime__rspack_import_8 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js"); - var zod__rspack_import_6 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); + var _agent_bundle_runtime__rspack_import_8 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js"); + var _agent_bundle_runtime__rspack_import_9 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js"); + var zod__rspack_import_7 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); var _core_relay_routes_js__rspack_import_1 = __webpack_require__("./src/core/relay/routes.ts"); var _core_codex_bridge_js__rspack_import_2 = __webpack_require__("./src/core/codex-bridge.js"); - var _core_codex_contract_js__rspack_import_3 = __webpack_require__("./src/core/codex/contract.js"); - var _core_history_js__rspack_import_4 = __webpack_require__("./src/core/history.js"); - var _shared_js__rspack_import_5 = __webpack_require__("./src/cli/_shared.ts"); + var _core_sender_prefix_js__rspack_import_3 = __webpack_require__("./src/core/sender-prefix.js"); + var _core_codex_contract_js__rspack_import_4 = __webpack_require__("./src/core/codex/contract.js"); + var _core_history_js__rspack_import_5 = __webpack_require__("./src/core/history.js"); + var _shared_js__rspack_import_6 = __webpack_require__("./src/cli/_shared.ts"); const config = { description: 'Send a message to a Grok Bot bot or group by name or id.', exitCode: 'result', @@ -10964,44 +11017,44 @@ var __webpack_modules__ = { 'message' ] }; - const inputSchema = _shared_js__rspack_import_5.lK.extend({ + const inputSchema = _shared_js__rspack_import_6.lK.extend({ ..._core_relay_routes_js__rspack_import_1.zK, - replyMode: zod__rspack_import_6.k5n([ + replyMode: zod__rspack_import_7.k5n([ 'auto', 'manual' ]).optional(), - correlationId: zod__rspack_import_6.YjP().min(1).optional(), - envelope: zod__rspack_import_6.zMY().default(false), - historyDir: zod__rspack_import_6.YjP().min(1).optional(), - hop: zod__rspack_import_6.aig().int().min(0).optional(), - message: zod__rspack_import_6.YOg(zod__rspack_import_6.YjP()).min(1), - noHistory: zod__rspack_import_6.zMY().default(false), - replyTo: zod__rspack_import_6.YjP().min(1).optional(), - target: zod__rspack_import_6.YjP().min(1) + correlationId: zod__rspack_import_7.YjP().min(1).optional(), + envelope: zod__rspack_import_7.zMY().default(false), + historyDir: zod__rspack_import_7.YjP().min(1).optional(), + hop: zod__rspack_import_7.aig().int().min(0).optional(), + message: zod__rspack_import_7.YOg(zod__rspack_import_7.YjP()).min(1), + noHistory: zod__rspack_import_7.zMY().default(false), + replyTo: zod__rspack_import_7.YjP().min(1).optional(), + target: zod__rspack_import_7.YjP().min(1) }).strict(); - const receiptSchema = zod__rspack_import_6.Ikc({ - correlationId: zod__rspack_import_6.YjP(), - delivery: zod__rspack_import_6.k5n([ + const receiptSchema = zod__rspack_import_7.Ikc({ + correlationId: zod__rspack_import_7.YjP(), + delivery: zod__rspack_import_7.k5n([ 'accepted', 'unknown' ]), - envelopeId: zod__rspack_import_6.YjP(), - exitCode: zod__rspack_import_6.euz(0), - hop: zod__rspack_import_6.aig().int().min(0), - id: zod__rspack_import_6.YjP(), - kind: zod__rspack_import_6.k5n([ + envelopeId: zod__rspack_import_7.YjP(), + exitCode: zod__rspack_import_7.euz(0), + hop: zod__rspack_import_7.aig().int().min(0), + id: zod__rspack_import_7.YjP(), + kind: zod__rspack_import_7.k5n([ 'bot', 'group' ]), - maxHops: zod__rspack_import_6.aig().int().min(0), - messageId: zod__rspack_import_6.YjP().optional(), - name: zod__rspack_import_6.YjP(), - replyTo: zod__rspack_import_6.YjP().optional(), - result: zod__rspack_import_6.g1P(zod__rspack_import_6.YjP(), zod__rspack_import_6.Pq9()) + maxHops: zod__rspack_import_7.aig().int().min(0), + messageId: zod__rspack_import_7.YjP().optional(), + name: zod__rspack_import_7.YjP(), + replyTo: zod__rspack_import_7.YjP().optional(), + result: zod__rspack_import_7.g1P(zod__rspack_import_7.YjP(), zod__rspack_import_7.Pq9()) }).strict(); - const resultSchema = zod__rspack_import_6.KCZ([ + const resultSchema = zod__rspack_import_7.KCZ([ receiptSchema, - _shared_js__rspack_import_5.R9, + _shared_js__rspack_import_6.R9, _core_relay_routes_js__rspack_import_1.Ax ]); const deliver = async (input)=>{ @@ -11012,9 +11065,12 @@ var __webpack_modules__ = { replyTo: input.replyTo }); const message = input.message.join(' ').trim(); - const backend = await (0, _shared_js__rspack_import_5.FS)(input); - const out = await backend.send(input.target, (0, _core_codex_bridge_js__rspack_import_2.Mr)(message, envelope)); - (0, _core_history_js__rspack_import_4.QX)(out, { + const backend = await (0, _shared_js__rspack_import_6.FS)(input); + const out = await backend.send(input.target, (0, _core_sender_prefix_js__rspack_import_3.Xt)((0, _core_codex_bridge_js__rspack_import_2.Mr)(message, envelope), { + threadId: (0, _core_sender_prefix_js__rspack_import_3.Wh)(), + cwd: input.expectedCwd ?? process.cwd() + })); + (0, _core_history_js__rspack_import_5.QX)(out, { dir: input.historyDir, disabled: input.noHistory, event: 'send', @@ -11055,25 +11111,25 @@ var __webpack_modules__ = { requestId: input.requestId, hop: input.hop, correlationId: input.correlationId - }, await (0, _agent_bundle_runtime__rspack_import_7.MA)()); - return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_8.g.Result, { + }, await (0, _agent_bundle_runtime__rspack_import_8.MA)()); + return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_9.g.Result, { value: { ...out, exitCode: out.delivery === 'rejected' ? 1 : 0 }, - children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_8.g.Text, { + children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_9.g.Text, { children: `Delivery ${out.delivery}; inspect codex bridge status for automatic reply delivery.` }) }); } value = await deliver(input); } catch (error) { - value = (0, _core_codex_contract_js__rspack_import_3.DG)(error); + value = (0, _core_codex_contract_js__rspack_import_4.DG)(error); } const text = value.exitCode === 0 ? `Sent to ${value.kind} ${value.name} (${value.id})${value.messageId ? ` message ${value.messageId}` : ''}; envelope ${value.envelopeId}` : value.error; - return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_8.g.Result, { + return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_9.g.Result, { value: value, - children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_8.g.Text, { + children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_9.g.Text, { children: text }) }); @@ -15266,6 +15322,7 @@ var __webpack_modules__ = { var _codex_bridge_js__rspack_import_0 = __webpack_require__("./src/core/codex-bridge.js"); var _contract_js__rspack_import_1 = __webpack_require__("./src/core/codex/contract.js"); var _conversation_js__rspack_import_2 = __webpack_require__("./src/core/codex/conversation.js"); + var _format_js__rspack_import_6 = __webpack_require__("./src/core/format.js"); var _thread_id_js__rspack_import_4 = __webpack_require__("./src/core/codex/thread-id.js"); const bareId = zod__rspack_import_3.YjP().regex(/^[A-Za-z0-9_.:-]{1,128}$/); const id = zod__rspack_import_3.YjP().min(1).max(160).transform((value, ctx)=>{ @@ -15326,7 +15383,23 @@ var __webpack_modules__ = { }).strict(); const threadsSchema = zod__rspack_import_3.Ikc({ limit: zod__rspack_import_3.aig().int().min(1).max(200).default(20), - cursor: zod__rspack_import_3.YjP().min(1).max(4096).optional() + cursor: zod__rspack_import_3.YjP().min(1).max(4096).optional(), + sort: zod__rspack_import_3.k5n([ + 'updated', + 'created', + 'recency' + ]).default('updated'), + order: zod__rspack_import_3.k5n([ + 'desc', + 'asc' + ]).default('desc'), + query: zod__rspack_import_3.YjP().trim().min(1).max(256).optional(), + activeWithin: zod__rspack_import_3.YjP().trim().regex(/^\d+(?:\.\d+)?\s*[smhdw]$/i, 'use a duration like 30m, 12h, 7d or 2w').optional(), + since: zod__rspack_import_3.YjP().trim().min(1).max(64).optional(), + cwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), + modelProvider: zod__rspack_import_3.YjP().min(1).max(256).optional(), + archived: zod__rspack_import_3.zMY().optional(), + sourceKind: zod__rspack_import_3.YjP().min(1).max(64).optional() }).strict(); const resultSchema = zod__rspack_import_3.Ikc({ exitCode: zod__rspack_import_3.aig().int().min(0).max(1), @@ -15486,8 +15559,16 @@ var __webpack_modules__ = { } async function threadsOperation(input) { try { + const { sourceKind, ...rest } = input; return { - ...await listCodexThreads(input), + ...await listCodexThreads({ + ...rest, + ...sourceKind ? { + sourceKinds: [ + sourceKind + ] + } : {} + }), exitCode: 0 }; } catch (error) { @@ -15501,7 +15582,10 @@ var __webpack_modules__ = { if (result.delivery === 'accepted') return `Started turn ${result.turnId} (${result.turnStatus}) on Codex thread ${result.threadId}; message ${result.messageId}`; if (result.delivery) return `Codex delivery ${result.delivery} on thread ${result.threadId}`; if (result.reason) return `Codex observation: ${result.reason}`; - if (Array.isArray(result.threads)) return `${result.threads.length} Codex threads`; + if (Array.isArray(result.threads)) { + const rows = result.threads.map((t)=>(0, _format_js__rspack_import_6.nz)(t)).join('\n\n'); + return `${result.threads.length} Codex threads (sort ${String(result.sort ?? 'updated')} ${String(result.order ?? 'desc')})${result.nextCursor ? `; more: pass cursor ${JSON.stringify(result.nextCursor)}` : ''}${rows ? `\n\n${rows}` : ''}`; + } return String(result.error ?? 'Codex observation complete'); } __webpack_require__.d(__webpack_exports__, { @@ -15510,6 +15594,7 @@ var __webpack_modules__ = { gT: ()=>observeOperation }, { FD: resultSchema, + P3: threadsSchema, R9: watchSchema, at: sendFields, jS: waitSchema @@ -15539,68 +15624,69 @@ var __webpack_modules__ = { }); }, "./src/core/relay/routes.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) { - var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/40.js"); - var zod__rspack_import_3 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); + var _agent_bundle_runtime__rspack_import_5 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/40.js"); + var zod__rspack_import_4 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); var _managed_js__rspack_import_0 = __webpack_require__("./src/core/relay/managed.js"); var _gbot_js__rspack_import_1 = __webpack_require__("./src/gbot.ts"); var _codex_bridge_js__rspack_import_2 = __webpack_require__("./src/core/codex-bridge.js"); - const id = zod__rspack_import_3.YjP().min(1).max(128); + var _sender_prefix_js__rspack_import_3 = __webpack_require__("./src/core/sender-prefix.js"); + const id = zod__rspack_import_4.YjP().min(1).max(128); const routeFields = { codexThreadId: id.optional(), - expectedCwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), + expectedCwd: zod__rspack_import_4.YjP().min(1).max(4096).optional(), + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), requestId: id.optional() }; - const grokSendSchema = zod__rspack_import_3.Ikc({ - target: zod__rspack_import_3.YjP().min(1), - message: zod__rspack_import_3.YjP().min(1), - replyMode: zod__rspack_import_3.k5n([ + const grokSendSchema = zod__rspack_import_4.Ikc({ + target: zod__rspack_import_4.YjP().min(1), + message: zod__rspack_import_4.YjP().min(1), + replyMode: zod__rspack_import_4.k5n([ "auto", "manual" ]).optional(), - hop: zod__rspack_import_3.aig().int().min(0).optional(), + hop: zod__rspack_import_4.aig().int().min(0).optional(), correlationId: id.optional(), ...routeFields }).strict(); - const bridgeStartSchema = zod__rspack_import_3.Ikc({ - grokTarget: zod__rspack_import_3.YjP().min(1), + const bridgeStartSchema = zod__rspack_import_4.Ikc({ + grokTarget: zod__rspack_import_4.YjP().min(1), codexThreadId: id.optional(), - expectedCwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), - busyPolicy: zod__rspack_import_3.k5n([ + expectedCwd: zod__rspack_import_4.YjP().min(1).max(4096).optional(), + busyPolicy: zod__rspack_import_4.k5n([ "steer", "reject" ]).optional(), requestId: id.optional() }).strict(); - const bridgeStatusSchema = zod__rspack_import_3.Ikc({ - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - limit: zod__rspack_import_3.aig().int().min(1).max(100).optional() + const bridgeStatusSchema = zod__rspack_import_4.Ikc({ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + limit: zod__rspack_import_4.aig().int().min(1).max(100).optional() }).strict(); - const bridgeStopSchema = zod__rspack_import_3.Ikc({ - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - all: zod__rspack_import_3.zMY().optional(), - worker: zod__rspack_import_3.zMY().optional() + const bridgeStopSchema = zod__rspack_import_4.Ikc({ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + all: zod__rspack_import_4.zMY().optional(), + worker: zod__rspack_import_4.zMY().optional() }).strict().refine((x)=>!!x.bindingId || x.all === true || x.worker === true, "Specify bindingId, all or worker"); - const respondSchema = zod__rspack_import_3.Ikc({ - interactionId: zod__rspack_import_3.YjP().min(1).max(512), + const respondSchema = zod__rspack_import_4.Ikc({ + interactionId: zod__rspack_import_4.YjP().min(1).max(512), generation: id, threadId: id, turnId: id, - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - exchangeId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - decision: zod__rspack_import_3.k5n([ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + exchangeId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + decision: zod__rspack_import_4.k5n([ "accept", "decline", "cancel" ]).optional(), - answersJson: zod__rspack_import_3.YjP().min(2).max(65536).optional() + answersJson: zod__rspack_import_4.YjP().min(2).max(65536).optional() }).strict().refine((x)=>!!x.bindingId || !!x.exchangeId, "Binding or exchange scope required").refine((x)=>!!x.decision !== !!x.answersJson, "Supply decision or answersJson"); - const answersSchema = zod__rspack_import_3.g1P(zod__rspack_import_3.YjP().min(1).max(128), zod__rspack_import_3.Ikc({ - answers: zod__rspack_import_3.YOg(zod__rspack_import_3.YjP().max(8192)).max(20) + const answersSchema = zod__rspack_import_4.g1P(zod__rspack_import_4.YjP().min(1).max(128), zod__rspack_import_4.Ikc({ + answers: zod__rspack_import_4.YOg(zod__rspack_import_4.YjP().max(8192)).max(20) }).strict()); - const relayResultSchema = zod__rspack_import_3.g1P(zod__rspack_import_3.YjP(), zod__rspack_import_3.Pq9()); + const relayResultSchema = zod__rspack_import_4.g1P(zod__rspack_import_4.YjP(), zod__rspack_import_4.Pq9()); function nativeCodexThread(context) { - return context.host.state === "available" && (0, _agent_bundle_runtime__rspack_import_4.bg)(context.host.value.name) === "codex" && context.lineage.state === "available" && context.lineage.source === "native" && context.lineage.value.resolution === "native" ? context.lineage.value.conversation : undefined; + return context.host.state === "available" && (0, _agent_bundle_runtime__rspack_import_5.bg)(context.host.value.name) === "codex" && context.lineage.state === "available" && context.lineage.source === "native" && context.lineage.value.resolution === "native" ? context.lineage.value.conversation : undefined; } function options(context) { return { @@ -15633,7 +15719,11 @@ var __webpack_modules__ = { } : {} }, options(context))); if (input.replyMode === "auto") throw Error("Automatic reply delivery requires a native Codex source, codexThreadId or bindingId"); - const message = input.hop !== undefined || input.correlationId !== undefined ? (0, _codex_bridge_js__rspack_import_2.Mr)(input.message, (0, _codex_bridge_js__rspack_import_2.nq)(input)) : input.message; + const stamped = input.hop !== undefined || input.correlationId !== undefined ? (0, _codex_bridge_js__rspack_import_2.Mr)(input.message, (0, _codex_bridge_js__rspack_import_2.nq)(input)) : input.message; + const message = (0, _sender_prefix_js__rspack_import_3.Xt)(stamped, { + threadId: route.codexThreadId, + cwd: route.expectedCwd + }); const sent = await (0, _gbot_js__rspack_import_1.yF)(async ()=>(0, _gbot_js__rspack_import_1.LV)(await (0, _gbot_js__rspack_import_1.Vq)(), input.target, message)); return { result: sent.result, @@ -27048,7 +27138,52 @@ var __webpack_modules__ = { }; } const THREAD_LIST_MAX_LIMIT = 200; - async function listCodexThreads1({ limit = 20, cursor, modelProviders = [], env = process.env } = {}) { + const THREAD_SORT_KEYS = { + updated: "updated_at", + created: "created_at", + recency: "recency_at" + }; + const GBOT_CURSOR = "gbot1:"; + const DURATION_MS = { + s: 1000, + m: 60000, + h: 3600000, + d: 86400000, + w: 604800000 + }; + const toSeconds = (value)=>value > 1e11 ? value / 1000 : value; + function parseActiveWithin(text) { + const m = /^(\d+(?:\.\d+)?)\s*([smhdw])$/i.exec(String(text).trim()); + if (!m) throw new RangeError("--active-within must look like 30m, 12h, 7d or 2w"); + return Number(m[1]) * DURATION_MS[m[2].toLowerCase()]; + } + function parseSince(value) { + const text = String(value).trim(); + const n = /^\d+(?:\.\d+)?$/.test(text) ? toSeconds(Number(text)) : Date.parse(text) / 1000; + if (!Number.isFinite(n)) throw new RangeError("--since must be an ISO date/time or epoch seconds"); + return n; + } + function encodeThreadCursor(state) { + return GBOT_CURSOR + Buffer.from(JSON.stringify(state)).toString("base64url"); + } + function decodeThreadCursor(cursor) { + if (cursor === undefined) return { + skip: 0 + }; + if (!cursor.startsWith(GBOT_CURSOR)) return { + c: cursor, + skip: 0 + }; + try { + const v = JSON.parse(Buffer.from(cursor.slice(GBOT_CURSOR.length), "base64url").toString("utf8")); + if (isObject(v) && Number.isInteger(v.skip) && v.skip >= 0 && (v.c === undefined || typeof v.c === "string")) return { + c: v.c, + skip: v.skip + }; + } catch {} + throw new RangeError("--cursor is not a valid thread cursor"); + } + async function listCodexThreads1({ limit = 20, cursor, modelProviders = [], modelProvider, sort = "updated", order = "desc", query, since, activeWithin, cwd, archived, sourceKinds, now = Date.now(), env = process.env } = {}) { if (!Number.isInteger(limit) || limit < 1 || limit > THREAD_LIST_MAX_LIMIT) { throw new RangeError("--limit must be an integer 1-" + THREAD_LIST_MAX_LIMIT); } @@ -27056,45 +27191,125 @@ var __webpack_modules__ = { if (!Array.isArray(modelProviders) || modelProviders.some((p)=>typeof p !== "string")) { throw new RangeError("modelProviders must be an array of strings (empty = all providers)"); } + if (!Object.hasOwn(THREAD_SORT_KEYS, sort)) throw new RangeError("--sort must be one of: " + Object.keys(THREAD_SORT_KEYS).join(", ")); + if (order !== "asc" && order !== "desc") throw new RangeError("--order must be asc or desc"); + if (query !== undefined && (typeof query !== "string" || !query.trim())) throw new RangeError("--query must be a non-empty string"); + if (sourceKinds !== undefined && (!Array.isArray(sourceKinds) || sourceKinds.some((k)=>typeof k !== "string" || !k))) { + throw new RangeError("--source-kind must be a non-empty string"); + } + const providers = modelProvider ? [ + ...modelProviders, + modelProvider + ] : modelProviders; + const needle = query?.trim().toLowerCase(); + const cutoffs = []; + if (since !== undefined) cutoffs.push(parseSince(since)); + if (activeWithin !== undefined) cutoffs.push((now - parseActiveWithin(activeWithin)) / 1000); + const cutoff = cutoffs.length ? Math.max(...cutoffs) : undefined; + const clientSide = needle !== undefined || cutoff !== undefined; + const activityOf = (t)=>typeof t.updatedAt === "number" ? toSeconds(t.updatedAt) : typeof t.createdAt === "number" ? toSeconds(t.createdAt) : null; + const keep = (t)=>{ + if (cutoff !== undefined) { + const at = activityOf(t); + if (at === null || at < cutoff) return false; + } + if (needle !== undefined && ![ + t.name, + t.preview, + t.id + ].some((f)=>typeof f === "string" && f.toLowerCase().includes(needle))) return false; + return true; + }; + const pageSize = clientSide ? THREAD_LIST_MAX_LIMIT : limit; + const start = decodeThreadCursor(cursor); const { client } = await openSession(env); try { const baseParams = { - limit, - modelProviders, - ...cursor !== undefined ? { - cursor + limit: pageSize, + modelProviders: providers, + sortKey: THREAD_SORT_KEYS[sort], + ...order === "asc" ? { + sortDirection: "asc" + } : {}, + ...cwd ? { + cwd + } : {}, + ...archived === true ? { + archived: true + } : {}, + ...sourceKinds?.length ? { + sourceKinds } : {} }; - let out; - let usedStateDbOnly = true; - try { - out = await client.request("thread/list", { - ...baseParams, - useStateDbOnly: true - }); - } catch (err) { - throw transportError(err); - } - if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); - if (out.data.length === 0 && cursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + const fetchPage = async (pageCursor, useStateDbOnly)=>{ try { - out = await client.request("thread/list", { + return await client.request("thread/list", { ...baseParams, - useStateDbOnly: false + ...pageCursor !== undefined ? { + cursor: pageCursor + } : {}, + useStateDbOnly }); - usedStateDbOnly = false; } catch (err) { throw transportError(err); } + }; + const checkPage = (out)=>{ if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); + if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); + }; + const threads = []; + let usedStateDbOnly = true; + let scanned = 0; + let nextCursor = null; + let pageCursor = start.c; + let skip = start.skip; + for(;;){ + let out = await fetchPage(pageCursor, true); + checkPage(out); + if (out.data.length === 0 && pageCursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + out = await fetchPage(pageCursor, false); + usedStateDbOnly = false; + checkPage(out); + } + const rows = out.data.map(summarizeThread); + scanned += rows.length; + let matches = rows.filter(keep); + const pageSkip = skip; + if (skip) { + matches = matches.slice(skip); + skip = 0; + } + const need = limit - threads.length; + if (matches.length > need) { + threads.push(...matches.slice(0, need)); + nextCursor = encodeThreadCursor({ + ...pageCursor !== undefined ? { + c: pageCursor + } : {}, + skip: pageSkip + need + }); + break; + } + threads.push(...matches); + const more = out.nextCursor || null; + const last = rows[rows.length - 1]; + const pastCutoff = cutoff !== undefined && sort === "updated" && order === "desc" && last !== undefined && (activityOf(last) ?? -Infinity) < cutoff; + if (!more || pastCutoff) break; + if (threads.length >= limit) { + nextCursor = more; + break; + } + pageCursor = more; } - if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); - const threads = out.data.map(summarizeThread); return { threads, - nextCursor: out.nextCursor ?? null, + nextCursor, limit, - useStateDbOnly: usedStateDbOnly + useStateDbOnly: usedStateDbOnly, + sort, + order, + scanned }; } finally{ client.close(); @@ -29094,7 +29309,8 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } function formatCodexThread(t) { const title = t.name ? " - " + stripTerminalControls(t.name) : ""; const preview = t.preview ? "\n " + stripTerminalControls(String(t.preview).replace(/\s+/g, " ")).slice(0, 200) : ""; - return stripTerminalControls(t.id) + " " + stripTerminalControls(t.status) + title + "\n " + stripTerminalControls(t.cwd ?? "") + preview; + const at = typeof t.updatedAt === "number" && Number.isFinite(t.updatedAt) ? new Date(t.updatedAt > 1e11 ? t.updatedAt : t.updatedAt * 1000).toISOString().replace(/\.\d{3}Z$/, "Z") : ""; + return stripTerminalControls(t.id) + " " + stripTerminalControls(t.status) + title + "\n " + stripTerminalControls(t.cwd ?? "") + (at ? " (updated " + at + ")" : "") + preview; } function shellQuote(value) { return "'" + String(value).replace(/'/g, "'\\''") + "'"; @@ -30176,6 +30392,42 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } br: digest }); }, + "./src/core/sender-prefix.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { + var node_os__rspack_import_0 = __webpack_require__("node:os"); + const oneLine = (value)=>String(value ?? "").replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/[\]]/g, ")").trim(); + function machineName(env = process.env) { + try { + return oneLine(env.GROK_BOT_MACHINE_NAME || (0, node_os__rspack_import_0.hostname)()); + } catch { + return ""; + } + } + function codexSenderPrefix({ threadId, machine, cwd, details = [], env = process.env } = {}) { + const id = oneLine(threadId); + if (!id) return ""; + const where = oneLine(machine ?? machineName(env)); + const dir = oneLine(cwd); + const head = "from Codex thread " + id + (where ? " @ " + where : "") + (dir ? (where ? ", " : " ") + "cwd " + dir : ""); + const reply = "reply: codex_send({threadId:\"" + id + "\", message:\"...\"})" + (where ? " via MCP on " + where : " via MCP") + " (or CLI: gbot codex send " + id + " \"...\")"; + return "[" + [ + head, + ...details.map(oneLine).filter(Boolean), + reply + ].join("; ") + "]"; + } + function withCodexSender(text, fields) { + const prefix = codexSenderPrefix(fields); + return prefix ? prefix + "\n" + text : text; + } + function envCodexThreadId(env = process.env) { + const id = env.CODEX_THREAD_ID?.trim(); + return id && /^[A-Za-z0-9_.:-]{1,128}$/.test(id) ? id : undefined; + } + __webpack_require__.d(__webpack_exports__, { + Wh: ()=>envCodexThreadId, + Xt: ()=>withCodexSender + }); + }, "./src/core/store.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { var node_crypto__rspack_import_0 = __webpack_require__("node:crypto"); var node_fs__rspack_import_1 = __webpack_require__("node:fs"); diff --git a/artifact/bin/gbot.mjs b/artifact/bin/gbot.mjs index 23d2efb..347cc00 100755 --- a/artifact/bin/gbot.mjs +++ b/artifact/bin/gbot.mjs @@ -7937,14 +7937,15 @@ var __webpack_modules__ = { "./src/cli/codex/list-threads.tsx" (__unused_rspack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js"); - var _agent_bundle_runtime__rspack_import_5 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js"); - var zod__rspack_import_4 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); + var _agent_bundle_runtime__rspack_import_6 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js"); + var zod__rspack_import_5 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); var _core_codex_bridge_js__rspack_import_1 = __webpack_require__("./src/core/codex-bridge.js"); var _core_codex_contract_js__rspack_import_2 = __webpack_require__("./src/core/codex/contract.js"); - var _core_format_js__rspack_import_6 = __webpack_require__("./src/core/format.js"); + var _core_format_js__rspack_import_7 = __webpack_require__("./src/core/format.js"); var _shared_js__rspack_import_3 = __webpack_require__("./src/cli/_shared.ts"); + var _core_codex_routes_js__rspack_import_4 = __webpack_require__("./src/core/codex/routes.ts"); const config = { - description: 'List Codex daemon-managed threads (all modelProviders; pages via --cursor / nextCursor).', + description: 'List Codex daemon-managed threads, newest activity first (all modelProviders; pages via --cursor / nextCursor). Find old threads with --query (name/title/id prefix, all pages), --active-within 7d, --since, --sort created.', exitCode: 'result', inputJsonSchema: { additionalProperties: false, @@ -7957,49 +7958,100 @@ var __webpack_modules__ = { default: 20, description: 'Max threads to list (1-200)', type: 'number' + }, + sort: { + default: 'updated', + description: 'updated (last activity, default) | created | recency', + enum: [ + 'updated', + 'created', + 'recency' + ], + type: 'string' + }, + order: { + default: 'desc', + enum: [ + 'desc', + 'asc' + ], + type: 'string' + }, + query: { + description: 'Case-insensitive substring of name/title, preview or id (id prefix works); scans every page', + type: 'string' + }, + activeWithin: { + description: 'Only threads updated within 90s, 30m, 12h, 7d, 2w', + type: 'string' + }, + since: { + description: 'Only threads updated at/after this ISO date/time or epoch seconds', + type: 'string' + }, + cwd: { + description: 'Exact session cwd', + type: 'string' + }, + modelProvider: { + description: 'Any modelProvider id; omit for all', + type: 'string' + }, + sourceKind: { + description: 'Any app-server source kind; omit for interactive sources', + type: 'string' + }, + archived: { + description: 'Archived threads only', + type: 'boolean' } }, type: 'object' } }; - const inputSchema = zod__rspack_import_4.Ikc({ - cursor: zod__rspack_import_4.YjP().min(1).optional(), - limit: zod__rspack_import_4.aig().int().min(1).max(200).default(20) - }).strict(); - const resultSchema = zod__rspack_import_4.KCZ([ - zod__rspack_import_4.Ikc({ - exitCode: zod__rspack_import_4.euz(0), - limit: zod__rspack_import_4.aig().int().min(1).max(200), - nextCursor: zod__rspack_import_4.YjP().nullable(), - threads: zod__rspack_import_4.YOg(zod__rspack_import_4.g1P(zod__rspack_import_4.YjP(), zod__rspack_import_4.Pq9())), - useStateDbOnly: zod__rspack_import_4.zMY().optional() + const inputSchema = _core_codex_routes_js__rspack_import_4.P3; + const resultSchema = zod__rspack_import_5.KCZ([ + zod__rspack_import_5.Ikc({ + exitCode: zod__rspack_import_5.euz(0), + limit: zod__rspack_import_5.aig().int().min(1).max(200), + sort: zod__rspack_import_5.YjP().optional(), + order: zod__rspack_import_5.YjP().optional(), + scanned: zod__rspack_import_5.aig().int().min(0).optional(), + nextCursor: zod__rspack_import_5.YjP().nullable(), + threads: zod__rspack_import_5.YOg(zod__rspack_import_5.g1P(zod__rspack_import_5.YjP(), zod__rspack_import_5.Pq9())), + useStateDbOnly: zod__rspack_import_5.zMY().optional() }).strict(), _shared_js__rspack_import_3.R9 ]); async function codexListThreads({ input }) { let out; try { + const { sourceKind, ...rest } = input; out = await (0, _core_codex_bridge_js__rspack_import_1.X$)({ - cursor: input.cursor, - limit: input.limit + ...rest, + ...sourceKind ? { + sourceKinds: [ + sourceKind + ] + } : {} }); } catch (error) { const failure = (0, _core_codex_contract_js__rspack_import_2.DG)(error); - return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_5.g.Result, { + return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6.g.Result, { value: failure, - children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_5.g.Text, { + children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6.g.Text, { children: failure.error }) }); } const more = out.nextCursor ? `\n\nmore: --cursor ${JSON.stringify((0, _core_codex_bridge_js__rspack_import_1.pF)(out.nextCursor))}` : ''; - const text = out.threads.length === 0 ? 'No Codex threads.' : out.threads.map(_core_format_js__rspack_import_6.nz).join('\n\n') + more; - return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_5.g.Result, { + const text = out.threads.length === 0 ? 'No Codex threads.' : out.threads.map(_core_format_js__rspack_import_7.nz).join('\n\n') + more; + return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6.g.Result, { value: { ...out, exitCode: 0 }, - children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_5.g.Text, { + children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_6.g.Text, { children: text }) }); @@ -9282,14 +9334,15 @@ var __webpack_modules__ = { "./src/cli/send.tsx" (__unused_rspack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); var react_jsx_runtime__rspack_import_0 = __webpack_require__("./node_modules/react/jsx-runtime.js"); - var _agent_bundle_runtime__rspack_import_7 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js"); - var _agent_bundle_runtime__rspack_import_8 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js"); - var zod__rspack_import_6 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); + var _agent_bundle_runtime__rspack_import_8 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/736.js"); + var _agent_bundle_runtime__rspack_import_9 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/506.js"); + var zod__rspack_import_7 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); var _core_relay_routes_js__rspack_import_1 = __webpack_require__("./src/core/relay/routes.ts"); var _core_codex_bridge_js__rspack_import_2 = __webpack_require__("./src/core/codex-bridge.js"); - var _core_codex_contract_js__rspack_import_3 = __webpack_require__("./src/core/codex/contract.js"); - var _core_history_js__rspack_import_4 = __webpack_require__("./src/core/history.js"); - var _shared_js__rspack_import_5 = __webpack_require__("./src/cli/_shared.ts"); + var _core_sender_prefix_js__rspack_import_3 = __webpack_require__("./src/core/sender-prefix.js"); + var _core_codex_contract_js__rspack_import_4 = __webpack_require__("./src/core/codex/contract.js"); + var _core_history_js__rspack_import_5 = __webpack_require__("./src/core/history.js"); + var _shared_js__rspack_import_6 = __webpack_require__("./src/cli/_shared.ts"); const config = { description: 'Send a message to a Grok Bot bot or group by name or id.', exitCode: 'result', @@ -9372,44 +9425,44 @@ var __webpack_modules__ = { 'message' ] }; - const inputSchema = _shared_js__rspack_import_5.lK.extend({ + const inputSchema = _shared_js__rspack_import_6.lK.extend({ ..._core_relay_routes_js__rspack_import_1.zK, - replyMode: zod__rspack_import_6.k5n([ + replyMode: zod__rspack_import_7.k5n([ 'auto', 'manual' ]).optional(), - correlationId: zod__rspack_import_6.YjP().min(1).optional(), - envelope: zod__rspack_import_6.zMY().default(false), - historyDir: zod__rspack_import_6.YjP().min(1).optional(), - hop: zod__rspack_import_6.aig().int().min(0).optional(), - message: zod__rspack_import_6.YOg(zod__rspack_import_6.YjP()).min(1), - noHistory: zod__rspack_import_6.zMY().default(false), - replyTo: zod__rspack_import_6.YjP().min(1).optional(), - target: zod__rspack_import_6.YjP().min(1) + correlationId: zod__rspack_import_7.YjP().min(1).optional(), + envelope: zod__rspack_import_7.zMY().default(false), + historyDir: zod__rspack_import_7.YjP().min(1).optional(), + hop: zod__rspack_import_7.aig().int().min(0).optional(), + message: zod__rspack_import_7.YOg(zod__rspack_import_7.YjP()).min(1), + noHistory: zod__rspack_import_7.zMY().default(false), + replyTo: zod__rspack_import_7.YjP().min(1).optional(), + target: zod__rspack_import_7.YjP().min(1) }).strict(); - const receiptSchema = zod__rspack_import_6.Ikc({ - correlationId: zod__rspack_import_6.YjP(), - delivery: zod__rspack_import_6.k5n([ + const receiptSchema = zod__rspack_import_7.Ikc({ + correlationId: zod__rspack_import_7.YjP(), + delivery: zod__rspack_import_7.k5n([ 'accepted', 'unknown' ]), - envelopeId: zod__rspack_import_6.YjP(), - exitCode: zod__rspack_import_6.euz(0), - hop: zod__rspack_import_6.aig().int().min(0), - id: zod__rspack_import_6.YjP(), - kind: zod__rspack_import_6.k5n([ + envelopeId: zod__rspack_import_7.YjP(), + exitCode: zod__rspack_import_7.euz(0), + hop: zod__rspack_import_7.aig().int().min(0), + id: zod__rspack_import_7.YjP(), + kind: zod__rspack_import_7.k5n([ 'bot', 'group' ]), - maxHops: zod__rspack_import_6.aig().int().min(0), - messageId: zod__rspack_import_6.YjP().optional(), - name: zod__rspack_import_6.YjP(), - replyTo: zod__rspack_import_6.YjP().optional(), - result: zod__rspack_import_6.g1P(zod__rspack_import_6.YjP(), zod__rspack_import_6.Pq9()) + maxHops: zod__rspack_import_7.aig().int().min(0), + messageId: zod__rspack_import_7.YjP().optional(), + name: zod__rspack_import_7.YjP(), + replyTo: zod__rspack_import_7.YjP().optional(), + result: zod__rspack_import_7.g1P(zod__rspack_import_7.YjP(), zod__rspack_import_7.Pq9()) }).strict(); - const resultSchema = zod__rspack_import_6.KCZ([ + const resultSchema = zod__rspack_import_7.KCZ([ receiptSchema, - _shared_js__rspack_import_5.R9, + _shared_js__rspack_import_6.R9, _core_relay_routes_js__rspack_import_1.Ax ]); const deliver = async (input)=>{ @@ -9420,9 +9473,12 @@ var __webpack_modules__ = { replyTo: input.replyTo }); const message = input.message.join(' ').trim(); - const backend = await (0, _shared_js__rspack_import_5.FS)(input); - const out = await backend.send(input.target, (0, _core_codex_bridge_js__rspack_import_2.Mr)(message, envelope)); - (0, _core_history_js__rspack_import_4.QX)(out, { + const backend = await (0, _shared_js__rspack_import_6.FS)(input); + const out = await backend.send(input.target, (0, _core_sender_prefix_js__rspack_import_3.Xt)((0, _core_codex_bridge_js__rspack_import_2.Mr)(message, envelope), { + threadId: (0, _core_sender_prefix_js__rspack_import_3.Wh)(), + cwd: input.expectedCwd ?? process.cwd() + })); + (0, _core_history_js__rspack_import_5.QX)(out, { dir: input.historyDir, disabled: input.noHistory, event: 'send', @@ -9463,25 +9519,25 @@ var __webpack_modules__ = { requestId: input.requestId, hop: input.hop, correlationId: input.correlationId - }, await (0, _agent_bundle_runtime__rspack_import_7.MA)()); - return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_8.g.Result, { + }, await (0, _agent_bundle_runtime__rspack_import_8.MA)()); + return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_9.g.Result, { value: { ...out, exitCode: out.delivery === 'rejected' ? 1 : 0 }, - children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_8.g.Text, { + children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_9.g.Text, { children: `Delivery ${out.delivery}; inspect codex bridge status for automatic reply delivery.` }) }); } value = await deliver(input); } catch (error) { - value = (0, _core_codex_contract_js__rspack_import_3.DG)(error); + value = (0, _core_codex_contract_js__rspack_import_4.DG)(error); } const text = value.exitCode === 0 ? `Sent to ${value.kind} ${value.name} (${value.id})${value.messageId ? ` message ${value.messageId}` : ''}; envelope ${value.envelopeId}` : value.error; - return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_8.g.Result, { + return (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_9.g.Result, { value: value, - children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_8.g.Text, { + children: (0, react_jsx_runtime__rspack_import_0.jsx)(_agent_bundle_runtime__rspack_import_9.g.Text, { children: text }) }); @@ -13674,6 +13730,7 @@ var __webpack_modules__ = { var _codex_bridge_js__rspack_import_0 = __webpack_require__("./src/core/codex-bridge.js"); var _contract_js__rspack_import_1 = __webpack_require__("./src/core/codex/contract.js"); var _conversation_js__rspack_import_2 = __webpack_require__("./src/core/codex/conversation.js"); + var _format_js__rspack_import_6 = __webpack_require__("./src/core/format.js"); var _thread_id_js__rspack_import_4 = __webpack_require__("./src/core/codex/thread-id.js"); const bareId = zod__rspack_import_3.YjP().regex(/^[A-Za-z0-9_.:-]{1,128}$/); const id = zod__rspack_import_3.YjP().min(1).max(160).transform((value, ctx)=>{ @@ -13734,7 +13791,23 @@ var __webpack_modules__ = { }).strict(); const threadsSchema = zod__rspack_import_3.Ikc({ limit: zod__rspack_import_3.aig().int().min(1).max(200).default(20), - cursor: zod__rspack_import_3.YjP().min(1).max(4096).optional() + cursor: zod__rspack_import_3.YjP().min(1).max(4096).optional(), + sort: zod__rspack_import_3.k5n([ + 'updated', + 'created', + 'recency' + ]).default('updated'), + order: zod__rspack_import_3.k5n([ + 'desc', + 'asc' + ]).default('desc'), + query: zod__rspack_import_3.YjP().trim().min(1).max(256).optional(), + activeWithin: zod__rspack_import_3.YjP().trim().regex(/^\d+(?:\.\d+)?\s*[smhdw]$/i, 'use a duration like 30m, 12h, 7d or 2w').optional(), + since: zod__rspack_import_3.YjP().trim().min(1).max(64).optional(), + cwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), + modelProvider: zod__rspack_import_3.YjP().min(1).max(256).optional(), + archived: zod__rspack_import_3.zMY().optional(), + sourceKind: zod__rspack_import_3.YjP().min(1).max(64).optional() }).strict(); const resultSchema = zod__rspack_import_3.Ikc({ exitCode: zod__rspack_import_3.aig().int().min(0).max(1), @@ -13894,8 +13967,16 @@ var __webpack_modules__ = { } async function threadsOperation(input) { try { + const { sourceKind, ...rest } = input; return { - ...await listCodexThreads(input), + ...await listCodexThreads({ + ...rest, + ...sourceKind ? { + sourceKinds: [ + sourceKind + ] + } : {} + }), exitCode: 0 }; } catch (error) { @@ -13909,7 +13990,10 @@ var __webpack_modules__ = { if (result.delivery === 'accepted') return `Started turn ${result.turnId} (${result.turnStatus}) on Codex thread ${result.threadId}; message ${result.messageId}`; if (result.delivery) return `Codex delivery ${result.delivery} on thread ${result.threadId}`; if (result.reason) return `Codex observation: ${result.reason}`; - if (Array.isArray(result.threads)) return `${result.threads.length} Codex threads`; + if (Array.isArray(result.threads)) { + const rows = result.threads.map((t)=>(0, _format_js__rspack_import_6.nz)(t)).join('\n\n'); + return `${result.threads.length} Codex threads (sort ${String(result.sort ?? 'updated')} ${String(result.order ?? 'desc')})${result.nextCursor ? `; more: pass cursor ${JSON.stringify(result.nextCursor)}` : ''}${rows ? `\n\n${rows}` : ''}`; + } return String(result.error ?? 'Codex observation complete'); } __webpack_require__.d(__webpack_exports__, { @@ -13918,6 +14002,7 @@ var __webpack_modules__ = { gT: ()=>observeOperation }, { FD: resultSchema, + P3: threadsSchema, R9: watchSchema, at: sendFields, jS: waitSchema @@ -13947,68 +14032,69 @@ var __webpack_modules__ = { }); }, "./src/core/relay/routes.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) { - var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/40.js"); - var zod__rspack_import_3 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); + var _agent_bundle_runtime__rspack_import_5 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/40.js"); + var zod__rspack_import_4 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); var _managed_js__rspack_import_0 = __webpack_require__("./src/core/relay/managed.js"); var _gbot_js__rspack_import_1 = __webpack_require__("./src/gbot.ts"); var _codex_bridge_js__rspack_import_2 = __webpack_require__("./src/core/codex-bridge.js"); - const id = zod__rspack_import_3.YjP().min(1).max(128); + var _sender_prefix_js__rspack_import_3 = __webpack_require__("./src/core/sender-prefix.js"); + const id = zod__rspack_import_4.YjP().min(1).max(128); const routeFields = { codexThreadId: id.optional(), - expectedCwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), + expectedCwd: zod__rspack_import_4.YjP().min(1).max(4096).optional(), + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), requestId: id.optional() }; - const grokSendSchema = zod__rspack_import_3.Ikc({ - target: zod__rspack_import_3.YjP().min(1), - message: zod__rspack_import_3.YjP().min(1), - replyMode: zod__rspack_import_3.k5n([ + const grokSendSchema = zod__rspack_import_4.Ikc({ + target: zod__rspack_import_4.YjP().min(1), + message: zod__rspack_import_4.YjP().min(1), + replyMode: zod__rspack_import_4.k5n([ "auto", "manual" ]).optional(), - hop: zod__rspack_import_3.aig().int().min(0).optional(), + hop: zod__rspack_import_4.aig().int().min(0).optional(), correlationId: id.optional(), ...routeFields }).strict(); - const bridgeStartSchema = zod__rspack_import_3.Ikc({ - grokTarget: zod__rspack_import_3.YjP().min(1), + const bridgeStartSchema = zod__rspack_import_4.Ikc({ + grokTarget: zod__rspack_import_4.YjP().min(1), codexThreadId: id.optional(), - expectedCwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), - busyPolicy: zod__rspack_import_3.k5n([ + expectedCwd: zod__rspack_import_4.YjP().min(1).max(4096).optional(), + busyPolicy: zod__rspack_import_4.k5n([ "steer", "reject" ]).optional(), requestId: id.optional() }).strict(); - const bridgeStatusSchema = zod__rspack_import_3.Ikc({ - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - limit: zod__rspack_import_3.aig().int().min(1).max(100).optional() + const bridgeStatusSchema = zod__rspack_import_4.Ikc({ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + limit: zod__rspack_import_4.aig().int().min(1).max(100).optional() }).strict(); - const bridgeStopSchema = zod__rspack_import_3.Ikc({ - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - all: zod__rspack_import_3.zMY().optional(), - worker: zod__rspack_import_3.zMY().optional() + const bridgeStopSchema = zod__rspack_import_4.Ikc({ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + all: zod__rspack_import_4.zMY().optional(), + worker: zod__rspack_import_4.zMY().optional() }).strict().refine((x)=>!!x.bindingId || x.all === true || x.worker === true, "Specify bindingId, all or worker"); - const respondSchema = zod__rspack_import_3.Ikc({ - interactionId: zod__rspack_import_3.YjP().min(1).max(512), + const respondSchema = zod__rspack_import_4.Ikc({ + interactionId: zod__rspack_import_4.YjP().min(1).max(512), generation: id, threadId: id, turnId: id, - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - exchangeId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - decision: zod__rspack_import_3.k5n([ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + exchangeId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + decision: zod__rspack_import_4.k5n([ "accept", "decline", "cancel" ]).optional(), - answersJson: zod__rspack_import_3.YjP().min(2).max(65536).optional() + answersJson: zod__rspack_import_4.YjP().min(2).max(65536).optional() }).strict().refine((x)=>!!x.bindingId || !!x.exchangeId, "Binding or exchange scope required").refine((x)=>!!x.decision !== !!x.answersJson, "Supply decision or answersJson"); - const answersSchema = zod__rspack_import_3.g1P(zod__rspack_import_3.YjP().min(1).max(128), zod__rspack_import_3.Ikc({ - answers: zod__rspack_import_3.YOg(zod__rspack_import_3.YjP().max(8192)).max(20) + const answersSchema = zod__rspack_import_4.g1P(zod__rspack_import_4.YjP().min(1).max(128), zod__rspack_import_4.Ikc({ + answers: zod__rspack_import_4.YOg(zod__rspack_import_4.YjP().max(8192)).max(20) }).strict()); - const relayResultSchema = zod__rspack_import_3.g1P(zod__rspack_import_3.YjP(), zod__rspack_import_3.Pq9()); + const relayResultSchema = zod__rspack_import_4.g1P(zod__rspack_import_4.YjP(), zod__rspack_import_4.Pq9()); function nativeCodexThread(context) { - return context.host.state === "available" && (0, _agent_bundle_runtime__rspack_import_4.bg)(context.host.value.name) === "codex" && context.lineage.state === "available" && context.lineage.source === "native" && context.lineage.value.resolution === "native" ? context.lineage.value.conversation : undefined; + return context.host.state === "available" && (0, _agent_bundle_runtime__rspack_import_5.bg)(context.host.value.name) === "codex" && context.lineage.state === "available" && context.lineage.source === "native" && context.lineage.value.resolution === "native" ? context.lineage.value.conversation : undefined; } function options(context) { return { @@ -14041,7 +14127,11 @@ var __webpack_modules__ = { } : {} }, options(context))); if (input.replyMode === "auto") throw Error("Automatic reply delivery requires a native Codex source, codexThreadId or bindingId"); - const message = input.hop !== undefined || input.correlationId !== undefined ? (0, _codex_bridge_js__rspack_import_2.Mr)(input.message, (0, _codex_bridge_js__rspack_import_2.nq)(input)) : input.message; + const stamped = input.hop !== undefined || input.correlationId !== undefined ? (0, _codex_bridge_js__rspack_import_2.Mr)(input.message, (0, _codex_bridge_js__rspack_import_2.nq)(input)) : input.message; + const message = (0, _sender_prefix_js__rspack_import_3.Xt)(stamped, { + threadId: route.codexThreadId, + cwd: route.expectedCwd + }); const sent = await (0, _gbot_js__rspack_import_1.yF)(async ()=>(0, _gbot_js__rspack_import_1.LV)(await (0, _gbot_js__rspack_import_1.Vq)(), input.target, message)); return { result: sent.result, @@ -42493,9 +42583,25 @@ var __webpack_modules__ = { }, { "aliases": [], - "description": "List Codex daemon-managed threads (all modelProviders; pages via --cursor / nextCursor).", + "description": "List Codex daemon-managed threads, newest activity first (all modelProviders; pages via --cursor / nextCursor). Find old threads with --query (name/title/id prefix, all pages), --active-within 7d, --since, --sort created.", "exitCode": "result", "options": [ + { + "description": "Only threads updated within 90s, 30m, 12h, 7d, 2w", + "key": "activeWithin", + "kind": "string", + "option": "active-within", + "repeated": false, + "required": false + }, + { + "description": "Archived threads only", + "key": "archived", + "kind": "boolean", + "option": "archived", + "repeated": false, + "required": false + }, { "description": "Opaque pagination cursor from a previous nextCursor (may start with -)", "key": "cursor", @@ -42504,6 +42610,14 @@ var __webpack_modules__ = { "repeated": false, "required": false }, + { + "description": "Exact session cwd", + "key": "cwd", + "kind": "string", + "option": "cwd", + "repeated": false, + "required": false + }, { "defaultValue": 20, "description": "Max threads to list (1-200)", @@ -42512,6 +42626,64 @@ var __webpack_modules__ = { "option": "limit", "repeated": false, "required": false + }, + { + "description": "Any modelProvider id; omit for all", + "key": "modelProvider", + "kind": "string", + "option": "model-provider", + "repeated": false, + "required": false + }, + { + "choices": [ + "desc", + "asc" + ], + "defaultValue": "desc", + "key": "order", + "kind": "enum", + "option": "order", + "repeated": false, + "required": false + }, + { + "description": "Case-insensitive substring of name/title, preview or id (id prefix works); scans every page", + "key": "query", + "kind": "string", + "option": "query", + "repeated": false, + "required": false + }, + { + "description": "Only threads updated at/after this ISO date/time or epoch seconds", + "key": "since", + "kind": "string", + "option": "since", + "repeated": false, + "required": false + }, + { + "choices": [ + "updated", + "created", + "recency" + ], + "defaultValue": "updated", + "description": "updated (last activity, default) | created | recency", + "key": "sort", + "kind": "enum", + "option": "sort", + "repeated": false, + "required": false + }, + { + "description": "Any app-server source kind; omit for interactive sources", + "key": "sourceKind", + "kind": "string", + "option": "source-kind", + "repeated": false, + "required": false } ], "path": [ @@ -45395,7 +45567,52 @@ var __webpack_modules__ = { }; } const THREAD_LIST_MAX_LIMIT = 200; - async function listCodexThreads1({ limit = 20, cursor, modelProviders = [], env = process.env } = {}) { + const THREAD_SORT_KEYS = { + updated: "updated_at", + created: "created_at", + recency: "recency_at" + }; + const GBOT_CURSOR = "gbot1:"; + const DURATION_MS = { + s: 1000, + m: 60000, + h: 3600000, + d: 86400000, + w: 604800000 + }; + const toSeconds = (value)=>value > 1e11 ? value / 1000 : value; + function parseActiveWithin(text) { + const m = /^(\d+(?:\.\d+)?)\s*([smhdw])$/i.exec(String(text).trim()); + if (!m) throw new RangeError("--active-within must look like 30m, 12h, 7d or 2w"); + return Number(m[1]) * DURATION_MS[m[2].toLowerCase()]; + } + function parseSince(value) { + const text = String(value).trim(); + const n = /^\d+(?:\.\d+)?$/.test(text) ? toSeconds(Number(text)) : Date.parse(text) / 1000; + if (!Number.isFinite(n)) throw new RangeError("--since must be an ISO date/time or epoch seconds"); + return n; + } + function encodeThreadCursor(state) { + return GBOT_CURSOR + Buffer.from(JSON.stringify(state)).toString("base64url"); + } + function decodeThreadCursor(cursor) { + if (cursor === undefined) return { + skip: 0 + }; + if (!cursor.startsWith(GBOT_CURSOR)) return { + c: cursor, + skip: 0 + }; + try { + const v = JSON.parse(Buffer.from(cursor.slice(GBOT_CURSOR.length), "base64url").toString("utf8")); + if (isObject(v) && Number.isInteger(v.skip) && v.skip >= 0 && (v.c === undefined || typeof v.c === "string")) return { + c: v.c, + skip: v.skip + }; + } catch {} + throw new RangeError("--cursor is not a valid thread cursor"); + } + async function listCodexThreads1({ limit = 20, cursor, modelProviders = [], modelProvider, sort = "updated", order: order1 = "desc", query, since, activeWithin, cwd, archived, sourceKinds, now = Date.now(), env = process.env } = {}) { if (!Number.isInteger(limit) || limit < 1 || limit > THREAD_LIST_MAX_LIMIT) { throw new RangeError("--limit must be an integer 1-" + THREAD_LIST_MAX_LIMIT); } @@ -45403,45 +45620,125 @@ var __webpack_modules__ = { if (!Array.isArray(modelProviders) || modelProviders.some((p)=>typeof p !== "string")) { throw new RangeError("modelProviders must be an array of strings (empty = all providers)"); } + if (!Object.hasOwn(THREAD_SORT_KEYS, sort)) throw new RangeError("--sort must be one of: " + Object.keys(THREAD_SORT_KEYS).join(", ")); + if (order1 !== "asc" && order1 !== "desc") throw new RangeError("--order must be asc or desc"); + if (query !== undefined && (typeof query !== "string" || !query.trim())) throw new RangeError("--query must be a non-empty string"); + if (sourceKinds !== undefined && (!Array.isArray(sourceKinds) || sourceKinds.some((k)=>typeof k !== "string" || !k))) { + throw new RangeError("--source-kind must be a non-empty string"); + } + const providers = modelProvider ? [ + ...modelProviders, + modelProvider + ] : modelProviders; + const needle = query?.trim().toLowerCase(); + const cutoffs = []; + if (since !== undefined) cutoffs.push(parseSince(since)); + if (activeWithin !== undefined) cutoffs.push((now - parseActiveWithin(activeWithin)) / 1000); + const cutoff = cutoffs.length ? Math.max(...cutoffs) : undefined; + const clientSide = needle !== undefined || cutoff !== undefined; + const activityOf = (t)=>typeof t.updatedAt === "number" ? toSeconds(t.updatedAt) : typeof t.createdAt === "number" ? toSeconds(t.createdAt) : null; + const keep = (t)=>{ + if (cutoff !== undefined) { + const at = activityOf(t); + if (at === null || at < cutoff) return false; + } + if (needle !== undefined && ![ + t.name, + t.preview, + t.id + ].some((f)=>typeof f === "string" && f.toLowerCase().includes(needle))) return false; + return true; + }; + const pageSize = clientSide ? THREAD_LIST_MAX_LIMIT : limit; + const start = decodeThreadCursor(cursor); const { client } = await openSession(env); try { const baseParams = { - limit, - modelProviders, - ...cursor !== undefined ? { - cursor + limit: pageSize, + modelProviders: providers, + sortKey: THREAD_SORT_KEYS[sort], + ...order1 === "asc" ? { + sortDirection: "asc" + } : {}, + ...cwd ? { + cwd + } : {}, + ...archived === true ? { + archived: true + } : {}, + ...sourceKinds?.length ? { + sourceKinds } : {} }; - let out; - let usedStateDbOnly = true; - try { - out = await client.request("thread/list", { - ...baseParams, - useStateDbOnly: true - }); - } catch (err) { - throw transportError(err); - } - if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); - if (out.data.length === 0 && cursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + const fetchPage = async (pageCursor, useStateDbOnly)=>{ try { - out = await client.request("thread/list", { + return await client.request("thread/list", { ...baseParams, - useStateDbOnly: false + ...pageCursor !== undefined ? { + cursor: pageCursor + } : {}, + useStateDbOnly }); - usedStateDbOnly = false; } catch (err) { throw transportError(err); } + }; + const checkPage = (out)=>{ if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); + if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); + }; + const threads = []; + let usedStateDbOnly = true; + let scanned = 0; + let nextCursor = null; + let pageCursor = start.c; + let skip = start.skip; + for(;;){ + let out = await fetchPage(pageCursor, true); + checkPage(out); + if (out.data.length === 0 && pageCursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + out = await fetchPage(pageCursor, false); + usedStateDbOnly = false; + checkPage(out); + } + const rows = out.data.map(summarizeThread); + scanned += rows.length; + let matches = rows.filter(keep); + const pageSkip = skip; + if (skip) { + matches = matches.slice(skip); + skip = 0; + } + const need = limit - threads.length; + if (matches.length > need) { + threads.push(...matches.slice(0, need)); + nextCursor = encodeThreadCursor({ + ...pageCursor !== undefined ? { + c: pageCursor + } : {}, + skip: pageSkip + need + }); + break; + } + threads.push(...matches); + const more = out.nextCursor || null; + const last = rows[rows.length - 1]; + const pastCutoff = cutoff !== undefined && sort === "updated" && order1 === "desc" && last !== undefined && (activityOf(last) ?? -Infinity) < cutoff; + if (!more || pastCutoff) break; + if (threads.length >= limit) { + nextCursor = more; + break; + } + pageCursor = more; } - if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); - const threads = out.data.map(summarizeThread); return { threads, - nextCursor: out.nextCursor ?? null, + nextCursor, limit, - useStateDbOnly: usedStateDbOnly + useStateDbOnly: usedStateDbOnly, + sort, + order: order1, + scanned }; } finally{ client.close(); @@ -47441,7 +47738,8 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } function formatCodexThread(t) { const title = t.name ? " - " + stripTerminalControls(t.name) : ""; const preview = t.preview ? "\n " + stripTerminalControls(String(t.preview).replace(/\s+/g, " ")).slice(0, 200) : ""; - return stripTerminalControls(t.id) + " " + stripTerminalControls(t.status) + title + "\n " + stripTerminalControls(t.cwd ?? "") + preview; + const at = typeof t.updatedAt === "number" && Number.isFinite(t.updatedAt) ? new Date(t.updatedAt > 1e11 ? t.updatedAt : t.updatedAt * 1000).toISOString().replace(/\.\d{3}Z$/, "Z") : ""; + return stripTerminalControls(t.id) + " " + stripTerminalControls(t.status) + title + "\n " + stripTerminalControls(t.cwd ?? "") + (at ? " (updated " + at + ")" : "") + preview; } function shellQuote(value) { return "'" + String(value).replace(/'/g, "'\\''") + "'"; @@ -48523,6 +48821,42 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } br: digest }); }, + "./src/core/sender-prefix.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { + var node_os__rspack_import_0 = __webpack_require__("node:os"); + const oneLine = (value)=>String(value ?? "").replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/[\]]/g, ")").trim(); + function machineName(env = process.env) { + try { + return oneLine(env.GROK_BOT_MACHINE_NAME || (0, node_os__rspack_import_0.hostname)()); + } catch { + return ""; + } + } + function codexSenderPrefix({ threadId, machine, cwd, details = [], env = process.env } = {}) { + const id = oneLine(threadId); + if (!id) return ""; + const where = oneLine(machine ?? machineName(env)); + const dir = oneLine(cwd); + const head = "from Codex thread " + id + (where ? " @ " + where : "") + (dir ? (where ? ", " : " ") + "cwd " + dir : ""); + const reply = "reply: codex_send({threadId:\"" + id + "\", message:\"...\"})" + (where ? " via MCP on " + where : " via MCP") + " (or CLI: gbot codex send " + id + " \"...\")"; + return "[" + [ + head, + ...details.map(oneLine).filter(Boolean), + reply + ].join("; ") + "]"; + } + function withCodexSender(text, fields) { + const prefix = codexSenderPrefix(fields); + return prefix ? prefix + "\n" + text : text; + } + function envCodexThreadId(env = process.env) { + const id = env.CODEX_THREAD_ID?.trim(); + return id && /^[A-Za-z0-9_.:-]{1,128}$/.test(id) ? id : undefined; + } + __webpack_require__.d(__webpack_exports__, { + Wh: ()=>envCodexThreadId, + Xt: ()=>withCodexSender + }); + }, "./src/core/store.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { var node_crypto__rspack_import_0 = __webpack_require__("node:crypto"); var node_fs__rspack_import_1 = __webpack_require__("node:fs"); diff --git a/artifact/mcp/mcp-grok-bot-b8c2461e-flight.mjs b/artifact/mcp/mcp-grok-bot-b8c2461e-flight.mjs index f30c44c..246c349 100644 --- a/artifact/mcp/mcp-grok-bot-b8c2461e-flight.mjs +++ b/artifact/mcp/mcp-grok-bot-b8c2461e-flight.mjs @@ -11956,6 +11956,7 @@ var __webpack_modules__ = { var _codex_bridge_js__rspack_import_0 = __webpack_require__("./src/core/codex-bridge.js"); var _contract_js__rspack_import_1 = __webpack_require__("./src/core/codex/contract.js"); var _conversation_js__rspack_import_2 = __webpack_require__("./src/core/codex/conversation.js"); + var _format_js__rspack_import_6 = __webpack_require__("./src/core/format.js"); var _thread_id_js__rspack_import_4 = __webpack_require__("./src/core/codex/thread-id.js"); const bareId = zod__rspack_import_3.YjP().regex(/^[A-Za-z0-9_.:-]{1,128}$/); const id = zod__rspack_import_3.YjP().min(1).max(160).transform((value, ctx)=>{ @@ -12016,7 +12017,23 @@ var __webpack_modules__ = { }).strict(); const threadsSchema = zod__rspack_import_3.Ikc({ limit: zod__rspack_import_3.aig().int().min(1).max(200).default(20), - cursor: zod__rspack_import_3.YjP().min(1).max(4096).optional() + cursor: zod__rspack_import_3.YjP().min(1).max(4096).optional(), + sort: zod__rspack_import_3.k5n([ + 'updated', + 'created', + 'recency' + ]).default('updated'), + order: zod__rspack_import_3.k5n([ + 'desc', + 'asc' + ]).default('desc'), + query: zod__rspack_import_3.YjP().trim().min(1).max(256).optional(), + activeWithin: zod__rspack_import_3.YjP().trim().regex(/^\d+(?:\.\d+)?\s*[smhdw]$/i, 'use a duration like 30m, 12h, 7d or 2w').optional(), + since: zod__rspack_import_3.YjP().trim().min(1).max(64).optional(), + cwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), + modelProvider: zod__rspack_import_3.YjP().min(1).max(256).optional(), + archived: zod__rspack_import_3.zMY().optional(), + sourceKind: zod__rspack_import_3.YjP().min(1).max(64).optional() }).strict(); const resultSchema = zod__rspack_import_3.Ikc({ exitCode: zod__rspack_import_3.aig().int().min(0).max(1), @@ -12176,8 +12193,16 @@ var __webpack_modules__ = { } async function threadsOperation(input) { try { + const { sourceKind, ...rest } = input; return { - ...await (0, _codex_bridge_js__rspack_import_0.X$)(input), + ...await (0, _codex_bridge_js__rspack_import_0.X$)({ + ...rest, + ...sourceKind ? { + sourceKinds: [ + sourceKind + ] + } : {} + }), exitCode: 0 }; } catch (error) { @@ -12191,7 +12216,10 @@ var __webpack_modules__ = { if (result.delivery === 'accepted') return `Started turn ${result.turnId} (${result.turnStatus}) on Codex thread ${result.threadId}; message ${result.messageId}`; if (result.delivery) return `Codex delivery ${result.delivery} on thread ${result.threadId}`; if (result.reason) return `Codex observation: ${result.reason}`; - if (Array.isArray(result.threads)) return `${result.threads.length} Codex threads`; + if (Array.isArray(result.threads)) { + const rows = result.threads.map((t)=>(0, _format_js__rspack_import_6.nz)(t)).join('\n\n'); + return `${result.threads.length} Codex threads (sort ${String(result.sort ?? 'updated')} ${String(result.order ?? 'desc')})${result.nextCursor ? `; more: pass cursor ${JSON.stringify(result.nextCursor)}` : ''}${rows ? `\n\n${rows}` : ''}`; + } return String(result.error ?? 'Codex observation complete'); } __webpack_require__.d(__webpack_exports__, { @@ -12231,68 +12259,69 @@ var __webpack_modules__ = { }); }, "./src/core/relay/routes.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) { - var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/40.js"); - var zod__rspack_import_3 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); + var _agent_bundle_runtime__rspack_import_5 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/40.js"); + var zod__rspack_import_4 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); var _managed_js__rspack_import_0 = __webpack_require__("./src/core/relay/managed.js"); var _gbot_js__rspack_import_1 = __webpack_require__("./src/gbot.ts"); var _codex_bridge_js__rspack_import_2 = __webpack_require__("./src/core/codex-bridge.js"); - const id = zod__rspack_import_3.YjP().min(1).max(128); + var _sender_prefix_js__rspack_import_3 = __webpack_require__("./src/core/sender-prefix.js"); + const id = zod__rspack_import_4.YjP().min(1).max(128); const routeFields = { codexThreadId: id.optional(), - expectedCwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), + expectedCwd: zod__rspack_import_4.YjP().min(1).max(4096).optional(), + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), requestId: id.optional() }; - const grokSendSchema = zod__rspack_import_3.Ikc({ - target: zod__rspack_import_3.YjP().min(1), - message: zod__rspack_import_3.YjP().min(1), - replyMode: zod__rspack_import_3.k5n([ + const grokSendSchema = zod__rspack_import_4.Ikc({ + target: zod__rspack_import_4.YjP().min(1), + message: zod__rspack_import_4.YjP().min(1), + replyMode: zod__rspack_import_4.k5n([ "auto", "manual" ]).optional(), - hop: zod__rspack_import_3.aig().int().min(0).optional(), + hop: zod__rspack_import_4.aig().int().min(0).optional(), correlationId: id.optional(), ...routeFields }).strict(); - const bridgeStartSchema = zod__rspack_import_3.Ikc({ - grokTarget: zod__rspack_import_3.YjP().min(1), + const bridgeStartSchema = zod__rspack_import_4.Ikc({ + grokTarget: zod__rspack_import_4.YjP().min(1), codexThreadId: id.optional(), - expectedCwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), - busyPolicy: zod__rspack_import_3.k5n([ + expectedCwd: zod__rspack_import_4.YjP().min(1).max(4096).optional(), + busyPolicy: zod__rspack_import_4.k5n([ "steer", "reject" ]).optional(), requestId: id.optional() }).strict(); - const bridgeStatusSchema = zod__rspack_import_3.Ikc({ - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - limit: zod__rspack_import_3.aig().int().min(1).max(100).optional() + const bridgeStatusSchema = zod__rspack_import_4.Ikc({ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + limit: zod__rspack_import_4.aig().int().min(1).max(100).optional() }).strict(); - const bridgeStopSchema = zod__rspack_import_3.Ikc({ - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - all: zod__rspack_import_3.zMY().optional(), - worker: zod__rspack_import_3.zMY().optional() + const bridgeStopSchema = zod__rspack_import_4.Ikc({ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + all: zod__rspack_import_4.zMY().optional(), + worker: zod__rspack_import_4.zMY().optional() }).strict().refine((x)=>!!x.bindingId || x.all === true || x.worker === true, "Specify bindingId, all or worker"); - const respondSchema = zod__rspack_import_3.Ikc({ - interactionId: zod__rspack_import_3.YjP().min(1).max(512), + const respondSchema = zod__rspack_import_4.Ikc({ + interactionId: zod__rspack_import_4.YjP().min(1).max(512), generation: id, threadId: id, turnId: id, - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - exchangeId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - decision: zod__rspack_import_3.k5n([ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + exchangeId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + decision: zod__rspack_import_4.k5n([ "accept", "decline", "cancel" ]).optional(), - answersJson: zod__rspack_import_3.YjP().min(2).max(65536).optional() + answersJson: zod__rspack_import_4.YjP().min(2).max(65536).optional() }).strict().refine((x)=>!!x.bindingId || !!x.exchangeId, "Binding or exchange scope required").refine((x)=>!!x.decision !== !!x.answersJson, "Supply decision or answersJson"); - const answersSchema = zod__rspack_import_3.g1P(zod__rspack_import_3.YjP().min(1).max(128), zod__rspack_import_3.Ikc({ - answers: zod__rspack_import_3.YOg(zod__rspack_import_3.YjP().max(8192)).max(20) + const answersSchema = zod__rspack_import_4.g1P(zod__rspack_import_4.YjP().min(1).max(128), zod__rspack_import_4.Ikc({ + answers: zod__rspack_import_4.YOg(zod__rspack_import_4.YjP().max(8192)).max(20) }).strict()); - const relayResultSchema = zod__rspack_import_3.g1P(zod__rspack_import_3.YjP(), zod__rspack_import_3.Pq9()); + const relayResultSchema = zod__rspack_import_4.g1P(zod__rspack_import_4.YjP(), zod__rspack_import_4.Pq9()); function nativeCodexThread(context) { - return context.host.state === "available" && (0, _agent_bundle_runtime__rspack_import_4.bg)(context.host.value.name) === "codex" && context.lineage.state === "available" && context.lineage.source === "native" && context.lineage.value.resolution === "native" ? context.lineage.value.conversation : undefined; + return context.host.state === "available" && (0, _agent_bundle_runtime__rspack_import_5.bg)(context.host.value.name) === "codex" && context.lineage.state === "available" && context.lineage.source === "native" && context.lineage.value.resolution === "native" ? context.lineage.value.conversation : undefined; } function options(context) { return { @@ -12325,7 +12354,11 @@ var __webpack_modules__ = { } : {} }, options(context))); if (input.replyMode === "auto") throw Error("Automatic reply delivery requires a native Codex source, codexThreadId or bindingId"); - const message = input.hop !== undefined || input.correlationId !== undefined ? (0, _codex_bridge_js__rspack_import_2.Mr)(input.message, (0, _codex_bridge_js__rspack_import_2.nq)(input)) : input.message; + const stamped = input.hop !== undefined || input.correlationId !== undefined ? (0, _codex_bridge_js__rspack_import_2.Mr)(input.message, (0, _codex_bridge_js__rspack_import_2.nq)(input)) : input.message; + const message = (0, _sender_prefix_js__rspack_import_3.Xt)(stamped, { + threadId: route.codexThreadId, + cwd: route.expectedCwd + }); const sent = await (0, _gbot_js__rspack_import_1.yF)(async ()=>(0, _gbot_js__rspack_import_1.LV)(await (0, _gbot_js__rspack_import_1.Vq)(), input.target, message)); return { result: sent.result, @@ -12472,7 +12505,7 @@ var __webpack_modules__ = { }; }; const metaLength = (entry)=>entry.id.length + entry.kind.length + (entry.role?.length ?? 0); - const transcriptEntries = (transcript)=>{ + const transcriptEntries1 = (transcript)=>{ const rows = (0, _core_transcript_js__rspack_import_2.xw)(transcript); let remaining = TRANSCRIPT_TOTAL_MAX; return rows.map((raw)=>{ @@ -12494,7 +12527,7 @@ var __webpack_modules__ = { }, { Oo: entrySchema, rW: summarizeTarget, - xw: transcriptEntries, + xw: transcriptEntries1, yF: withRedactedErrors }); }, @@ -13231,7 +13264,7 @@ var __webpack_modules__ = { excludeClients: [ 'codex' ], - description: 'Discover a bounded page of Codex daemon threads. Runs on the user\'s registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.', + description: 'Discover Codex daemon threads on the user\'s registered machine (local socket, not the Grok Bot box; from the box run gbot there through Shell with a machineId after codex app-server daemon start or bootstrap). Newest activity first by default (sort:"updated"), so old-but-active threads surface; sort:"created" restores creation order. Find one thread with query (case-insensitive substring of name/title, preview or id, so an id prefix works) - it scans every page, not just the first 100. Narrow with activeWithin ("30m", "12h", "7d", "2w") or since (ISO/epoch seconds), cwd, modelProvider, sourceKind, archived. limit is the page size (1-200); pass nextCursor back as cursor for more.', title: 'Codex threads', annotations: { readOnlyHint: true @@ -13245,13 +13278,59 @@ var __webpack_modules__ = { type: 'object', additionalProperties: false, properties: { - "limit": { - "type": "number", - "description": "Maximum threads in this page: 1-200. Pass modelProviders:[] internally so every provider is included; use cursor/nextCursor to page." + limit: { + type: 'number', + description: 'Maximum threads in this page: 1-200 (default 20). Every provider is included; use cursor/nextCursor to page.' }, - "cursor": { - "type": "string", - "description": "Opaque nextCursor from a previous page." + cursor: { + type: 'string', + description: 'Opaque nextCursor from a previous page.' + }, + sort: { + type: 'string', + enum: [ + 'updated', + 'created', + 'recency' + ], + default: 'updated', + description: 'updated = last activity (default), created = creation time, recency = daemon recency order.' + }, + order: { + type: 'string', + enum: [ + 'desc', + 'asc' + ], + default: 'desc' + }, + query: { + type: 'string', + description: 'Case-insensitive substring of thread name/title, preview or id (id prefix works). Scans all pages.' + }, + activeWithin: { + type: 'string', + description: 'Only threads updated within this long: 90s, 30m, 12h, 7d, 2w.' + }, + since: { + type: 'string', + description: 'Only threads updated at or after this ISO date/time or epoch seconds.' + }, + cwd: { + type: 'string', + description: 'Exact session working directory.' + }, + modelProvider: { + type: 'string', + description: 'Any modelProvider id; omit for all.' + }, + sourceKind: { + type: 'string', + description: 'Any app-server source kind (cli, vscode, exec, appServer, subAgent...); omit for interactive sources.' + }, + archived: { + type: 'boolean', + description: 'true = archived threads only.' } }, required: [] @@ -25764,7 +25843,52 @@ var __webpack_modules__ = { }; } const THREAD_LIST_MAX_LIMIT = 200; - async function listCodexThreads({ limit = 20, cursor, modelProviders = [], env = process.env } = {}) { + const THREAD_SORT_KEYS = { + updated: "updated_at", + created: "created_at", + recency: "recency_at" + }; + const GBOT_CURSOR = "gbot1:"; + const DURATION_MS = { + s: 1000, + m: 60000, + h: 3600000, + d: 86400000, + w: 604800000 + }; + const toSeconds = (value)=>value > 1e11 ? value / 1000 : value; + function parseActiveWithin(text) { + const m = /^(\d+(?:\.\d+)?)\s*([smhdw])$/i.exec(String(text).trim()); + if (!m) throw new RangeError("--active-within must look like 30m, 12h, 7d or 2w"); + return Number(m[1]) * DURATION_MS[m[2].toLowerCase()]; + } + function parseSince(value) { + const text = String(value).trim(); + const n = /^\d+(?:\.\d+)?$/.test(text) ? toSeconds(Number(text)) : Date.parse(text) / 1000; + if (!Number.isFinite(n)) throw new RangeError("--since must be an ISO date/time or epoch seconds"); + return n; + } + function encodeThreadCursor(state) { + return GBOT_CURSOR + Buffer.from(JSON.stringify(state)).toString("base64url"); + } + function decodeThreadCursor(cursor) { + if (cursor === undefined) return { + skip: 0 + }; + if (!cursor.startsWith(GBOT_CURSOR)) return { + c: cursor, + skip: 0 + }; + try { + const v = JSON.parse(Buffer.from(cursor.slice(GBOT_CURSOR.length), "base64url").toString("utf8")); + if (isObject(v) && Number.isInteger(v.skip) && v.skip >= 0 && (v.c === undefined || typeof v.c === "string")) return { + c: v.c, + skip: v.skip + }; + } catch {} + throw new RangeError("--cursor is not a valid thread cursor"); + } + async function listCodexThreads({ limit = 20, cursor, modelProviders = [], modelProvider, sort = "updated", order = "desc", query, since, activeWithin, cwd, archived, sourceKinds, now = Date.now(), env = process.env } = {}) { if (!Number.isInteger(limit) || limit < 1 || limit > THREAD_LIST_MAX_LIMIT) { throw new RangeError("--limit must be an integer 1-" + THREAD_LIST_MAX_LIMIT); } @@ -25772,45 +25896,125 @@ var __webpack_modules__ = { if (!Array.isArray(modelProviders) || modelProviders.some((p)=>typeof p !== "string")) { throw new RangeError("modelProviders must be an array of strings (empty = all providers)"); } + if (!Object.hasOwn(THREAD_SORT_KEYS, sort)) throw new RangeError("--sort must be one of: " + Object.keys(THREAD_SORT_KEYS).join(", ")); + if (order !== "asc" && order !== "desc") throw new RangeError("--order must be asc or desc"); + if (query !== undefined && (typeof query !== "string" || !query.trim())) throw new RangeError("--query must be a non-empty string"); + if (sourceKinds !== undefined && (!Array.isArray(sourceKinds) || sourceKinds.some((k)=>typeof k !== "string" || !k))) { + throw new RangeError("--source-kind must be a non-empty string"); + } + const providers = modelProvider ? [ + ...modelProviders, + modelProvider + ] : modelProviders; + const needle = query?.trim().toLowerCase(); + const cutoffs = []; + if (since !== undefined) cutoffs.push(parseSince(since)); + if (activeWithin !== undefined) cutoffs.push((now - parseActiveWithin(activeWithin)) / 1000); + const cutoff = cutoffs.length ? Math.max(...cutoffs) : undefined; + const clientSide = needle !== undefined || cutoff !== undefined; + const activityOf = (t)=>typeof t.updatedAt === "number" ? toSeconds(t.updatedAt) : typeof t.createdAt === "number" ? toSeconds(t.createdAt) : null; + const keep = (t)=>{ + if (cutoff !== undefined) { + const at = activityOf(t); + if (at === null || at < cutoff) return false; + } + if (needle !== undefined && ![ + t.name, + t.preview, + t.id + ].some((f)=>typeof f === "string" && f.toLowerCase().includes(needle))) return false; + return true; + }; + const pageSize = clientSide ? THREAD_LIST_MAX_LIMIT : limit; + const start = decodeThreadCursor(cursor); const { client } = await openSession(env); try { const baseParams = { - limit, - modelProviders, - ...cursor !== undefined ? { - cursor + limit: pageSize, + modelProviders: providers, + sortKey: THREAD_SORT_KEYS[sort], + ...order === "asc" ? { + sortDirection: "asc" + } : {}, + ...cwd ? { + cwd + } : {}, + ...archived === true ? { + archived: true + } : {}, + ...sourceKinds?.length ? { + sourceKinds } : {} }; - let out; - let usedStateDbOnly = true; - try { - out = await client.request("thread/list", { - ...baseParams, - useStateDbOnly: true - }); - } catch (err) { - throw transportError(err); - } - if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); - if (out.data.length === 0 && cursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + const fetchPage = async (pageCursor, useStateDbOnly)=>{ try { - out = await client.request("thread/list", { + return await client.request("thread/list", { ...baseParams, - useStateDbOnly: false + ...pageCursor !== undefined ? { + cursor: pageCursor + } : {}, + useStateDbOnly }); - usedStateDbOnly = false; } catch (err) { throw transportError(err); } + }; + const checkPage = (out)=>{ if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); + if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); + }; + const threads = []; + let usedStateDbOnly = true; + let scanned = 0; + let nextCursor = null; + let pageCursor = start.c; + let skip = start.skip; + for(;;){ + let out = await fetchPage(pageCursor, true); + checkPage(out); + if (out.data.length === 0 && pageCursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + out = await fetchPage(pageCursor, false); + usedStateDbOnly = false; + checkPage(out); + } + const rows = out.data.map(summarizeThread); + scanned += rows.length; + let matches = rows.filter(keep); + const pageSkip = skip; + if (skip) { + matches = matches.slice(skip); + skip = 0; + } + const need = limit - threads.length; + if (matches.length > need) { + threads.push(...matches.slice(0, need)); + nextCursor = encodeThreadCursor({ + ...pageCursor !== undefined ? { + c: pageCursor + } : {}, + skip: pageSkip + need + }); + break; + } + threads.push(...matches); + const more = out.nextCursor || null; + const last = rows[rows.length - 1]; + const pastCutoff = cutoff !== undefined && sort === "updated" && order === "desc" && last !== undefined && (activityOf(last) ?? -Infinity) < cutoff; + if (!more || pastCutoff) break; + if (threads.length >= limit) { + nextCursor = more; + break; + } + pageCursor = more; } - if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); - const threads = out.data.map(summarizeThread); return { threads, - nextCursor: out.nextCursor ?? null, + nextCursor, limit, - useStateDbOnly: usedStateDbOnly + useStateDbOnly: usedStateDbOnly, + sort, + order, + scanned }; } finally{ client.close(); @@ -27635,6 +27839,127 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } em: ()=>desktopShimStatus }); }, + "./src/core/format.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { + function stripTerminalControls(text) { + return String(text).replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, "").replace(/\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)/g, "").replace(/\u001b./g, "").replace(/[\u0000-\u001F\u007F-\u009F]/g, ""); + } + function summarize(rec) { + return { + id: rec.id, + name: rec.name, + title: rec.title || undefined, + description: rec.description || undefined, + avatarShape: rec.avatarShape || undefined, + avatarColor: rec.avatarColor || undefined, + ...rec.notifyOnAgentUpdates !== undefined ? { + notifyOnAgentUpdates: rec.notifyOnAgentUpdates + } : {}, + ...rec.hiddenFromSidebar !== undefined ? { + hiddenFromSidebar: rec.hiddenFromSidebar + } : {}, + kind: rec.isGroup ? "group" : "bot", + members: rec.isGroup ? rec.memberIds : undefined + }; + } + function formatRecord(rec, all) { + const kind = rec.isGroup ? "group" : "bot"; + const members = rec.isGroup ? rec.memberIds.map((id)=>{ + const m = all.find((r)=>r.id === id); + return m ? m.name + " (" + id + ")" : id; + }).join(", ") : ""; + const title = rec.title ? " - " + rec.title : ""; + const desc = rec.description ? "\n " + rec.description : ""; + const avatar = rec.avatarShape || rec.avatarColor ? "\n avatar: " + [ + rec.avatarShape, + rec.avatarColor + ].filter(Boolean).join(" ") : ""; + const settings = []; + if (rec.notifyOnAgentUpdates !== undefined) settings.push("notify " + (rec.notifyOnAgentUpdates ? "on" : "off")); + if (rec.hiddenFromSidebar !== undefined) settings.push("hidden " + (rec.hiddenFromSidebar ? "on" : "off")); + const settingsLine = settings.length ? "\n " + settings.join(", ") : ""; + const extra = rec.isGroup ? "\n members (" + rec.memberIds.length + "): " + (members || "(none)") : ""; + return kind + " " + rec.name + title + "\n " + rec.id + desc + avatar + settingsLine + extra; + } + function formatTranscript(out, { full = false } = {}) { + const rec = out.target; + const payload = out.transcript || out.thread || {}; + const entries = transcriptEntries(payload); + const header = (rec.isGroup ? "group" : "bot") + " " + rec.name + "\n " + rec.id; + if (!Array.isArray(entries) || entries.length === 0) { + return header + "\n (no messages)"; + } + const lines = [ + header, + "" + ]; + for (const e of entries){ + const role = e.role || e.kind || e.sender || e.type || "msg"; + const text = entryText(e); + const id = e.id || ""; + lines.push("[" + role + (id ? " " + id : "") + "] " + (full ? text : truncateCliText(text))); + } + return lines.join("\n"); + } + function truncateCliText(text, max = 400) { + if (text.length <= max) return text; + return text.slice(0, max) + "… [+" + (text.length - max) + " chars; --full or --json for complete text]"; + } + function formatCodexStatus(s) { + const lines = [ + "socket: " + s.socketPath + " (" + s.socketState + ")" + ]; + if (s.desktopShimConfigured) lines.push("desktop shim: configured (managed attachment unverified)"); + if (!s.reachable) return lines.concat("reachable: no (" + s.mode + ")", s.message).join("\n"); + if (s.mode !== "daemon") { + return lines.concat("reachable: yes, but unusable (" + s.mode + ")", s.message).join("\n"); + } + lines.push("reachable: yes (daemon)"); + const cli = s.cliVersion ?? (s.cliVersionProbe === "ok" ? "unknown" : "unknown, probe " + s.cliVersionProbe); + lines.push("daemon version: " + (s.daemonVersion ?? "unknown") + " cli version: " + cli + " pinned schema: " + s.pinnedVersion + " (" + s.schema.compatibility + ")"); + lines.push(s.desktopAttached === "private-stdio" ? "desktop attached: private-stdio (Desktop-bundled app-server process observed; managed attachment unverified)" : "desktop attached: unknown (not observable from the socket)"); + if (s.versionMismatch) { + lines.push("warning: daemon and CLI versions differ; `codex app-server daemon restart` picks up the installed CLI"); + } + return lines.join("\n"); + } + function formatCodexQueue({ threadId, queued }) { + if (queued.length === 0) return "No queued submissions on Codex thread " + threadId + "."; + return queued.map((q)=>q.id + " " + (q.clientUserMessageId ?? "") + "\n " + stripTerminalControls(q.text).replace(/\s+/g, " ").slice(0, 200)).join("\n\n"); + } + function formatCodexThread(t) { + const title = t.name ? " - " + stripTerminalControls(t.name) : ""; + const preview = t.preview ? "\n " + stripTerminalControls(String(t.preview).replace(/\s+/g, " ")).slice(0, 200) : ""; + const at = typeof t.updatedAt === "number" && Number.isFinite(t.updatedAt) ? new Date(t.updatedAt > 1e11 ? t.updatedAt : t.updatedAt * 1000).toISOString().replace(/\.\d{3}Z$/, "Z") : ""; + return stripTerminalControls(t.id) + " " + stripTerminalControls(t.status) + title + "\n " + stripTerminalControls(t.cwd ?? "") + (at ? " (updated " + at + ")" : "") + preview; + } + function shellQuote(value) { + return "'" + String(value).replace(/'/g, "'\\''") + "'"; + } + function formatDesktopShimStatus(s) { + const mark = (ok)=>ok ? "yes" : "no"; + const cliLine = s.platform === "darwin" ? "CODEX_CLI_PATH: GUI domain " + (s.guiCliPath ?? "(unset)") + " / this shell " + (s.cliPath ?? "(unset)") + (s.wrapperPointsAtShim ? " (Desktop-facing value points at shim)" : "") : "CODEX_CLI_PATH: " + (s.cliPath ?? "(unset)") + (s.wrapperPointsAtShim ? " (points at shim)" : ""); + const lines = [ + "wrapper: " + s.wrapperPath + " (" + (s.wrapperExecutable ? "executable" : s.wrapperPresent ? "present, not executable" : "absent") + ")", + "bridge: " + s.bridgePath + " (" + mark(s.bridgePresent) + ")", + "login env: " + s.envScriptPath + " (" + mark(s.envScriptPresent) + ")", + s.platform === "darwin" ? "LaunchAgent: " + s.plistPath + " (" + mark(s.plistPresent) + ")" : "LaunchAgent: n/a (macOS-only)", + cliLine, + "daemon socket: " + s.socketPath + " (" + s.socketState + ", from " + (s.socketSource ?? "CODEX_HOME") + ")" + ]; + if (!s.installed) { + lines.push("shim: not installed — run `gbot codex desktop-shim install` (Desktop keeps stock behavior until then)"); + } else if (!s.wrapperPointsAtShim) { + lines.push(s.platform === "darwin" ? "shim: installed but CODEX_CLI_PATH does not point at it — reinstall or relaunch ChatGPT.app after login" : "shim: installed but CODEX_CLI_PATH does not point at it — export CODEX_CLI_PATH=" + shellQuote(s.wrapperPath)); + } else { + lines.push("shim: active — Desktop app-server spawns bridge onto the managed daemon"); + } + for (const warning of s.warnings ?? [])lines.push("warning: " + String(warning)); + return lines.join("\n"); + } + __webpack_require__.d(__webpack_exports__, { + nz: ()=>formatCodexThread + }); + }, "./src/core/gateway.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { var node_crypto__rspack_import_0 = __webpack_require__("node:crypto"); var _headers_js__rspack_import_5 = __webpack_require__("./src/core/headers.js"); @@ -28561,6 +28886,41 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } br: digest }); }, + "./src/core/sender-prefix.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { + var node_os__rspack_import_0 = __webpack_require__("node:os"); + const oneLine = (value)=>String(value ?? "").replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/[\]]/g, ")").trim(); + function machineName(env = process.env) { + try { + return oneLine(env.GROK_BOT_MACHINE_NAME || (0, node_os__rspack_import_0.hostname)()); + } catch { + return ""; + } + } + function codexSenderPrefix({ threadId, machine, cwd, details = [], env = process.env } = {}) { + const id = oneLine(threadId); + if (!id) return ""; + const where = oneLine(machine ?? machineName(env)); + const dir = oneLine(cwd); + const head = "from Codex thread " + id + (where ? " @ " + where : "") + (dir ? (where ? ", " : " ") + "cwd " + dir : ""); + const reply = "reply: codex_send({threadId:\"" + id + "\", message:\"...\"})" + (where ? " via MCP on " + where : " via MCP") + " (or CLI: gbot codex send " + id + " \"...\")"; + return "[" + [ + head, + ...details.map(oneLine).filter(Boolean), + reply + ].join("; ") + "]"; + } + function withCodexSender(text, fields) { + const prefix = codexSenderPrefix(fields); + return prefix ? prefix + "\n" + text : text; + } + function envCodexThreadId(env = process.env) { + const id = env.CODEX_THREAD_ID?.trim(); + return id && /^[A-Za-z0-9_.:-]{1,128}$/.test(id) ? id : undefined; + } + __webpack_require__.d(__webpack_exports__, { + Xt: ()=>withCodexSender + }); + }, "./src/core/store.js" (__unused_rspack___webpack_module__, __unused_rspack___webpack_exports__, __webpack_require__) { var node_crypto__rspack_import_0 = __webpack_require__("node:crypto"); var node_fs__rspack_import_1 = __webpack_require__("node:fs"); @@ -28895,7 +29255,7 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } function normalizeText(value) { return toSafeText(value).replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(? 0 && !sourceEntryId(page[page.length - 1]); return { @@ -28969,8 +29329,8 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } } __webpack_require__.d(__webpack_exports__, { N3: ()=>transcriptDelta, - u0: ()=>entryText, - xw: ()=>transcriptEntries + u0: ()=>entryText1, + xw: ()=>transcriptEntries1 }); }, "./src/core/url-policy.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { @@ -29723,20 +30083,66 @@ const routes = Object.freeze({ "annotations": { "readOnlyHint": true }, - "description": "Discover a bounded page of Codex daemon threads. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.", + "description": "Discover Codex daemon threads on the user's registered machine (local socket, not the Grok Bot box; from the box run gbot there through Shell with a machineId after codex app-server daemon start or bootstrap). Newest activity first by default (sort:\"updated\"), so old-but-active threads surface; sort:\"created\" restores creation order. Find one thread with query (case-insensitive substring of name/title, preview or id, so an id prefix works) - it scans every page, not just the first 100. Narrow with activeWithin (\"30m\", \"12h\", \"7d\", \"2w\") or since (ISO/epoch seconds), cwd, modelProvider, sourceKind, archived. limit is the page size (1-200); pass nextCursor back as cursor for more.", "excludeClients": [ "codex" ], "inputJsonSchema": { "additionalProperties": false, "properties": { + "activeWithin": { + "description": "Only threads updated within this long: 90s, 30m, 12h, 7d, 2w.", + "type": "string" + }, + "archived": { + "description": "true = archived threads only.", + "type": "boolean" + }, "cursor": { "description": "Opaque nextCursor from a previous page.", "type": "string" }, + "cwd": { + "description": "Exact session working directory.", + "type": "string" + }, "limit": { - "description": "Maximum threads in this page: 1-200. Pass modelProviders:[] internally so every provider is included; use cursor/nextCursor to page.", + "description": "Maximum threads in this page: 1-200 (default 20). Every provider is included; use cursor/nextCursor to page.", "type": "number" + }, + "modelProvider": { + "description": "Any modelProvider id; omit for all.", + "type": "string" + }, + "order": { + "default": "desc", + "enum": [ + "desc", + "asc" + ], + "type": "string" + }, + "query": { + "description": "Case-insensitive substring of thread name/title, preview or id (id prefix works). Scans all pages.", + "type": "string" + }, + "since": { + "description": "Only threads updated at or after this ISO date/time or epoch seconds.", + "type": "string" + }, + "sort": { + "default": "updated", + "description": "updated = last activity (default), created = creation time, recency = daemon recency order.", + "enum": [ + "updated", + "created", + "recency" + ], + "type": "string" + }, + "sourceKind": { + "description": "Any app-server source kind (cli, vscode, exec, appServer, subAgent...); omit for interactive sources.", + "type": "string" } }, "required": [], diff --git a/artifact/mcp/mcp-grok-bot-b8c2461e.mjs b/artifact/mcp/mcp-grok-bot-b8c2461e.mjs index 592629d..e476f9d 100644 --- a/artifact/mcp/mcp-grok-bot-b8c2461e.mjs +++ b/artifact/mcp/mcp-grok-bot-b8c2461e.mjs @@ -10364,6 +10364,7 @@ var __webpack_modules__ = { var _codex_bridge_js__rspack_import_0 = __webpack_require__("./src/core/codex-bridge.js"); var _contract_js__rspack_import_1 = __webpack_require__("./src/core/codex/contract.js"); var _conversation_js__rspack_import_2 = __webpack_require__("./src/core/codex/conversation.js"); + var _format_js__rspack_import_6 = __webpack_require__("./src/core/format.js"); var _thread_id_js__rspack_import_4 = __webpack_require__("./src/core/codex/thread-id.js"); const bareId = zod__rspack_import_3.YjP().regex(/^[A-Za-z0-9_.:-]{1,128}$/); const id = zod__rspack_import_3.YjP().min(1).max(160).transform((value, ctx)=>{ @@ -10424,7 +10425,23 @@ var __webpack_modules__ = { }).strict(); const threadsSchema = zod__rspack_import_3.Ikc({ limit: zod__rspack_import_3.aig().int().min(1).max(200).default(20), - cursor: zod__rspack_import_3.YjP().min(1).max(4096).optional() + cursor: zod__rspack_import_3.YjP().min(1).max(4096).optional(), + sort: zod__rspack_import_3.k5n([ + 'updated', + 'created', + 'recency' + ]).default('updated'), + order: zod__rspack_import_3.k5n([ + 'desc', + 'asc' + ]).default('desc'), + query: zod__rspack_import_3.YjP().trim().min(1).max(256).optional(), + activeWithin: zod__rspack_import_3.YjP().trim().regex(/^\d+(?:\.\d+)?\s*[smhdw]$/i, 'use a duration like 30m, 12h, 7d or 2w').optional(), + since: zod__rspack_import_3.YjP().trim().min(1).max(64).optional(), + cwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), + modelProvider: zod__rspack_import_3.YjP().min(1).max(256).optional(), + archived: zod__rspack_import_3.zMY().optional(), + sourceKind: zod__rspack_import_3.YjP().min(1).max(64).optional() }).strict(); const resultSchema = zod__rspack_import_3.Ikc({ exitCode: zod__rspack_import_3.aig().int().min(0).max(1), @@ -10584,8 +10601,16 @@ var __webpack_modules__ = { } async function threadsOperation(input) { try { + const { sourceKind, ...rest } = input; return { - ...await (0, _codex_bridge_js__rspack_import_0.X$)(input), + ...await (0, _codex_bridge_js__rspack_import_0.X$)({ + ...rest, + ...sourceKind ? { + sourceKinds: [ + sourceKind + ] + } : {} + }), exitCode: 0 }; } catch (error) { @@ -10599,7 +10624,10 @@ var __webpack_modules__ = { if (result.delivery === 'accepted') return `Started turn ${result.turnId} (${result.turnStatus}) on Codex thread ${result.threadId}; message ${result.messageId}`; if (result.delivery) return `Codex delivery ${result.delivery} on thread ${result.threadId}`; if (result.reason) return `Codex observation: ${result.reason}`; - if (Array.isArray(result.threads)) return `${result.threads.length} Codex threads`; + if (Array.isArray(result.threads)) { + const rows = result.threads.map((t)=>(0, _format_js__rspack_import_6.nz)(t)).join('\n\n'); + return `${result.threads.length} Codex threads (sort ${String(result.sort ?? 'updated')} ${String(result.order ?? 'desc')})${result.nextCursor ? `; more: pass cursor ${JSON.stringify(result.nextCursor)}` : ''}${rows ? `\n\n${rows}` : ''}`; + } return String(result.error ?? 'Codex observation complete'); } __webpack_require__.d(__webpack_exports__, { @@ -10639,68 +10667,69 @@ var __webpack_modules__ = { }); }, "./src/core/relay/routes.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) { - var _agent_bundle_runtime__rspack_import_4 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/40.js"); - var zod__rspack_import_3 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); + var _agent_bundle_runtime__rspack_import_5 = __webpack_require__("./node_modules/@agent-bundle/runtime/dist/40.js"); + var zod__rspack_import_4 = __webpack_require__("./node_modules/zod/v4/classic/schemas.js"); var _managed_js__rspack_import_0 = __webpack_require__("./src/core/relay/managed.js"); var _gbot_js__rspack_import_1 = __webpack_require__("./src/gbot.ts"); var _codex_bridge_js__rspack_import_2 = __webpack_require__("./src/core/codex-bridge.js"); - const id = zod__rspack_import_3.YjP().min(1).max(128); + var _sender_prefix_js__rspack_import_3 = __webpack_require__("./src/core/sender-prefix.js"); + const id = zod__rspack_import_4.YjP().min(1).max(128); const routeFields = { codexThreadId: id.optional(), - expectedCwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), + expectedCwd: zod__rspack_import_4.YjP().min(1).max(4096).optional(), + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), requestId: id.optional() }; - const grokSendSchema = zod__rspack_import_3.Ikc({ - target: zod__rspack_import_3.YjP().min(1), - message: zod__rspack_import_3.YjP().min(1), - replyMode: zod__rspack_import_3.k5n([ + const grokSendSchema = zod__rspack_import_4.Ikc({ + target: zod__rspack_import_4.YjP().min(1), + message: zod__rspack_import_4.YjP().min(1), + replyMode: zod__rspack_import_4.k5n([ "auto", "manual" ]).optional(), - hop: zod__rspack_import_3.aig().int().min(0).optional(), + hop: zod__rspack_import_4.aig().int().min(0).optional(), correlationId: id.optional(), ...routeFields }).strict(); - const bridgeStartSchema = zod__rspack_import_3.Ikc({ - grokTarget: zod__rspack_import_3.YjP().min(1), + const bridgeStartSchema = zod__rspack_import_4.Ikc({ + grokTarget: zod__rspack_import_4.YjP().min(1), codexThreadId: id.optional(), - expectedCwd: zod__rspack_import_3.YjP().min(1).max(4096).optional(), - busyPolicy: zod__rspack_import_3.k5n([ + expectedCwd: zod__rspack_import_4.YjP().min(1).max(4096).optional(), + busyPolicy: zod__rspack_import_4.k5n([ "steer", "reject" ]).optional(), requestId: id.optional() }).strict(); - const bridgeStatusSchema = zod__rspack_import_3.Ikc({ - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - limit: zod__rspack_import_3.aig().int().min(1).max(100).optional() + const bridgeStatusSchema = zod__rspack_import_4.Ikc({ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + limit: zod__rspack_import_4.aig().int().min(1).max(100).optional() }).strict(); - const bridgeStopSchema = zod__rspack_import_3.Ikc({ - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - all: zod__rspack_import_3.zMY().optional(), - worker: zod__rspack_import_3.zMY().optional() + const bridgeStopSchema = zod__rspack_import_4.Ikc({ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + all: zod__rspack_import_4.zMY().optional(), + worker: zod__rspack_import_4.zMY().optional() }).strict().refine((x)=>!!x.bindingId || x.all === true || x.worker === true, "Specify bindingId, all or worker"); - const respondSchema = zod__rspack_import_3.Ikc({ - interactionId: zod__rspack_import_3.YjP().min(1).max(512), + const respondSchema = zod__rspack_import_4.Ikc({ + interactionId: zod__rspack_import_4.YjP().min(1).max(512), generation: id, threadId: id, turnId: id, - bindingId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - exchangeId: zod__rspack_import_3.YjP().min(1).max(512).optional(), - decision: zod__rspack_import_3.k5n([ + bindingId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + exchangeId: zod__rspack_import_4.YjP().min(1).max(512).optional(), + decision: zod__rspack_import_4.k5n([ "accept", "decline", "cancel" ]).optional(), - answersJson: zod__rspack_import_3.YjP().min(2).max(65536).optional() + answersJson: zod__rspack_import_4.YjP().min(2).max(65536).optional() }).strict().refine((x)=>!!x.bindingId || !!x.exchangeId, "Binding or exchange scope required").refine((x)=>!!x.decision !== !!x.answersJson, "Supply decision or answersJson"); - const answersSchema = zod__rspack_import_3.g1P(zod__rspack_import_3.YjP().min(1).max(128), zod__rspack_import_3.Ikc({ - answers: zod__rspack_import_3.YOg(zod__rspack_import_3.YjP().max(8192)).max(20) + const answersSchema = zod__rspack_import_4.g1P(zod__rspack_import_4.YjP().min(1).max(128), zod__rspack_import_4.Ikc({ + answers: zod__rspack_import_4.YOg(zod__rspack_import_4.YjP().max(8192)).max(20) }).strict()); - const relayResultSchema = zod__rspack_import_3.g1P(zod__rspack_import_3.YjP(), zod__rspack_import_3.Pq9()); + const relayResultSchema = zod__rspack_import_4.g1P(zod__rspack_import_4.YjP(), zod__rspack_import_4.Pq9()); function nativeCodexThread(context) { - return context.host.state === "available" && (0, _agent_bundle_runtime__rspack_import_4.bg)(context.host.value.name) === "codex" && context.lineage.state === "available" && context.lineage.source === "native" && context.lineage.value.resolution === "native" ? context.lineage.value.conversation : undefined; + return context.host.state === "available" && (0, _agent_bundle_runtime__rspack_import_5.bg)(context.host.value.name) === "codex" && context.lineage.state === "available" && context.lineage.source === "native" && context.lineage.value.resolution === "native" ? context.lineage.value.conversation : undefined; } function options(context) { return { @@ -10733,7 +10762,11 @@ var __webpack_modules__ = { } : {} }, options(context))); if (input.replyMode === "auto") throw Error("Automatic reply delivery requires a native Codex source, codexThreadId or bindingId"); - const message = input.hop !== undefined || input.correlationId !== undefined ? (0, _codex_bridge_js__rspack_import_2.Mr)(input.message, (0, _codex_bridge_js__rspack_import_2.nq)(input)) : input.message; + const stamped = input.hop !== undefined || input.correlationId !== undefined ? (0, _codex_bridge_js__rspack_import_2.Mr)(input.message, (0, _codex_bridge_js__rspack_import_2.nq)(input)) : input.message; + const message = (0, _sender_prefix_js__rspack_import_3.Xt)(stamped, { + threadId: route.codexThreadId, + cwd: route.expectedCwd + }); const sent = await (0, _gbot_js__rspack_import_1.yF)(async ()=>(0, _gbot_js__rspack_import_1.LV)(await (0, _gbot_js__rspack_import_1.Vq)(), input.target, message)); return { result: sent.result, @@ -10880,7 +10913,7 @@ var __webpack_modules__ = { }; }; const metaLength = (entry)=>entry.id.length + entry.kind.length + (entry.role?.length ?? 0); - const transcriptEntries = (transcript)=>{ + const transcriptEntries1 = (transcript)=>{ const rows = (0, _core_transcript_js__rspack_import_2.xw)(transcript); let remaining = TRANSCRIPT_TOTAL_MAX; return rows.map((raw)=>{ @@ -10902,7 +10935,7 @@ var __webpack_modules__ = { }, { Oo: entrySchema, rW: summarizeTarget, - xw: transcriptEntries, + xw: transcriptEntries1, yF: withRedactedErrors }); }, @@ -11639,7 +11672,7 @@ var __webpack_modules__ = { excludeClients: [ 'codex' ], - description: 'Discover a bounded page of Codex daemon threads. Runs on the user\'s registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.', + description: 'Discover Codex daemon threads on the user\'s registered machine (local socket, not the Grok Bot box; from the box run gbot there through Shell with a machineId after codex app-server daemon start or bootstrap). Newest activity first by default (sort:"updated"), so old-but-active threads surface; sort:"created" restores creation order. Find one thread with query (case-insensitive substring of name/title, preview or id, so an id prefix works) - it scans every page, not just the first 100. Narrow with activeWithin ("30m", "12h", "7d", "2w") or since (ISO/epoch seconds), cwd, modelProvider, sourceKind, archived. limit is the page size (1-200); pass nextCursor back as cursor for more.', title: 'Codex threads', annotations: { readOnlyHint: true @@ -11653,13 +11686,59 @@ var __webpack_modules__ = { type: 'object', additionalProperties: false, properties: { - "limit": { - "type": "number", - "description": "Maximum threads in this page: 1-200. Pass modelProviders:[] internally so every provider is included; use cursor/nextCursor to page." + limit: { + type: 'number', + description: 'Maximum threads in this page: 1-200 (default 20). Every provider is included; use cursor/nextCursor to page.' }, - "cursor": { - "type": "string", - "description": "Opaque nextCursor from a previous page." + cursor: { + type: 'string', + description: 'Opaque nextCursor from a previous page.' + }, + sort: { + type: 'string', + enum: [ + 'updated', + 'created', + 'recency' + ], + default: 'updated', + description: 'updated = last activity (default), created = creation time, recency = daemon recency order.' + }, + order: { + type: 'string', + enum: [ + 'desc', + 'asc' + ], + default: 'desc' + }, + query: { + type: 'string', + description: 'Case-insensitive substring of thread name/title, preview or id (id prefix works). Scans all pages.' + }, + activeWithin: { + type: 'string', + description: 'Only threads updated within this long: 90s, 30m, 12h, 7d, 2w.' + }, + since: { + type: 'string', + description: 'Only threads updated at or after this ISO date/time or epoch seconds.' + }, + cwd: { + type: 'string', + description: 'Exact session working directory.' + }, + modelProvider: { + type: 'string', + description: 'Any modelProvider id; omit for all.' + }, + sourceKind: { + type: 'string', + description: 'Any app-server source kind (cli, vscode, exec, appServer, subAgent...); omit for interactive sources.' + }, + archived: { + type: 'boolean', + description: 'true = archived threads only.' } }, required: [] @@ -61097,20 +61176,66 @@ var __webpack_modules__ = { "annotations": { "readOnlyHint": true }, - "description": "Discover a bounded page of Codex daemon threads. Runs on the user's registered machine via its local socket, not the Grok Bot box. From the box, use Grok Bot Shell with a machineId to run gbot there after codex app-server daemon start or bootstrap; gbot has no remote transport.", + "description": "Discover Codex daemon threads on the user's registered machine (local socket, not the Grok Bot box; from the box run gbot there through Shell with a machineId after codex app-server daemon start or bootstrap). Newest activity first by default (sort:\"updated\"), so old-but-active threads surface; sort:\"created\" restores creation order. Find one thread with query (case-insensitive substring of name/title, preview or id, so an id prefix works) - it scans every page, not just the first 100. Narrow with activeWithin (\"30m\", \"12h\", \"7d\", \"2w\") or since (ISO/epoch seconds), cwd, modelProvider, sourceKind, archived. limit is the page size (1-200); pass nextCursor back as cursor for more.", "excludeClients": [ "codex" ], "inputJsonSchema": { "additionalProperties": false, "properties": { + "activeWithin": { + "description": "Only threads updated within this long: 90s, 30m, 12h, 7d, 2w.", + "type": "string" + }, + "archived": { + "description": "true = archived threads only.", + "type": "boolean" + }, "cursor": { "description": "Opaque nextCursor from a previous page.", "type": "string" }, + "cwd": { + "description": "Exact session working directory.", + "type": "string" + }, "limit": { - "description": "Maximum threads in this page: 1-200. Pass modelProviders:[] internally so every provider is included; use cursor/nextCursor to page.", + "description": "Maximum threads in this page: 1-200 (default 20). Every provider is included; use cursor/nextCursor to page.", "type": "number" + }, + "modelProvider": { + "description": "Any modelProvider id; omit for all.", + "type": "string" + }, + "order": { + "default": "desc", + "enum": [ + "desc", + "asc" + ], + "type": "string" + }, + "query": { + "description": "Case-insensitive substring of thread name/title, preview or id (id prefix works). Scans all pages.", + "type": "string" + }, + "since": { + "description": "Only threads updated at or after this ISO date/time or epoch seconds.", + "type": "string" + }, + "sort": { + "default": "updated", + "description": "updated = last activity (default), created = creation time, recency = daemon recency order.", + "enum": [ + "updated", + "created", + "recency" + ], + "type": "string" + }, + "sourceKind": { + "description": "Any app-server source kind (cli, vscode, exec, appServer, subAgent...); omit for interactive sources.", + "type": "string" } }, "required": [], @@ -62933,7 +63058,52 @@ var __webpack_modules__ = { }; } const THREAD_LIST_MAX_LIMIT = 200; - async function listCodexThreads({ limit = 20, cursor, modelProviders = [], env = process.env } = {}) { + const THREAD_SORT_KEYS = { + updated: "updated_at", + created: "created_at", + recency: "recency_at" + }; + const GBOT_CURSOR = "gbot1:"; + const DURATION_MS = { + s: 1000, + m: 60000, + h: 3600000, + d: 86400000, + w: 604800000 + }; + const toSeconds = (value)=>value > 1e11 ? value / 1000 : value; + function parseActiveWithin(text) { + const m = /^(\d+(?:\.\d+)?)\s*([smhdw])$/i.exec(String(text).trim()); + if (!m) throw new RangeError("--active-within must look like 30m, 12h, 7d or 2w"); + return Number(m[1]) * DURATION_MS[m[2].toLowerCase()]; + } + function parseSince(value) { + const text = String(value).trim(); + const n = /^\d+(?:\.\d+)?$/.test(text) ? toSeconds(Number(text)) : Date.parse(text) / 1000; + if (!Number.isFinite(n)) throw new RangeError("--since must be an ISO date/time or epoch seconds"); + return n; + } + function encodeThreadCursor(state) { + return GBOT_CURSOR + Buffer.from(JSON.stringify(state)).toString("base64url"); + } + function decodeThreadCursor(cursor) { + if (cursor === undefined) return { + skip: 0 + }; + if (!cursor.startsWith(GBOT_CURSOR)) return { + c: cursor, + skip: 0 + }; + try { + const v = JSON.parse(Buffer.from(cursor.slice(GBOT_CURSOR.length), "base64url").toString("utf8")); + if (isObject(v) && Number.isInteger(v.skip) && v.skip >= 0 && (v.c === undefined || typeof v.c === "string")) return { + c: v.c, + skip: v.skip + }; + } catch {} + throw new RangeError("--cursor is not a valid thread cursor"); + } + async function listCodexThreads({ limit = 20, cursor, modelProviders = [], modelProvider, sort = "updated", order: order1 = "desc", query, since, activeWithin, cwd, archived, sourceKinds, now = Date.now(), env = process.env } = {}) { if (!Number.isInteger(limit) || limit < 1 || limit > THREAD_LIST_MAX_LIMIT) { throw new RangeError("--limit must be an integer 1-" + THREAD_LIST_MAX_LIMIT); } @@ -62941,45 +63111,125 @@ var __webpack_modules__ = { if (!Array.isArray(modelProviders) || modelProviders.some((p)=>typeof p !== "string")) { throw new RangeError("modelProviders must be an array of strings (empty = all providers)"); } + if (!Object.hasOwn(THREAD_SORT_KEYS, sort)) throw new RangeError("--sort must be one of: " + Object.keys(THREAD_SORT_KEYS).join(", ")); + if (order1 !== "asc" && order1 !== "desc") throw new RangeError("--order must be asc or desc"); + if (query !== undefined && (typeof query !== "string" || !query.trim())) throw new RangeError("--query must be a non-empty string"); + if (sourceKinds !== undefined && (!Array.isArray(sourceKinds) || sourceKinds.some((k)=>typeof k !== "string" || !k))) { + throw new RangeError("--source-kind must be a non-empty string"); + } + const providers = modelProvider ? [ + ...modelProviders, + modelProvider + ] : modelProviders; + const needle = query?.trim().toLowerCase(); + const cutoffs = []; + if (since !== undefined) cutoffs.push(parseSince(since)); + if (activeWithin !== undefined) cutoffs.push((now - parseActiveWithin(activeWithin)) / 1000); + const cutoff = cutoffs.length ? Math.max(...cutoffs) : undefined; + const clientSide = needle !== undefined || cutoff !== undefined; + const activityOf = (t)=>typeof t.updatedAt === "number" ? toSeconds(t.updatedAt) : typeof t.createdAt === "number" ? toSeconds(t.createdAt) : null; + const keep = (t)=>{ + if (cutoff !== undefined) { + const at = activityOf(t); + if (at === null || at < cutoff) return false; + } + if (needle !== undefined && ![ + t.name, + t.preview, + t.id + ].some((f)=>typeof f === "string" && f.toLowerCase().includes(needle))) return false; + return true; + }; + const pageSize = clientSide ? THREAD_LIST_MAX_LIMIT : limit; + const start = decodeThreadCursor(cursor); const { client } = await openSession(env); try { const baseParams = { - limit, - modelProviders, - ...cursor !== undefined ? { - cursor + limit: pageSize, + modelProviders: providers, + sortKey: THREAD_SORT_KEYS[sort], + ...order1 === "asc" ? { + sortDirection: "asc" + } : {}, + ...cwd ? { + cwd + } : {}, + ...archived === true ? { + archived: true + } : {}, + ...sourceKinds?.length ? { + sourceKinds } : {} }; - let out; - let usedStateDbOnly = true; - try { - out = await client.request("thread/list", { - ...baseParams, - useStateDbOnly: true - }); - } catch (err) { - throw transportError(err); - } - if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); - if (out.data.length === 0 && cursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + const fetchPage = async (pageCursor, useStateDbOnly)=>{ try { - out = await client.request("thread/list", { + return await client.request("thread/list", { ...baseParams, - useStateDbOnly: false + ...pageCursor !== undefined ? { + cursor: pageCursor + } : {}, + useStateDbOnly }); - usedStateDbOnly = false; } catch (err) { throw transportError(err); } + }; + const checkPage = (out)=>{ if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); + if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); + }; + const threads = []; + let usedStateDbOnly = true; + let scanned = 0; + let nextCursor = null; + let pageCursor = start.c; + let skip = start.skip; + for(;;){ + let out = await fetchPage(pageCursor, true); + checkPage(out); + if (out.data.length === 0 && pageCursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + out = await fetchPage(pageCursor, false); + usedStateDbOnly = false; + checkPage(out); + } + const rows = out.data.map(summarizeThread); + scanned += rows.length; + let matches = rows.filter(keep); + const pageSkip = skip; + if (skip) { + matches = matches.slice(skip); + skip = 0; + } + const need = limit - threads.length; + if (matches.length > need) { + threads.push(...matches.slice(0, need)); + nextCursor = encodeThreadCursor({ + ...pageCursor !== undefined ? { + c: pageCursor + } : {}, + skip: pageSkip + need + }); + break; + } + threads.push(...matches); + const more = out.nextCursor || null; + const last = rows[rows.length - 1]; + const pastCutoff = cutoff !== undefined && sort === "updated" && order1 === "desc" && last !== undefined && (activityOf(last) ?? -Infinity) < cutoff; + if (!more || pastCutoff) break; + if (threads.length >= limit) { + nextCursor = more; + break; + } + pageCursor = more; } - if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); - const threads = out.data.map(summarizeThread); return { threads, - nextCursor: out.nextCursor ?? null, + nextCursor, limit, - useStateDbOnly: usedStateDbOnly + useStateDbOnly: usedStateDbOnly, + sort, + order: order1, + scanned }; } finally{ client.close(); @@ -64804,6 +65054,127 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } em: ()=>desktopShimStatus }); }, + "./src/core/format.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { + function stripTerminalControls(text) { + return String(text).replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, "").replace(/\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)/g, "").replace(/\u001b./g, "").replace(/[\u0000-\u001F\u007F-\u009F]/g, ""); + } + function summarize(rec) { + return { + id: rec.id, + name: rec.name, + title: rec.title || undefined, + description: rec.description || undefined, + avatarShape: rec.avatarShape || undefined, + avatarColor: rec.avatarColor || undefined, + ...rec.notifyOnAgentUpdates !== undefined ? { + notifyOnAgentUpdates: rec.notifyOnAgentUpdates + } : {}, + ...rec.hiddenFromSidebar !== undefined ? { + hiddenFromSidebar: rec.hiddenFromSidebar + } : {}, + kind: rec.isGroup ? "group" : "bot", + members: rec.isGroup ? rec.memberIds : undefined + }; + } + function formatRecord(rec, all) { + const kind = rec.isGroup ? "group" : "bot"; + const members = rec.isGroup ? rec.memberIds.map((id)=>{ + const m = all.find((r)=>r.id === id); + return m ? m.name + " (" + id + ")" : id; + }).join(", ") : ""; + const title = rec.title ? " - " + rec.title : ""; + const desc = rec.description ? "\n " + rec.description : ""; + const avatar = rec.avatarShape || rec.avatarColor ? "\n avatar: " + [ + rec.avatarShape, + rec.avatarColor + ].filter(Boolean).join(" ") : ""; + const settings = []; + if (rec.notifyOnAgentUpdates !== undefined) settings.push("notify " + (rec.notifyOnAgentUpdates ? "on" : "off")); + if (rec.hiddenFromSidebar !== undefined) settings.push("hidden " + (rec.hiddenFromSidebar ? "on" : "off")); + const settingsLine = settings.length ? "\n " + settings.join(", ") : ""; + const extra = rec.isGroup ? "\n members (" + rec.memberIds.length + "): " + (members || "(none)") : ""; + return kind + " " + rec.name + title + "\n " + rec.id + desc + avatar + settingsLine + extra; + } + function formatTranscript(out, { full = false } = {}) { + const rec = out.target; + const payload = out.transcript || out.thread || {}; + const entries = transcriptEntries(payload); + const header = (rec.isGroup ? "group" : "bot") + " " + rec.name + "\n " + rec.id; + if (!Array.isArray(entries) || entries.length === 0) { + return header + "\n (no messages)"; + } + const lines = [ + header, + "" + ]; + for (const e of entries){ + const role = e.role || e.kind || e.sender || e.type || "msg"; + const text = entryText(e); + const id = e.id || ""; + lines.push("[" + role + (id ? " " + id : "") + "] " + (full ? text : truncateCliText(text))); + } + return lines.join("\n"); + } + function truncateCliText(text, max = 400) { + if (text.length <= max) return text; + return text.slice(0, max) + "… [+" + (text.length - max) + " chars; --full or --json for complete text]"; + } + function formatCodexStatus(s) { + const lines = [ + "socket: " + s.socketPath + " (" + s.socketState + ")" + ]; + if (s.desktopShimConfigured) lines.push("desktop shim: configured (managed attachment unverified)"); + if (!s.reachable) return lines.concat("reachable: no (" + s.mode + ")", s.message).join("\n"); + if (s.mode !== "daemon") { + return lines.concat("reachable: yes, but unusable (" + s.mode + ")", s.message).join("\n"); + } + lines.push("reachable: yes (daemon)"); + const cli = s.cliVersion ?? (s.cliVersionProbe === "ok" ? "unknown" : "unknown, probe " + s.cliVersionProbe); + lines.push("daemon version: " + (s.daemonVersion ?? "unknown") + " cli version: " + cli + " pinned schema: " + s.pinnedVersion + " (" + s.schema.compatibility + ")"); + lines.push(s.desktopAttached === "private-stdio" ? "desktop attached: private-stdio (Desktop-bundled app-server process observed; managed attachment unverified)" : "desktop attached: unknown (not observable from the socket)"); + if (s.versionMismatch) { + lines.push("warning: daemon and CLI versions differ; `codex app-server daemon restart` picks up the installed CLI"); + } + return lines.join("\n"); + } + function formatCodexQueue({ threadId, queued }) { + if (queued.length === 0) return "No queued submissions on Codex thread " + threadId + "."; + return queued.map((q)=>q.id + " " + (q.clientUserMessageId ?? "") + "\n " + stripTerminalControls(q.text).replace(/\s+/g, " ").slice(0, 200)).join("\n\n"); + } + function formatCodexThread(t) { + const title = t.name ? " - " + stripTerminalControls(t.name) : ""; + const preview = t.preview ? "\n " + stripTerminalControls(String(t.preview).replace(/\s+/g, " ")).slice(0, 200) : ""; + const at = typeof t.updatedAt === "number" && Number.isFinite(t.updatedAt) ? new Date(t.updatedAt > 1e11 ? t.updatedAt : t.updatedAt * 1000).toISOString().replace(/\.\d{3}Z$/, "Z") : ""; + return stripTerminalControls(t.id) + " " + stripTerminalControls(t.status) + title + "\n " + stripTerminalControls(t.cwd ?? "") + (at ? " (updated " + at + ")" : "") + preview; + } + function shellQuote(value) { + return "'" + String(value).replace(/'/g, "'\\''") + "'"; + } + function formatDesktopShimStatus(s) { + const mark = (ok)=>ok ? "yes" : "no"; + const cliLine = s.platform === "darwin" ? "CODEX_CLI_PATH: GUI domain " + (s.guiCliPath ?? "(unset)") + " / this shell " + (s.cliPath ?? "(unset)") + (s.wrapperPointsAtShim ? " (Desktop-facing value points at shim)" : "") : "CODEX_CLI_PATH: " + (s.cliPath ?? "(unset)") + (s.wrapperPointsAtShim ? " (points at shim)" : ""); + const lines = [ + "wrapper: " + s.wrapperPath + " (" + (s.wrapperExecutable ? "executable" : s.wrapperPresent ? "present, not executable" : "absent") + ")", + "bridge: " + s.bridgePath + " (" + mark(s.bridgePresent) + ")", + "login env: " + s.envScriptPath + " (" + mark(s.envScriptPresent) + ")", + s.platform === "darwin" ? "LaunchAgent: " + s.plistPath + " (" + mark(s.plistPresent) + ")" : "LaunchAgent: n/a (macOS-only)", + cliLine, + "daemon socket: " + s.socketPath + " (" + s.socketState + ", from " + (s.socketSource ?? "CODEX_HOME") + ")" + ]; + if (!s.installed) { + lines.push("shim: not installed — run `gbot codex desktop-shim install` (Desktop keeps stock behavior until then)"); + } else if (!s.wrapperPointsAtShim) { + lines.push(s.platform === "darwin" ? "shim: installed but CODEX_CLI_PATH does not point at it — reinstall or relaunch ChatGPT.app after login" : "shim: installed but CODEX_CLI_PATH does not point at it — export CODEX_CLI_PATH=" + shellQuote(s.wrapperPath)); + } else { + lines.push("shim: active — Desktop app-server spawns bridge onto the managed daemon"); + } + for (const warning of s.warnings ?? [])lines.push("warning: " + String(warning)); + return lines.join("\n"); + } + __webpack_require__.d(__webpack_exports__, { + nz: ()=>formatCodexThread + }); + }, "./src/core/gateway.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { var node_crypto__rspack_import_0 = __webpack_require__("node:crypto"); var _headers_js__rspack_import_5 = __webpack_require__("./src/core/headers.js"); @@ -65730,6 +66101,41 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } br: digest }); }, + "./src/core/sender-prefix.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { + var node_os__rspack_import_0 = __webpack_require__("node:os"); + const oneLine = (value)=>String(value ?? "").replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/[\]]/g, ")").trim(); + function machineName(env = process.env) { + try { + return oneLine(env.GROK_BOT_MACHINE_NAME || (0, node_os__rspack_import_0.hostname)()); + } catch { + return ""; + } + } + function codexSenderPrefix({ threadId, machine, cwd, details = [], env = process.env } = {}) { + const id = oneLine(threadId); + if (!id) return ""; + const where = oneLine(machine ?? machineName(env)); + const dir = oneLine(cwd); + const head = "from Codex thread " + id + (where ? " @ " + where : "") + (dir ? (where ? ", " : " ") + "cwd " + dir : ""); + const reply = "reply: codex_send({threadId:\"" + id + "\", message:\"...\"})" + (where ? " via MCP on " + where : " via MCP") + " (or CLI: gbot codex send " + id + " \"...\")"; + return "[" + [ + head, + ...details.map(oneLine).filter(Boolean), + reply + ].join("; ") + "]"; + } + function withCodexSender(text, fields) { + const prefix = codexSenderPrefix(fields); + return prefix ? prefix + "\n" + text : text; + } + function envCodexThreadId(env = process.env) { + const id = env.CODEX_THREAD_ID?.trim(); + return id && /^[A-Za-z0-9_.:-]{1,128}$/.test(id) ? id : undefined; + } + __webpack_require__.d(__webpack_exports__, { + Xt: ()=>withCodexSender + }); + }, "./src/core/store.js" (__unused_rspack___webpack_module__, __unused_rspack___webpack_exports__, __webpack_require__) { var node_crypto__rspack_import_0 = __webpack_require__("node:crypto"); var node_fs__rspack_import_1 = __webpack_require__("node:fs"); @@ -66064,7 +66470,7 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } function normalizeText(value) { return toSafeText(value).replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(? 0 && !sourceEntryId(page[page.length - 1]); return { @@ -66138,8 +66544,8 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } } __webpack_require__.d(__webpack_exports__, { N3: ()=>transcriptDelta, - u0: ()=>entryText, - xw: ()=>transcriptEntries + u0: ()=>entryText1, + xw: ()=>transcriptEntries1 }); }, "./src/core/url-policy.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { diff --git a/artifact/scripts/gbot-relay.mjs b/artifact/scripts/gbot-relay.mjs index b93ab54..4ddb169 100644 --- a/artifact/scripts/gbot-relay.mjs +++ b/artifact/scripts/gbot-relay.mjs @@ -23045,7 +23045,52 @@ var __webpack_modules__ = { }; } const THREAD_LIST_MAX_LIMIT = 200; - async function listCodexThreads({ limit = 20, cursor, modelProviders = [], env = process.env } = {}) { + const THREAD_SORT_KEYS = null && { + updated: "updated_at", + created: "created_at", + recency: "recency_at" + }; + const GBOT_CURSOR = "gbot1:"; + const DURATION_MS = null && { + s: 1000, + m: 60000, + h: 3600000, + d: 86400000, + w: 604800000 + }; + const toSeconds = (value)=>value > 1e11 ? value / 1000 : value; + function parseActiveWithin(text) { + const m = /^(\d+(?:\.\d+)?)\s*([smhdw])$/i.exec(String(text).trim()); + if (!m) throw new RangeError("--active-within must look like 30m, 12h, 7d or 2w"); + return Number(m[1]) * DURATION_MS[m[2].toLowerCase()]; + } + function parseSince(value) { + const text = String(value).trim(); + const n = /^\d+(?:\.\d+)?$/.test(text) ? toSeconds(Number(text)) : Date.parse(text) / 1000; + if (!Number.isFinite(n)) throw new RangeError("--since must be an ISO date/time or epoch seconds"); + return n; + } + function encodeThreadCursor(state) { + return GBOT_CURSOR + Buffer.from(JSON.stringify(state)).toString("base64url"); + } + function decodeThreadCursor(cursor) { + if (cursor === undefined) return { + skip: 0 + }; + if (!cursor.startsWith(GBOT_CURSOR)) return { + c: cursor, + skip: 0 + }; + try { + const v = JSON.parse(Buffer.from(cursor.slice(GBOT_CURSOR.length), "base64url").toString("utf8")); + if (isObject(v) && Number.isInteger(v.skip) && v.skip >= 0 && (v.c === undefined || typeof v.c === "string")) return { + c: v.c, + skip: v.skip + }; + } catch {} + throw new RangeError("--cursor is not a valid thread cursor"); + } + async function listCodexThreads({ limit = 20, cursor, modelProviders = [], modelProvider, sort = "updated", order: order1 = "desc", query, since, activeWithin, cwd, archived, sourceKinds, now = Date.now(), env = process.env } = {}) { if (!Number.isInteger(limit) || limit < 1 || limit > THREAD_LIST_MAX_LIMIT) { throw new RangeError("--limit must be an integer 1-" + THREAD_LIST_MAX_LIMIT); } @@ -23053,45 +23098,125 @@ var __webpack_modules__ = { if (!Array.isArray(modelProviders) || modelProviders.some((p)=>typeof p !== "string")) { throw new RangeError("modelProviders must be an array of strings (empty = all providers)"); } + if (!Object.hasOwn(THREAD_SORT_KEYS, sort)) throw new RangeError("--sort must be one of: " + Object.keys(THREAD_SORT_KEYS).join(", ")); + if (order1 !== "asc" && order1 !== "desc") throw new RangeError("--order must be asc or desc"); + if (query !== undefined && (typeof query !== "string" || !query.trim())) throw new RangeError("--query must be a non-empty string"); + if (sourceKinds !== undefined && (!Array.isArray(sourceKinds) || sourceKinds.some((k)=>typeof k !== "string" || !k))) { + throw new RangeError("--source-kind must be a non-empty string"); + } + const providers = modelProvider ? [ + ...modelProviders, + modelProvider + ] : modelProviders; + const needle = query?.trim().toLowerCase(); + const cutoffs = []; + if (since !== undefined) cutoffs.push(parseSince(since)); + if (activeWithin !== undefined) cutoffs.push((now - parseActiveWithin(activeWithin)) / 1000); + const cutoff = cutoffs.length ? Math.max(...cutoffs) : undefined; + const clientSide = needle !== undefined || cutoff !== undefined; + const activityOf = (t)=>typeof t.updatedAt === "number" ? toSeconds(t.updatedAt) : typeof t.createdAt === "number" ? toSeconds(t.createdAt) : null; + const keep = (t)=>{ + if (cutoff !== undefined) { + const at = activityOf(t); + if (at === null || at < cutoff) return false; + } + if (needle !== undefined && ![ + t.name, + t.preview, + t.id + ].some((f)=>typeof f === "string" && f.toLowerCase().includes(needle))) return false; + return true; + }; + const pageSize = clientSide ? THREAD_LIST_MAX_LIMIT : limit; + const start = decodeThreadCursor(cursor); const { client } = await openSession(env); try { const baseParams = { - limit, - modelProviders, - ...cursor !== undefined ? { - cursor + limit: pageSize, + modelProviders: providers, + sortKey: THREAD_SORT_KEYS[sort], + ...order1 === "asc" ? { + sortDirection: "asc" + } : {}, + ...cwd ? { + cwd + } : {}, + ...archived === true ? { + archived: true + } : {}, + ...sourceKinds?.length ? { + sourceKinds } : {} }; - let out; - let usedStateDbOnly = true; - try { - out = await client.request("thread/list", { - ...baseParams, - useStateDbOnly: true - }); - } catch (err) { - throw transportError(err); - } - if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); - if (out.data.length === 0 && cursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + const fetchPage = async (pageCursor, useStateDbOnly)=>{ try { - out = await client.request("thread/list", { + return await client.request("thread/list", { ...baseParams, - useStateDbOnly: false + ...pageCursor !== undefined ? { + cursor: pageCursor + } : {}, + useStateDbOnly }); - usedStateDbOnly = false; } catch (err) { throw transportError(err); } + }; + const checkPage = (out)=>{ if (!isObject(out) || !Array.isArray(out.data)) throw new CodexProtocolError("thread/list", "missing `data` array"); + if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); + }; + const threads = []; + let usedStateDbOnly = true; + let scanned = 0; + let nextCursor = null; + let pageCursor = start.c; + let skip = start.skip; + for(;;){ + let out = await fetchPage(pageCursor, true); + checkPage(out); + if (out.data.length === 0 && pageCursor === undefined && (out.nextCursor == null || out.nextCursor === "")) { + out = await fetchPage(pageCursor, false); + usedStateDbOnly = false; + checkPage(out); + } + const rows = out.data.map(summarizeThread); + scanned += rows.length; + let matches = rows.filter(keep); + const pageSkip = skip; + if (skip) { + matches = matches.slice(skip); + skip = 0; + } + const need = limit - threads.length; + if (matches.length > need) { + threads.push(...matches.slice(0, need)); + nextCursor = encodeThreadCursor({ + ...pageCursor !== undefined ? { + c: pageCursor + } : {}, + skip: pageSkip + need + }); + break; + } + threads.push(...matches); + const more = out.nextCursor || null; + const last = rows[rows.length - 1]; + const pastCutoff = cutoff !== undefined && sort === "updated" && order1 === "desc" && last !== undefined && (activityOf(last) ?? -Infinity) < cutoff; + if (!more || pastCutoff) break; + if (threads.length >= limit) { + nextCursor = more; + break; + } + pageCursor = more; } - if (out.nextCursor != null && typeof out.nextCursor !== "string") throw new CodexProtocolError("thread/list", "`nextCursor` is not a string"); - const threads = out.data.map(summarizeThread); return { threads, - nextCursor: out.nextCursor ?? null, + nextCursor, limit, - useStateDbOnly: usedStateDbOnly + useStateDbOnly: usedStateDbOnly, + sort, + order: order1, + scanned }; } finally{ client.close(); @@ -25793,12 +25918,13 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } }); }, "./src/core/relay/completion.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { - var _records_js__rspack_import_0 = __webpack_require__("./src/core/relay/records.js"); - function createCompletion({ state, codex, update, newRecord, runnable }) { + var _sender_prefix_js__rspack_import_0 = __webpack_require__("./src/core/sender-prefix.js"); + var _records_js__rspack_import_1 = __webpack_require__("./src/core/relay/records.js"); + function createCompletion({ env = process.env, state, codex, update, newRecord, runnable }) { let offset = 0; async function completions() { const groups = new Map(); - for (const r of (0, _records_js__rspack_import_0.V0)(state.read()))if (r.kind === "codex" && r.submission === "accepted" && r.turnId && !(0, _records_js__rspack_import_0.Fo)(r) && ![ + for (const r of (0, _records_js__rspack_import_1.V0)(state.read()))if (r.kind === "codex" && r.submission === "accepted" && r.turnId && !(0, _records_js__rspack_import_1.Fo)(r) && ![ "capacity", "hop-limit" ].includes(r.reason) && runnable(r)) { @@ -25850,7 +25976,7 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } const changes = []; let returnId = null; if (first.returnToGrok) { - returnId = "return:" + (0, _records_js__rspack_import_0.tW)([ + returnId = "return:" + (0, _records_js__rspack_import_1.tW)([ first.targetId, first.threadId, first.turnId @@ -25865,7 +25991,16 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } } const sources = group.flatMap((r)=>r.sourceIds), suffix = result.reply.truncated ? "\n[Output truncated]" : ""; let output = result.reply.text || `Codex turn ${execution} with no final text.`; - const prefix = `[Codex ${first.threadId}; turn ${first.turnId}; status ${execution}; sources ${sources.slice(0, 8).map((id)=>id.slice(0, 128)).join(", ")}${sources.length > 8 ? " (additional source IDs retained in relay state)" : ""}]\n`; + const prefix = (0, _sender_prefix_js__rspack_import_0.xA)({ + threadId: first.threadId, + cwd: first.expectedCwd, + env, + details: [ + `turn ${first.turnId}`, + `status ${execution}`, + `sources ${sources.slice(0, 8).map((id)=>id.slice(0, 128)).join(", ")}${sources.length > 8 ? " (additional source IDs retained in relay state)" : ""}` + ] + }) + "\n"; const budget = 65536 - Buffer.byteLength(prefix + suffix) - 32; let truncated = false; while(Buffer.byteLength(output) > budget){ @@ -25879,10 +26014,10 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } hop: first.hop + 1, maxHops: first.maxHops }); - changes.push((0, _records_js__rspack_import_0.op)("records", outgoing)); + changes.push((0, _records_js__rspack_import_1.op)("records", outgoing)); } } - for (const r of group)changes.push((0, _records_js__rspack_import_0.op)("records", { + for (const r of group)changes.push((0, _records_js__rspack_import_1.op)("records", { ...r, execution, reason: null, @@ -25972,13 +26107,14 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } var _codex_js__rspack_import_4 = __webpack_require__("./src/core/relay/codex.js"); var _records_js__rspack_import_5 = __webpack_require__("./src/core/relay/records.js"); var _intake_js__rspack_import_6 = __webpack_require__("./src/core/relay/intake.js"); - var _completion_js__rspack_import_7 = __webpack_require__("./src/core/relay/completion.js"); - var _gateway_js__rspack_import_8 = __webpack_require__("./src/core/gateway.js"); + var _sender_prefix_js__rspack_import_7 = __webpack_require__("./src/core/sender-prefix.js"); + var _completion_js__rspack_import_8 = __webpack_require__("./src/core/relay/completion.js"); + var _gateway_js__rspack_import_9 = __webpack_require__("./src/core/gateway.js"); function createGateway() { return { - resolve: async (ref)=>(0, _gateway_js__rspack_import_8.qE)(await (0, _gateway_js__rspack_import_8.Vq)(), ref), - tail: async (id)=>(0, _gateway_js__rspack_import_8.bA)(await (0, _gateway_js__rspack_import_8.Vq)(), id, 200), - send: async (id, text, extra)=>(0, _gateway_js__rspack_import_8.LV)(await (0, _gateway_js__rspack_import_8.Vq)({ + resolve: async (ref)=>(0, _gateway_js__rspack_import_9.qE)(await (0, _gateway_js__rspack_import_9.Vq)(), ref), + tail: async (id)=>(0, _gateway_js__rspack_import_9.bA)(await (0, _gateway_js__rspack_import_9.Vq)(), id, 200), + send: async (id, text, extra)=>(0, _gateway_js__rspack_import_9.LV)(await (0, _gateway_js__rspack_import_9.Vq)({ signal: extra.signal }), id, text, extra) }; @@ -26031,7 +26167,8 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } newRecord, stoppedBindings }); - const completions = (0, _completion_js__rspack_import_7.P)({ + const completions = (0, _completion_js__rspack_import_8.P)({ + env, state, codex, update, @@ -26175,9 +26312,14 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } if (old.fingerprint !== fingerprint) throw new Error("Idempotency conflict"); return (0, _records_js__rspack_import_5.R9)(old); } - const text = (0, _records_js__rspack_import_5.Lo)(input.message); + const raw = (0, _records_js__rspack_import_5.Lo)(input.message); envelope(input); const r = await route(input); + const text = kind === "grok-request" ? (0, _records_js__rspack_import_5.Lo)((0, _sender_prefix_js__rspack_import_7.Xt)(raw, { + threadId: r.threadId, + cwd: r.expectedCwd, + env + })) : raw; await baseline(r.targetId); if (state.read().targets[r.targetId].state !== "running") throw new Error("Target coverage is paused"); const record = newRecord(kind, id, r, text, { @@ -27377,6 +27519,42 @@ ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } F: ()=>runRelayWorker }); }, + "./src/core/sender-prefix.js" (__unused_rspack___webpack_module__, __webpack_exports__, __webpack_require__) { + var node_os__rspack_import_0 = __webpack_require__("node:os"); + const oneLine = (value)=>String(value ?? "").replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/[\]]/g, ")").trim(); + function machineName(env = process.env) { + try { + return oneLine(env.GROK_BOT_MACHINE_NAME || (0, node_os__rspack_import_0.hostname)()); + } catch { + return ""; + } + } + function codexSenderPrefix({ threadId, machine, cwd, details = [], env = process.env } = {}) { + const id = oneLine(threadId); + if (!id) return ""; + const where = oneLine(machine ?? machineName(env)); + const dir = oneLine(cwd); + const head = "from Codex thread " + id + (where ? " @ " + where : "") + (dir ? (where ? ", " : " ") + "cwd " + dir : ""); + const reply = "reply: codex_send({threadId:\"" + id + "\", message:\"...\"})" + (where ? " via MCP on " + where : " via MCP") + " (or CLI: gbot codex send " + id + " \"...\")"; + return "[" + [ + head, + ...details.map(oneLine).filter(Boolean), + reply + ].join("; ") + "]"; + } + function withCodexSender(text, fields) { + const prefix = codexSenderPrefix(fields); + return prefix ? prefix + "\n" + text : text; + } + function envCodexThreadId(env = process.env) { + const id = env.CODEX_THREAD_ID?.trim(); + return id && /^[A-Za-z0-9_.:-]{1,128}$/.test(id) ? id : undefined; + } + __webpack_require__.d(__webpack_exports__, { + Xt: ()=>withCodexSender, + xA: ()=>codexSenderPrefix + }); + }, "./src/core/store.js" (__unused_rspack___webpack_module__, __unused_rspack___webpack_exports__, __webpack_require__) { var node_crypto__rspack_import_0 = __webpack_require__("node:crypto"); var node_fs__rspack_import_1 = __webpack_require__("node:fs"); diff --git a/artifact/skills/talk-to-grok-bot/SKILL.md b/artifact/skills/talk-to-grok-bot/SKILL.md index 68c5ded..173d154 100644 --- a/artifact/skills/talk-to-grok-bot/SKILL.md +++ b/artifact/skills/talk-to-grok-bot/SKILL.md @@ -44,6 +44,20 @@ continue useful work instead of waiting or polling. Read `gbot_thread` later, using `after` for a known cursor and `full: true` only when entry bodies are needed. `replyMode: manual` explicitly requests this flow. +Every Codex -> Grok message arrives prefixed +`[from Codex thread @ , cwd ; reply: codex_send({threadId:"", message:"..."}) via MCP on (or CLI: gbot codex send "...")]`. +**If you are Grok Bot, answer a Codex sender by calling `codex_send` with that +`threadId`** (from the box, run `gbot codex send "..."` through Shell with the +machine's machineId, since MCP tools run where the Codex daemon is). Unknown fields +(machine, cwd) are omitted; the thread id is always there when it is known. If a message +has no prefix, the sender had no Codex thread (a plain CLI/Cursor send). + +Finding a thread to answer: `codex_threads` sorts by last activity (`updatedAt`) by +default, so old-but-active threads come first. Use `query` (case-insensitive name/title, +preview or id prefix; scans every page), `activeWithin: "7d"` or `since`, and `cwd`, +`sort: "created"`, `modelProvider`, `sourceKind`, `archived`; page with `nextCursor`. +CLI: `gbot codex list-threads --query zerofs --active-within 7d`. + Never resend an unknown submission under a new identity. Inspect delivery with `gbot_bridge_status`. Never infer permission from chat replies or auto-approve a Codex/Grok interaction; keep approvals in the owning UI unless the user explicitly diff --git a/artifact/skills/talk-to-grok-bot/references/bridge-administration.md b/artifact/skills/talk-to-grok-bot/references/bridge-administration.md index 268b1e6..5c1bdf9 100644 --- a/artifact/skills/talk-to-grok-bot/references/bridge-administration.md +++ b/artifact/skills/talk-to-grok-bot/references/bridge-administration.md @@ -39,7 +39,7 @@ Shell with a machineId, after `codex app-server daemon start` (or bootstrap) the Grok tools use the Grok gateway. Portable MCP artifacts must be configured in an MCP-capable host; they are not automatically loaded by the Grok app. -- `codex_threads`: bounded discovery of daemon-managed Codex threads. +- `codex_threads`: discovery of daemon-managed Codex threads, newest activity first. `query` (name/title, preview or id prefix, all pages), `activeWithin`/`since`, `sort`/`order`, `cwd`, `modelProvider`, `sourceKind`, `archived`; `limit` is the page size (1-200) and `nextCursor` continues. - `codex_send`: submit a message with a correlation envelope. Default delivery is immediate acceptance, which does not mean execution finished. `wait: true` adds bounded execution and final reply fields. An accepted message remains accepted