@wrenai/genbi 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/README.md +65 -3
  2. package/dist/assets/{echarts-LTFC-ysd.js → echarts-DYM4hjvk.js} +2 -2
  3. package/dist/assets/index-A_Wrq7Ey.css +1 -0
  4. package/dist/assets/{index-Bo--QMUN.js → index-DsH129tV.js} +18 -17
  5. package/dist/index.html +2 -2
  6. package/dist-server/harness/bundle/schema.d.ts +38 -0
  7. package/dist-server/harness/bundle/schema.js +18 -10
  8. package/dist-server/harness/bundle/version.js +1 -1
  9. package/dist-server/harness/cli-args.d.ts +10 -2
  10. package/dist-server/harness/cli-args.js +24 -8
  11. package/dist-server/harness/cli.js +75 -9
  12. package/dist-server/harness/compile/cache.js +4 -4
  13. package/dist-server/harness/compile/compose-profile.d.ts +51 -14
  14. package/dist-server/harness/compile/compose-profile.js +85 -19
  15. package/dist-server/harness/compile/context-loader.d.ts +56 -0
  16. package/dist-server/harness/compile/context-loader.js +237 -0
  17. package/dist-server/harness/compile/errors.d.ts +19 -0
  18. package/dist-server/harness/compile/errors.js +35 -0
  19. package/dist-server/harness/compile/index.d.ts +4 -3
  20. package/dist-server/harness/compile/index.js +4 -3
  21. package/dist-server/harness/compile/pipeline.d.ts +15 -7
  22. package/dist-server/harness/compile/pipeline.js +62 -14
  23. package/dist-server/harness/compile/resolve-binary.d.ts +2 -2
  24. package/dist-server/harness/compile/resolve-binary.js +13 -3
  25. package/dist-server/harness/compile/types.d.ts +29 -0
  26. package/dist-server/harness/compile/warble-identity.d.ts +11 -0
  27. package/dist-server/harness/compile/warble-identity.js +13 -0
  28. package/dist-server/harness/components/ai-step.d.ts +4 -0
  29. package/dist-server/harness/components/ai-step.js +40 -0
  30. package/dist-server/harness/components/broker.d.ts +60 -0
  31. package/dist-server/harness/components/broker.js +117 -0
  32. package/dist-server/harness/components/capability-card.d.ts +98 -0
  33. package/dist-server/harness/components/capability-card.js +169 -0
  34. package/dist-server/harness/components/context.d.ts +2 -0
  35. package/dist-server/harness/components/context.js +30 -0
  36. package/dist-server/harness/components/display.d.ts +6 -0
  37. package/dist-server/harness/components/display.js +29 -0
  38. package/dist-server/harness/components/egress-judge.d.ts +12 -0
  39. package/dist-server/harness/components/egress-judge.js +27 -0
  40. package/dist-server/harness/components/egress.d.ts +142 -0
  41. package/dist-server/harness/components/egress.js +469 -0
  42. package/dist-server/harness/components/in-process.d.ts +7 -0
  43. package/dist-server/harness/components/in-process.js +245 -0
  44. package/dist-server/harness/components/normalize.d.ts +35 -0
  45. package/dist-server/harness/components/normalize.js +245 -0
  46. package/dist-server/harness/components/plan.d.ts +31 -0
  47. package/dist-server/harness/components/plan.js +184 -0
  48. package/dist-server/harness/components/report.d.ts +207 -0
  49. package/dist-server/harness/components/report.js +309 -0
  50. package/dist-server/harness/components/runner.d.ts +193 -0
  51. package/dist-server/harness/components/runner.js +492 -0
  52. package/dist-server/harness/components/semantic-guards.d.ts +20 -0
  53. package/dist-server/harness/components/semantic-guards.js +42 -0
  54. package/dist-server/harness/components/terminal-json.d.ts +18 -0
  55. package/dist-server/harness/components/terminal-json.js +82 -0
  56. package/dist-server/harness/components/usage.d.ts +14 -0
  57. package/dist-server/harness/components/usage.js +19 -0
  58. package/dist-server/harness/components/wren-access.d.ts +29 -0
  59. package/dist-server/harness/components/wren-access.js +233 -0
  60. package/dist-server/harness/components/zone-dry-run.d.ts +43 -0
  61. package/dist-server/harness/components/zone-dry-run.js +107 -0
  62. package/dist-server/harness/components/zone-gate.d.ts +76 -0
  63. package/dist-server/harness/components/zone-gate.js +144 -0
  64. package/dist-server/harness/events/index.d.ts +1 -1
  65. package/dist-server/harness/events/types.d.ts +52 -0
  66. package/dist-server/harness/index.d.ts +9 -2
  67. package/dist-server/harness/index.js +5 -1
  68. package/dist-server/harness/loop/executor.d.ts +1 -0
  69. package/dist-server/harness/loop/executor.js +37 -15
  70. package/dist-server/harness/npm-package-resolve.d.ts +2 -0
  71. package/dist-server/harness/npm-package-resolve.js +16 -4
  72. package/dist-server/harness/providers/adapters/openai-compatible.d.ts +13 -0
  73. package/dist-server/harness/providers/adapters/openai-compatible.js +17 -0
  74. package/dist-server/harness/providers/adapters/openai.d.ts +7 -0
  75. package/dist-server/harness/providers/adapters/openai.js +6 -0
  76. package/dist-server/harness/providers/adapters/pi-ai.d.ts +48 -0
  77. package/dist-server/harness/providers/adapters/pi-ai.js +518 -0
  78. package/dist-server/harness/providers/binding.d.ts +45 -4
  79. package/dist-server/harness/providers/binding.js +44 -8
  80. package/dist-server/harness/providers/index.d.ts +9 -3
  81. package/dist-server/harness/providers/index.js +10 -3
  82. package/dist-server/harness/providers/zone.d.ts +96 -0
  83. package/dist-server/harness/providers/zone.js +112 -0
  84. package/dist-server/harness/render/answering-query.d.ts +29 -0
  85. package/dist-server/harness/render/answering-query.js +62 -0
  86. package/dist-server/harness/render/envelope.d.ts +6 -0
  87. package/dist-server/harness/render/envelope.js +10 -3
  88. package/dist-server/harness/route/adapter-spec.d.ts +8 -9
  89. package/dist-server/harness/route/adapter-spec.js +13 -14
  90. package/dist-server/harness/route/codex-ask-events.js +2 -1
  91. package/dist-server/harness/route/codex-ask.d.ts +4 -0
  92. package/dist-server/harness/route/codex-ask.js +69 -30
  93. package/dist-server/harness/route/codex-host-query.d.ts +52 -0
  94. package/dist-server/harness/route/codex-host-query.js +191 -0
  95. package/dist-server/harness/route/codex-local-manifest.d.ts +9 -1
  96. package/dist-server/harness/route/codex-local-manifest.js +96 -15
  97. package/dist-server/harness/route/codex-wren-proxy.d.ts +33 -0
  98. package/dist-server/harness/route/codex-wren-proxy.js +227 -0
  99. package/dist-server/harness/route/describe.js +45 -6
  100. package/dist-server/harness/route/in-process.d.ts +22 -1
  101. package/dist-server/harness/route/in-process.js +54 -4
  102. package/dist-server/harness/route/route.js +5 -2
  103. package/dist-server/harness/route/types.d.ts +30 -1
  104. package/dist-server/harness/session/run.js +30 -10
  105. package/dist-server/harness/setup/runner.d.ts +2 -0
  106. package/dist-server/harness/setup/runner.js +38 -17
  107. package/dist-server/harness/setup/yaml-scalar.d.ts +23 -0
  108. package/dist-server/harness/setup/yaml-scalar.js +62 -0
  109. package/dist-server/server/adopt.js +1 -17
  110. package/dist-server/server/app.d.ts +1 -0
  111. package/dist-server/server/app.js +163 -14
  112. package/dist-server/server/auth-choice.d.ts +13 -1
  113. package/dist-server/server/auth-choice.js +66 -1
  114. package/dist-server/server/bin.js +197 -26
  115. package/dist-server/server/codex-local-grounding.d.ts +18 -0
  116. package/dist-server/server/codex-local-grounding.js +92 -0
  117. package/dist-server/server/codex-native-session.d.ts +25 -0
  118. package/dist-server/server/codex-native-session.js +1 -0
  119. package/dist-server/server/codex-runtime-composition.d.ts +34 -0
  120. package/dist-server/server/codex-runtime-composition.js +250 -0
  121. package/dist-server/server/codex-structured-ask.d.ts +23 -0
  122. package/dist-server/server/codex-structured-ask.js +102 -0
  123. package/dist-server/server/conn-config.js +4 -16
  124. package/dist-server/server/conversation-socket.d.ts +16 -0
  125. package/dist-server/server/conversation-socket.js +65 -0
  126. package/dist-server/server/db.d.ts +46 -0
  127. package/dist-server/server/db.js +88 -9
  128. package/dist-server/server/env-detect.d.ts +6 -0
  129. package/dist-server/server/env-detect.js +7 -0
  130. package/dist-server/server/fold.d.ts +22 -4
  131. package/dist-server/server/fold.js +37 -5
  132. package/dist-server/server/harness.d.ts +2 -2
  133. package/dist-server/server/harness.js +33 -7
  134. package/dist-server/server/interactive-terminal.d.ts +10 -6
  135. package/dist-server/server/interactive-terminal.js +33 -8
  136. package/dist-server/server/managed-wren-runtime.d.ts +116 -0
  137. package/dist-server/server/managed-wren-runtime.js +670 -0
  138. package/dist-server/server/native-artifacts.d.ts +23 -7
  139. package/dist-server/server/native-artifacts.js +43 -12
  140. package/dist-server/server/native-component-context.d.ts +19 -0
  141. package/dist-server/server/native-component-context.js +76 -0
  142. package/dist-server/server/native-component-preparation.d.ts +20 -0
  143. package/dist-server/server/native-component-preparation.js +129 -0
  144. package/dist-server/server/native-component-runtime.d.ts +36 -0
  145. package/dist-server/server/native-component-runtime.js +92 -0
  146. package/dist-server/server/native-components.d.ts +84 -0
  147. package/dist-server/server/native-components.js +160 -0
  148. package/dist-server/server/native-dispatch-process.d.ts +8 -0
  149. package/dist-server/server/native-dispatch-process.js +65 -0
  150. package/dist-server/server/native-runtime-spec.d.ts +89 -0
  151. package/dist-server/server/native-runtime-spec.js +169 -0
  152. package/dist-server/server/native-sessions.d.ts +172 -19
  153. package/dist-server/server/native-sessions.js +870 -251
  154. package/dist-server/server/native-shutdown.d.ts +6 -0
  155. package/dist-server/server/native-shutdown.js +28 -0
  156. package/dist-server/server/native-wren-home.d.ts +18 -0
  157. package/dist-server/server/native-wren-home.js +262 -0
  158. package/dist-server/server/node-pty-host.d.ts +2 -1
  159. package/dist-server/server/node-pty-host.js +3 -2
  160. package/dist-server/server/profile-registry.d.ts +139 -0
  161. package/dist-server/server/profile-registry.js +620 -0
  162. package/dist-server/server/runtime-binding.d.ts +4 -1
  163. package/dist-server/server/runtime-binding.js +50 -2
  164. package/dist-server/server/runtime-host/claude-component-step.d.ts +25 -0
  165. package/dist-server/server/runtime-host/claude-component-step.js +186 -0
  166. package/dist-server/server/runtime-host/codex-app-server.d.ts +75 -0
  167. package/dist-server/server/runtime-host/codex-app-server.js +239 -0
  168. package/dist-server/server/runtime-host/codex-compatibility.d.ts +110 -0
  169. package/dist-server/server/runtime-host/codex-compatibility.js +162 -0
  170. package/dist-server/server/runtime-host/codex-component-step.d.ts +19 -0
  171. package/dist-server/server/runtime-host/codex-component-step.js +308 -0
  172. package/dist-server/server/runtime-host/codex-conversation.d.ts +109 -0
  173. package/dist-server/server/runtime-host/codex-conversation.js +295 -0
  174. package/dist-server/server/runtime-host/codex-direct-tools.d.ts +23 -0
  175. package/dist-server/server/runtime-host/codex-direct-tools.js +59 -0
  176. package/dist-server/server/runtime-host/codex-events.d.ts +647 -0
  177. package/dist-server/server/runtime-host/codex-events.js +66 -0
  178. package/dist-server/server/runtime-host/codex-policy.d.ts +16 -0
  179. package/dist-server/server/runtime-host/codex-policy.js +151 -0
  180. package/dist-server/server/runtime-host/codex-process.d.ts +8 -0
  181. package/dist-server/server/runtime-host/codex-process.js +96 -0
  182. package/dist-server/server/runtime-host/codex-rpc.d.ts +47 -0
  183. package/dist-server/server/runtime-host/codex-rpc.js +182 -0
  184. package/dist-server/server/runtime-host/codex-session.d.ts +74 -0
  185. package/dist-server/server/runtime-host/codex-session.js +492 -0
  186. package/dist-server/server/runtime-host/codex-terminal-protocol.d.ts +35 -0
  187. package/dist-server/server/runtime-host/codex-terminal-protocol.js +243 -0
  188. package/dist-server/server/runtime-host/codex-terminal.d.ts +16 -0
  189. package/dist-server/server/runtime-host/codex-terminal.js +120 -0
  190. package/dist-server/server/runtime-host/index.d.ts +5 -0
  191. package/dist-server/server/runtime-host/index.js +3 -0
  192. package/dist-server/server/runtime-host/local.d.ts +29 -0
  193. package/dist-server/server/runtime-host/local.js +90 -0
  194. package/dist-server/server/runtime-host/policy.d.ts +8 -0
  195. package/dist-server/server/runtime-host/policy.js +78 -0
  196. package/dist-server/server/runtime-host/types.d.ts +52 -0
  197. package/dist-server/server/runtime-host/types.js +62 -0
  198. package/dist-server/server/structured-query-evidence.d.ts +7 -0
  199. package/dist-server/server/structured-query-evidence.js +47 -0
  200. package/dist-server/server/structured-runtime.d.ts +52 -0
  201. package/dist-server/server/structured-runtime.js +130 -0
  202. package/dist-server/server/structured-scope.d.ts +4 -0
  203. package/dist-server/server/structured-scope.js +12 -0
  204. package/dist-server/server/turn.d.ts +6 -1
  205. package/dist-server/server/turn.js +82 -25
  206. package/dist-server/server/wire-types.d.ts +67 -3
  207. package/dist-server/server/wren-profiles.js +1 -1
  208. package/managed-wren/README.md +60 -0
  209. package/managed-wren/dependency-wheels.json +282 -0
  210. package/managed-wren/manifest.json +373 -0
  211. package/managed-wren/release-inputs.json +45 -0
  212. package/managed-wren/runtime-tree.cjs +115 -0
  213. package/managed-wren/source-inputs.json +40 -0
  214. package/package.json +15 -6
  215. package/profiles/genbi-default/context/binding.yml +17 -7
  216. package/profiles/genbi-default/context/context.json +146 -0
  217. package/profiles/genbi-default/ir.golden.json +39 -43
  218. package/profiles/genbi-default/profile.yml +31 -0
  219. package/profiles/genbi-enrich-context/context/binding.yml +14 -3
  220. package/profiles/genbi-enrich-context/context/context.json +146 -0
  221. package/profiles/genbi-enrich-context/ir.golden.json +4 -5
  222. package/profiles/genbi-monitor/context/binding.yml +13 -5
  223. package/profiles/genbi-monitor/context/context.json +146 -0
  224. package/profiles/genbi-monitor/ir.golden.json +13 -7
  225. package/profiles/genbi-report/context/binding.yml +19 -0
  226. package/profiles/genbi-report/context/context.json +223 -0
  227. package/profiles/genbi-report/ir.golden.json +328 -0
  228. package/profiles/genbi-report/profile.yml +38 -0
  229. package/profiles/genbi-setup/ir.golden.json +3 -1
  230. package/dist/assets/index-Xs4q7pNo.css +0 -1
@@ -0,0 +1,66 @@
1
+ import { z } from "zod";
2
+ import { CodexRpcError } from "./codex-rpc.js";
3
+ const id = z.string().min(1).max(256);
4
+ const text = z.string().max(1_048_576);
5
+ const itemBase = { id };
6
+ const state = z.enum(["inProgress", "completed", "failed", "declined"]);
7
+ // Explicit supported item projection: never forward opaque vendor objects or
8
+ // error text. New tools/items require reviewed schema and policy support.
9
+ export const codexItemSchema = z.discriminatedUnion("type", [
10
+ z.object({ ...itemBase, type: z.literal("userMessage"), content: z.array(z.object({ type: z.literal("text"), text })).max(128) }),
11
+ z.object({ ...itemBase, type: z.literal("agentMessage"), text }),
12
+ z.object({ ...itemBase, type: z.literal("plan"), text }),
13
+ z.object({ ...itemBase, type: z.literal("reasoning"), content: z.array(text).default([]), summary: z.array(text).default([]) }),
14
+ z.object({ ...itemBase, type: z.literal("commandExecution"), command: text, cwd: text, status: state, aggregatedOutput: text.nullish(), exitCode: z.number().int().nullish() }),
15
+ z.object({ ...itemBase, type: z.literal("fileChange"), status: state, changes: z.array(z.object({ path: text, diff: text, kind: z.discriminatedUnion("type", [z.object({ type: z.literal("add") }), z.object({ type: z.literal("delete") }), z.object({ type: z.literal("update"), move_path: text.nullish() })]) })) }),
16
+ z.object({ ...itemBase, type: z.literal("contextCompaction") }),
17
+ z.object({ ...itemBase, type: z.literal("dynamicToolCall"), tool: z.string().min(1).max(256), namespace: z.null().optional(), status: z.enum(["inProgress", "completed", "failed"]), success: z.boolean().nullable().optional() }),
18
+ ]);
19
+ export const codexTurnSchema = z.object({ id, status: z.enum(["inProgress", "completed", "interrupted", "failed"]), items: z.array(codexItemSchema).max(512), itemsView: z.enum(["full", "summary", "notLoaded"]).optional() })
20
+ .refine((turn) => turn.itemsView !== "notLoaded" || turn.items.length === 0);
21
+ export const codexThreadSchema = z.object({ id, cwd: text, cliVersion: z.string(), ephemeral: z.boolean() });
22
+ const scope = { threadId: id, turnId: id };
23
+ const scopedItem = { ...scope, itemId: id };
24
+ const delta = z.object({ ...scopedItem, delta: text });
25
+ const usage = z.object({ totalTokens: z.number().int().nonnegative(), inputTokens: z.number().int().nonnegative(), cachedInputTokens: z.number().int().nonnegative(), outputTokens: z.number().int().nonnegative(), reasoningOutputTokens: z.number().int().nonnegative() });
26
+ export const codexAccountUpdatedSchema = z.object({ authMode: z.literal("chatgpt"), planType: z.string().min(1).max(128).nullable().optional() }).strict();
27
+ const limitText = z.string().max(256).nullish();
28
+ const limitWindow = z.object({ usedPercent: z.number().int(), windowDurationMins: z.number().int().nullish(), resetsAt: z.number().int().nullish() }).strict().nullish();
29
+ export const codexRateLimitsUpdatedSchema = z.object({ rateLimits: z.object({
30
+ limitId: limitText, limitName: limitText, normalModelSlug: limitText, planType: limitText,
31
+ primary: limitWindow, secondary: limitWindow,
32
+ credits: z.object({ hasCredits: z.boolean(), unlimited: z.boolean(), balance: limitText }).strict().nullish(),
33
+ individualLimit: z.object({ limit: z.string().max(256), used: z.string().max(256), remainingPercent: z.number().int(), resetsAt: z.number().int() }).strict().nullish(),
34
+ spendControlReached: z.boolean().nullish(),
35
+ rateLimitReachedType: z.enum(["rate_limit_reached", "workspace_owner_credits_depleted", "workspace_member_credits_depleted", "workspace_owner_usage_limit_reached", "workspace_member_usage_limit_reached"]).nullish(),
36
+ }).strict() }).strict();
37
+ export const codexDisabledCodeModeWarningSchema = z.object({ threadId: id, message: z.literal("Code Mode is unavailable because code-mode host is disabled. Code mode will fail closed; enable `features.code_mode_host` and install `codex-code-mode-host`.") }).strict();
38
+ export const codexNotificationSchemas = {
39
+ "warning": codexDisabledCodeModeWarningSchema,
40
+ "remoteControl/status/changed": z.object({ status: z.literal("disabled"), installationId: text, serverName: text, environmentId: z.null().optional() }),
41
+ "thread/started": z.object({ thread: codexThreadSchema }),
42
+ "thread/status/changed": z.object({ threadId: id, status: z.discriminatedUnion("type", [z.object({ type: z.literal("idle") }), z.object({ type: z.literal("active"), activeFlags: z.array(z.enum(["waitingOnApproval", "waitingOnUserInput"])) })]) }),
43
+ "thread/tokenUsage/updated": z.object({ ...scope, tokenUsage: z.object({ total: usage, last: usage, modelContextWindow: z.number().int().nullish() }) }),
44
+ "turn/started": z.object({ threadId: id, turn: codexTurnSchema }),
45
+ "turn/completed": z.object({ threadId: id, turn: codexTurnSchema }),
46
+ "turn/diff/updated": z.object({ ...scope, diff: text }),
47
+ "turn/plan/updated": z.object({ ...scope, explanation: text.nullish(), plan: z.array(z.object({ step: text, status: z.enum(["pending", "inProgress", "completed"]) })) }),
48
+ "item/started": z.object({ ...scope, item: codexItemSchema }),
49
+ "item/completed": z.object({ ...scope, item: codexItemSchema }),
50
+ "item/agentMessage/delta": delta,
51
+ "item/commandExecution/outputDelta": delta,
52
+ "item/fileChange/outputDelta": delta,
53
+ "item/reasoning/summaryTextDelta": delta.extend({ summaryIndex: z.number().int().nonnegative() }),
54
+ "item/reasoning/textDelta": delta.extend({ contentIndex: z.number().int().nonnegative() }),
55
+ "item/reasoning/summaryPartAdded": z.object({ ...scopedItem, summaryIndex: z.number().int().nonnegative() }),
56
+ "command/exec/outputDelta": z.object({ processId: id, stream: z.enum(["stdout", "stderr"]), deltaBase64: text.refine((value) => Buffer.from(value, "base64").toString("base64") === value), capReached: z.boolean() }),
57
+ };
58
+ export function parseCodexEvent(method, params) {
59
+ if (!Object.hasOwn(codexNotificationSchemas, method))
60
+ throw new CodexRpcError("protocol");
61
+ const schema = codexNotificationSchemas[method];
62
+ const parsed = schema.safeParse(params);
63
+ if (!parsed.success)
64
+ throw new CodexRpcError("protocol");
65
+ return { method, params: parsed.data };
66
+ }
@@ -0,0 +1,16 @@
1
+ import { type NativeRuntimeSpec } from "../native-runtime-spec.js";
2
+ import type { ManagedWrenRuntimeRecord } from "../managed-wren-runtime.js";
3
+ import type { CodexWrenHome } from "../native-wren-home.js";
4
+ export declare const CODEX_PERMISSION_PROFILE = "genbi-scoped";
5
+ export interface CodexSessionPolicy {
6
+ readonly model?: string;
7
+ readonly cwd: string;
8
+ readonly codexHome: string;
9
+ readonly profile: typeof CODEX_PERMISSION_PROFILE;
10
+ readonly args: readonly string[];
11
+ readonly environment: Readonly<Record<string, string>>;
12
+ readonly commandEnvironment: Readonly<Record<string, string | null>>;
13
+ readonly configuration: Readonly<Record<string, unknown>>;
14
+ }
15
+ /** Pure, resolve-only policy construction from host-owned scope, never request JSON. */
16
+ export declare function buildCodexSessionPolicy(spec: NativeRuntimeSpec, runtime: ManagedWrenRuntimeRecord, home: CodexWrenHome, directTools?: boolean, model?: string): CodexSessionPolicy;
@@ -0,0 +1,151 @@
1
+ import { lstatSync, realpathSync, existsSync, readdirSync } from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { assertNativeRuntimeSpec } from "../native-runtime-spec.js";
5
+ import { CodexRpcError } from "./codex-rpc.js";
6
+ import { codexComponentConfiguration } from "./codex-component-step.js";
7
+ export const CODEX_PERMISSION_PROFILE = "genbi-scoped";
8
+ const deny = () => { throw new CodexRpcError("protocol"); };
9
+ const within = (root, target) => target === root || target.startsWith(root + path.sep);
10
+ function canonical(value) {
11
+ if (!path.isAbsolute(value) || realpathSync(value) !== value || lstatSync(value).isSymbolicLink())
12
+ deny();
13
+ // Permission keys interpret globs and ~, so never treat these as literal paths.
14
+ if (/[\x00-\x1f*?\[\]{}~]/.test(value))
15
+ deny();
16
+ return value;
17
+ }
18
+ function privateDirectory(value) {
19
+ canonical(value);
20
+ const stat = lstatSync(value);
21
+ if (!stat.isDirectory() || (stat.mode & 0o777) !== 0o700)
22
+ deny();
23
+ }
24
+ function toml(value) {
25
+ if (typeof value === "string" || typeof value === "boolean" || typeof value === "number")
26
+ return JSON.stringify(value);
27
+ if (Array.isArray(value))
28
+ return `[${value.map(toml).join(",")}]`;
29
+ if (value && typeof value === "object")
30
+ return `{${Object.entries(value).map(([key, item]) => `${JSON.stringify(key)}=${toml(item)}`).join(",")}}`;
31
+ return deny();
32
+ }
33
+ /** Pure, resolve-only policy construction from host-owned scope, never request JSON. */
34
+ export function buildCodexSessionPolicy(spec, runtime, home, directTools = false, model) {
35
+ assertNativeRuntimeSpec(spec);
36
+ if (spec.backend !== "codex-app-server" || spec.vendor !== "codex" || !spec.childEnvironment.CODEX_HOME || spec.mcp)
37
+ deny();
38
+ if (spec.executables.wren?.executable !== runtime.launcher || spec.executables.python?.executable !== runtime.venv_python)
39
+ deny();
40
+ if (spec.sessionWrenHome !== home.home || !home.assertActive || !home.active?.())
41
+ deny();
42
+ home.assertActive();
43
+ const codexHome = canonical(spec.childEnvironment.CODEX_HOME);
44
+ const cwd = canonical(spec.workspace);
45
+ const generation = canonical(runtime.generation_root);
46
+ privateDirectory(codexHome);
47
+ privateDirectory(spec.childEnvironment.HOME);
48
+ privateDirectory(home.home);
49
+ // Login belongs to the user. Never copy it or read its contents; require a
50
+ // dedicated externally authenticated home, outside every writable/read root.
51
+ if (codexHome === path.join(os.homedir(), ".codex") || spec.childEnvironment.HOME === os.homedir())
52
+ deny();
53
+ const auth = path.join(codexHome, "auth.json");
54
+ const authStat = lstatSync(auth);
55
+ if (!authStat.isFile() || authStat.isSymbolicLink() || (authStat.mode & 0o077) !== 0)
56
+ deny();
57
+ // No operator config, plugins, hooks, or project config may augment this
58
+ // backend. Auth and vendor-generated session state may remain in the home.
59
+ for (const name of ["config.toml", "requirements.toml", "AGENTS.md", "instructions.md", "hooks.json", "plugins"]) {
60
+ if (existsSync(path.join(codexHome, name)))
61
+ deny();
62
+ }
63
+ // Codex seeds its bundled .system skills during initialization. Permit only
64
+ // that namespace; user skills still cannot enter through the login home.
65
+ const skills = path.join(codexHome, "skills");
66
+ if (existsSync(skills)) {
67
+ canonical(skills);
68
+ if (!lstatSync(skills).isDirectory() || readdirSync(skills).some((name) => name !== ".system"))
69
+ deny();
70
+ if (existsSync(path.join(skills, ".system")))
71
+ canonical(path.join(skills, ".system"));
72
+ }
73
+ for (const root of [cwd, ...(spec.project ? [spec.project.path] : [])]) {
74
+ let current = root;
75
+ while (true) {
76
+ if (existsSync(path.join(current, ".codex")))
77
+ deny();
78
+ const parent = path.dirname(current);
79
+ if (current === parent)
80
+ break;
81
+ current = parent;
82
+ }
83
+ }
84
+ const readRoots = [...new Set([generation, ...spec.toolDirectories, ...(spec.project ? [spec.project.path] : []), ...home.dataRoots])].map(canonical);
85
+ if (within(cwd, generation) || within(generation, cwd) || within(cwd, codexHome) || within(codexHome, cwd))
86
+ deny();
87
+ for (const root of readRoots) {
88
+ if (root === path.parse(root).root || within(root, os.homedir()) || within(root, codexHome) || within(codexHome, root))
89
+ deny();
90
+ }
91
+ // Platform defaults include shared scratch directories. The certified vendor
92
+ // must enforce these exclusions even against those implicit grants; session
93
+ // workspace grants below remain explicit and more specific.
94
+ const filesystem = {
95
+ ":minimal": "read", "/private/tmp": "deny", "/private/var/tmp": "deny",
96
+ };
97
+ for (const root of readRoots)
98
+ filesystem[root] = "read";
99
+ filesystem[cwd] = "write";
100
+ // A selected Wren profile is readable, never editable by the agent. Narrow
101
+ // session secrets are deliberate; user/project .env remains protected.
102
+ filesystem[home.home] = "read";
103
+ filesystem[codexHome] = "deny";
104
+ filesystem[path.join(os.homedir(), ".ssh")] = "deny";
105
+ filesystem[path.join(os.homedir(), ".aws")] = "deny";
106
+ filesystem[path.join(os.homedir(), ".codex")] = "deny";
107
+ filesystem[path.join(os.homedir(), ".claude")] = "deny";
108
+ if (spec.project)
109
+ filesystem[path.join(spec.project.path, ".env")] = "deny";
110
+ filesystem[path.join(cwd, ".codex")] = "deny";
111
+ filesystem[path.join(cwd, ".git")] = "read";
112
+ const environment = {
113
+ PATH: spec.childEnvironment.PATH, HOME: spec.childEnvironment.HOME,
114
+ CODEX_HOME: codexHome, TERM: "xterm-256color", COLORTERM: "truecolor",
115
+ PYTHONNOUSERSITE: "1", PYTHONUTF8: "1", PYTHONDONTWRITEBYTECODE: "1",
116
+ WREN_HOME: home.home,
117
+ ...(spec.project ? { WREN_PROJECT_HOME: spec.project.path } : {}),
118
+ };
119
+ // App-server may read its login; commands receive neither its home variable
120
+ // nor any provider credentials. No ambient environment spread is used.
121
+ const { CODEX_HOME: _loginHome, ...shellEnvironment } = environment;
122
+ const config = directTools ? { ...codexComponentConfiguration(CODEX_PERMISSION_PROFILE) } : {
123
+ default_permissions: CODEX_PERMISSION_PROFILE,
124
+ permissions: { [CODEX_PERMISSION_PROFILE]: { filesystem, network: { enabled: false } } },
125
+ approval_policy: "never",
126
+ shell_environment_policy: { inherit: "none", set: shellEnvironment },
127
+ project_doc_max_bytes: 0,
128
+ project_root_markers: [], web_search: "disabled", mcp_servers: {},
129
+ features: Object.fromEntries([
130
+ "apps", "browser_use", "browser_use_external", "browser_use_full_cdp_access", "computer_use",
131
+ "code_mode_host", "code_mode", "code_mode_only", "hooks", "image_generation", "in_app_browser",
132
+ "multi_agent", "multi_agent_v2", "plugins", "remote_plugin", "plugin_sharing", "skill_mcp_dependency_install",
133
+ "skill_search", "tool_suggest", "workspace_dependencies", "request_permissions_tool", "exec_permission_approvals",
134
+ "guardian_approval", "guardianv2", "goals", "memories", "external_agent_memory_import", "realtime_conversation",
135
+ "shell_snapshot", "standalone_web_search",
136
+ ].map((name) => [name, false])),
137
+ };
138
+ if (model !== undefined) {
139
+ if (!model.trim() || model.length > 256)
140
+ deny();
141
+ config.model = model;
142
+ }
143
+ if (directTools) {
144
+ delete environment.WREN_HOME;
145
+ delete environment.WREN_PROJECT_HOME;
146
+ }
147
+ const args = Object.entries(config).flatMap(([key, value]) => ["-c", `${key}=${toml(value)}`]);
148
+ args.push("app-server", "--stdio", "--strict-config");
149
+ return Object.freeze({ ...(model ? { model } : {}), cwd, codexHome, profile: CODEX_PERMISSION_PROFILE, args: Object.freeze(args),
150
+ environment: Object.freeze(environment), commandEnvironment: Object.freeze(directTools ? {} : { ...shellEnvironment, CODEX_HOME: null }), configuration: Object.freeze(config) });
151
+ }
@@ -0,0 +1,8 @@
1
+ import { type RpcTransport } from "./codex-rpc.js";
2
+ /** Owned POSIX process group. Never accepts a PID from a vendor response. */
3
+ export declare function spawnCodexTransport(input: {
4
+ executable: string;
5
+ args: readonly string[];
6
+ cwd: string;
7
+ env: NodeJS.ProcessEnv;
8
+ }): RpcTransport;
@@ -0,0 +1,96 @@
1
+ import { spawn } from "node:child_process";
2
+ import { CodexRpcError } from "./codex-rpc.js";
3
+ /** Owned POSIX process group. Never accepts a PID from a vendor response. */
4
+ export function spawnCodexTransport(input) {
5
+ const child = spawn(input.executable, [...input.args], {
6
+ cwd: input.cwd, env: input.env, detached: true, stdio: ["pipe", "pipe", "pipe"],
7
+ });
8
+ let handlers;
9
+ let failed = false;
10
+ let ended = false;
11
+ let closing;
12
+ child.stderr.resume(); // drain without retaining secrets or model output
13
+ child.on("error", () => { failed = true; handlers?.error(); });
14
+ child.stdin.on("error", () => { failed = true; handlers?.error(); });
15
+ child.stdout.on("error", () => { failed = true; handlers?.error(); });
16
+ child.stdout.on("end", () => { ended = true; handlers?.end(); });
17
+ child.on("exit", () => { ended = true; handlers?.end(); });
18
+ const alive = () => {
19
+ if (!child.pid)
20
+ return false;
21
+ try {
22
+ process.kill(-child.pid, 0);
23
+ return true;
24
+ }
25
+ catch (error) {
26
+ const code = error.code;
27
+ if (code === "ESRCH")
28
+ return false;
29
+ // macOS can briefly return EPERM while a terminated group is being
30
+ // reaped. It is NOT evidence of exit: keep polling to the deadline.
31
+ if (code === "EPERM")
32
+ return true;
33
+ throw error;
34
+ }
35
+ };
36
+ const signal = (value) => {
37
+ if (!child.pid)
38
+ return;
39
+ try {
40
+ process.kill(-child.pid, value);
41
+ }
42
+ catch (error) {
43
+ const code = error.code;
44
+ // A denied signal is never success; the bounded liveness check below
45
+ // still has to observe ESRCH or report incomplete cleanup.
46
+ if (code !== "ESRCH" && code !== "EPERM")
47
+ throw error;
48
+ }
49
+ };
50
+ const wait = async (milliseconds) => {
51
+ const deadline = performance.now() + milliseconds;
52
+ while (alive() && performance.now() < deadline)
53
+ await new Promise((resolve) => setTimeout(resolve, 20));
54
+ return !alive();
55
+ };
56
+ return {
57
+ listen(value) {
58
+ if (handlers)
59
+ throw new CodexRpcError("transport");
60
+ handlers = value;
61
+ child.stdout.on("data", (chunk) => value.data(chunk));
62
+ if (failed)
63
+ value.error();
64
+ else if (ended)
65
+ value.end();
66
+ },
67
+ write(line) {
68
+ if (closing || failed || ended || child.stdin.destroyed || child.stdin.writableLength > 1_048_576)
69
+ throw new CodexRpcError("transport");
70
+ child.stdin.write(line);
71
+ },
72
+ close() {
73
+ closing ??= (async () => {
74
+ try {
75
+ child.stdin.end();
76
+ // Let the vendor's connection-close handler reap command/PTY groups
77
+ // that are distinct from this group before escalating host signals.
78
+ if (await wait(200))
79
+ return;
80
+ signal("SIGTERM");
81
+ if (await wait(500))
82
+ return;
83
+ signal("SIGKILL");
84
+ if (!(await wait(2_000)))
85
+ throw new CodexRpcError("cleanup");
86
+ }
87
+ finally {
88
+ child.stdin.destroy();
89
+ child.stdout.destroy();
90
+ child.stderr.destroy();
91
+ }
92
+ })();
93
+ return closing;
94
+ },
95
+ };
96
+ }
@@ -0,0 +1,47 @@
1
+ /** Codex JSONL is JSON-RPC with the jsonrpc header omitted. No raw diagnostics. */
2
+ export type RpcFailure = "protocol" | "closed" | "transport" | "timeout" | "cancelled" | "remote" | "cleanup" | "permission";
3
+ export declare class CodexRpcError extends Error {
4
+ readonly reason: RpcFailure;
5
+ constructor(reason: RpcFailure);
6
+ }
7
+ export interface RpcTransport {
8
+ listen(handlers: {
9
+ data(chunk: Buffer): void;
10
+ end(): void;
11
+ error(): void;
12
+ }): void;
13
+ write(line: string): void;
14
+ /** Resolves only when owned processes are gone; rejects on incomplete cleanup. */
15
+ close(): Promise<void>;
16
+ }
17
+ export declare function object(value: unknown): value is Record<string, unknown>;
18
+ export interface RpcNotification {
19
+ readonly method: string;
20
+ readonly params: unknown;
21
+ }
22
+ export declare class CodexRpcClient {
23
+ private readonly transport;
24
+ private readonly notification;
25
+ private readonly maxLineBytes;
26
+ /** Opt-in governed tools only. Existing session clients still reject all server requests. */
27
+ private readonly serverRequest?;
28
+ private buffer;
29
+ private nextId;
30
+ private pending;
31
+ private failure?;
32
+ private closing?;
33
+ private failureListeners;
34
+ private readonly serverIds;
35
+ private readonly serverTimers;
36
+ constructor(transport: RpcTransport, notification: (message: RpcNotification) => void, maxLineBytes?: number,
37
+ /** Opt-in governed tools only. Existing session clients still reject all server requests. */
38
+ serverRequest?: ((request: RpcNotification) => Promise<unknown>) | undefined);
39
+ onFailure(listener: (error: CodexRpcError) => void): () => void;
40
+ request(method: string, params: unknown, timeoutMs?: number, signal?: AbortSignal, responseReceived?: () => void): Promise<unknown>;
41
+ notify(method: string, params: unknown): void;
42
+ private send;
43
+ private receive;
44
+ private handleLine;
45
+ fail(reason: RpcFailure): void;
46
+ close(): Promise<void>;
47
+ }
@@ -0,0 +1,182 @@
1
+ export class CodexRpcError extends Error {
2
+ reason;
3
+ constructor(reason) {
4
+ super(`Codex RPC ${reason}`);
5
+ this.reason = reason;
6
+ }
7
+ }
8
+ export function object(value) {
9
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10
+ }
11
+ export class CodexRpcClient {
12
+ transport;
13
+ notification;
14
+ maxLineBytes;
15
+ serverRequest;
16
+ buffer = Buffer.alloc(0);
17
+ nextId = 1;
18
+ pending = new Map();
19
+ failure;
20
+ closing;
21
+ failureListeners = new Set();
22
+ serverIds = new Set();
23
+ serverTimers = new Set();
24
+ constructor(transport, notification, maxLineBytes = 1_048_576,
25
+ /** Opt-in governed tools only. Existing session clients still reject all server requests. */
26
+ serverRequest) {
27
+ this.transport = transport;
28
+ this.notification = notification;
29
+ this.maxLineBytes = maxLineBytes;
30
+ this.serverRequest = serverRequest;
31
+ transport.listen({
32
+ data: (chunk) => this.receive(chunk),
33
+ end: () => this.fail("closed"),
34
+ error: () => this.fail("transport"),
35
+ });
36
+ }
37
+ onFailure(listener) {
38
+ if (this.failure)
39
+ listener(this.failure);
40
+ else
41
+ this.failureListeners.add(listener);
42
+ return () => this.failureListeners.delete(listener);
43
+ }
44
+ request(method, params, timeoutMs = 10_000, signal, responseReceived) {
45
+ if (this.failure)
46
+ return Promise.reject(this.failure);
47
+ if (this.pending.size >= 128) {
48
+ this.fail("protocol");
49
+ return Promise.reject(this.failure);
50
+ }
51
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 3_600_000)
52
+ return Promise.reject(new CodexRpcError("protocol"));
53
+ if (signal?.aborted) {
54
+ this.fail("cancelled");
55
+ return Promise.reject(this.failure);
56
+ }
57
+ const id = this.nextId++;
58
+ return new Promise((resolve, reject) => {
59
+ const abort = () => this.fail("cancelled");
60
+ const timer = setTimeout(() => this.fail("timeout"), timeoutMs);
61
+ // Registration must precede write, including an in-process synchronous peer.
62
+ this.pending.set(id, { resolve, reject, timer, ...(responseReceived ? { responseReceived } : {}), removeAbort: () => signal?.removeEventListener("abort", abort) });
63
+ signal?.addEventListener("abort", abort, { once: true });
64
+ this.send({ id, method, params });
65
+ });
66
+ }
67
+ notify(method, params) {
68
+ if (this.failure)
69
+ throw this.failure;
70
+ this.send({ method, params });
71
+ if (this.failure)
72
+ throw this.failure;
73
+ }
74
+ send(message) {
75
+ try {
76
+ const line = JSON.stringify(message) + "\n";
77
+ if (Buffer.byteLength(line) > this.maxLineBytes)
78
+ return this.fail("protocol");
79
+ this.transport.write(line);
80
+ }
81
+ catch {
82
+ this.fail("transport");
83
+ }
84
+ }
85
+ receive(chunk) {
86
+ if (this.failure)
87
+ return;
88
+ // Never retain more than one bounded frame; a chunk may contain many frames.
89
+ let offset = 0;
90
+ while (offset < chunk.length && !this.failure) {
91
+ const newline = chunk.indexOf(10, offset);
92
+ const end = newline < 0 ? chunk.length : newline;
93
+ if (this.buffer.length + end - offset > this.maxLineBytes)
94
+ return this.fail("protocol");
95
+ this.buffer = Buffer.concat([this.buffer, chunk.subarray(offset, end)]);
96
+ if (newline < 0)
97
+ return;
98
+ const line = this.buffer;
99
+ this.buffer = Buffer.alloc(0);
100
+ offset = newline + 1;
101
+ this.handleLine(line);
102
+ }
103
+ }
104
+ handleLine(line) {
105
+ try {
106
+ const message = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(line));
107
+ if (!object(message))
108
+ return this.fail("protocol");
109
+ if ("id" in message) {
110
+ if ("method" in message) {
111
+ if (!this.serverRequest || typeof message.method !== "string" || !("params" in message) || "result" in message || "error" in message
112
+ || !(Number.isSafeInteger(message.id) || (typeof message.id === "string" && message.id.length > 0 && message.id.length <= 256)))
113
+ return this.fail("protocol");
114
+ const key = JSON.stringify(message.id);
115
+ if (this.serverIds.has(key) || this.serverIds.size >= 512)
116
+ return this.fail("protocol");
117
+ this.serverIds.add(key);
118
+ const timer = setTimeout(() => this.fail("timeout"), 120_000);
119
+ this.serverTimers.add(timer);
120
+ void Promise.resolve().then(() => { if (this.failure)
121
+ throw this.failure; return this.serverRequest({ method: message.method, params: message.params }); })
122
+ .then((result) => { if (!this.failure)
123
+ this.send({ id: message.id, result }); })
124
+ .catch(() => this.fail("protocol")).finally(() => { clearTimeout(timer); this.serverTimers.delete(timer); });
125
+ return;
126
+ }
127
+ if (!Number.isSafeInteger(message.id))
128
+ return this.fail("protocol");
129
+ if (("result" in message) === ("error" in message))
130
+ return this.fail("protocol");
131
+ const pending = this.pending.get(message.id);
132
+ if (!pending)
133
+ return this.fail("protocol"); // duplicates and unknown/late ids
134
+ if ("error" in message) {
135
+ if (!object(message.error) || !Number.isInteger(message.error.code) || typeof message.error.message !== "string")
136
+ return this.fail("protocol");
137
+ return this.fail("remote");
138
+ }
139
+ // Mark authority boundaries synchronously, before later frames in this buffer.
140
+ pending.responseReceived?.();
141
+ this.pending.delete(message.id);
142
+ clearTimeout(pending.timer);
143
+ pending.removeAbort();
144
+ pending.resolve(message.result);
145
+ }
146
+ else {
147
+ if (typeof message.method !== "string" || !("params" in message) || "result" in message || "error" in message)
148
+ return this.fail("protocol");
149
+ this.notification({ method: message.method, params: message.params });
150
+ }
151
+ }
152
+ catch {
153
+ this.fail("protocol");
154
+ }
155
+ }
156
+ fail(reason) {
157
+ if (this.failure)
158
+ return;
159
+ this.failure = new CodexRpcError(reason);
160
+ this.buffer = Buffer.alloc(0);
161
+ for (const pending of this.pending.values()) {
162
+ clearTimeout(pending.timer);
163
+ pending.removeAbort();
164
+ pending.reject(this.failure);
165
+ }
166
+ this.pending.clear();
167
+ for (const timer of this.serverTimers)
168
+ clearTimeout(timer);
169
+ this.serverTimers.clear();
170
+ this.closing = Promise.resolve().then(() => this.transport.close()).catch(() => { throw new CodexRpcError("cleanup"); });
171
+ // Failures remain observable through close(), without an unhandled rejection.
172
+ void this.closing.catch(() => { });
173
+ for (const listener of this.failureListeners) {
174
+ try {
175
+ listener(this.failure);
176
+ }
177
+ catch { /* no raw callback errors */ }
178
+ }
179
+ this.failureListeners.clear();
180
+ }
181
+ async close() { this.fail("closed"); await this.closing; }
182
+ }
@@ -0,0 +1,74 @@
1
+ import { z } from "zod";
2
+ import { codexTurnSchema, type CodexEvent } from "./codex-events.js";
3
+ import type { CodexSessionPolicy } from "./codex-policy.js";
4
+ import { CodexRpcError, type RpcTransport } from "./codex-rpc.js";
5
+ import type { CodexSessionTools } from "./codex-direct-tools.js";
6
+ type Turn = z.infer<typeof codexTurnSchema>;
7
+ declare const commandSchema: z.ZodObject<{
8
+ command: z.ZodArray<z.ZodString>;
9
+ tty: z.ZodDefault<z.ZodBoolean>;
10
+ size: z.ZodOptional<z.ZodObject<{
11
+ cols: z.ZodNumber;
12
+ rows: z.ZodNumber;
13
+ }, z.core.$strict>>;
14
+ timeoutMs: z.ZodDefault<z.ZodNumber>;
15
+ }, z.core.$strict>;
16
+ export type CodexCommandInput = z.input<typeof commandSchema>;
17
+ export interface CodexCommand {
18
+ readonly id: string;
19
+ readonly completed: Promise<{
20
+ exitCode: number;
21
+ }>;
22
+ write(bytes: Uint8Array, closeStdin?: boolean): Promise<void>;
23
+ resize(size: {
24
+ cols: number;
25
+ rows: number;
26
+ }): Promise<void>;
27
+ terminate(): Promise<void>;
28
+ }
29
+ /**
30
+ * Internal protocol driver. It has no spawn, readiness or certification grant;
31
+ * only CodexAppServerBackend may compose it with a real process. Tests can use
32
+ * an in-memory transport without creating an activation path.
33
+ */
34
+ export declare class CodexSession {
35
+ private readonly policy;
36
+ private readonly revalidate;
37
+ private readonly emit;
38
+ private readonly rpc;
39
+ private readonly tools;
40
+ private toolsClosing?;
41
+ private threadId?;
42
+ private startingThread;
43
+ private threadEventId?;
44
+ private turn;
45
+ private commands;
46
+ private ready;
47
+ private accountResponseReceived;
48
+ private closed;
49
+ private closePromise?;
50
+ private constructor();
51
+ static connect(transport: RpcTransport, policy: CodexSessionPolicy, revalidate: () => void, emit: (event: CodexEvent) => void, created?: (session: CodexSession) => void, tools?: CodexSessionTools): Promise<CodexSession>;
52
+ private check;
53
+ private protocolFailure;
54
+ startThread(): Promise<string>;
55
+ private validateThread;
56
+ /** Completes on turn/completed, not the immediate turn/start acknowledgement. */
57
+ runTurn(text: string, options?: {
58
+ signal?: AbortSignal;
59
+ timeoutMs?: number;
60
+ }): Promise<Turn>;
61
+ steerTurn(text: string, expectedTurnId: string): Promise<{
62
+ turnId: string;
63
+ }>;
64
+ interruptTurn(): Promise<void>;
65
+ startCommand(input: CodexCommandInput, signal?: AbortSignal): CodexCommand;
66
+ private settleTurn;
67
+ private receive;
68
+ private callTool;
69
+ private closeTools;
70
+ /** Disconnect and BFF shutdown use the same bounded, connection-owned close. */
71
+ onFailure(listener: (error: CodexRpcError) => void): () => void;
72
+ close(): Promise<void>;
73
+ }
74
+ export {};