(
options: TextOptions<CodexTextProviderOptions>,
)
| 199 | } |
| 200 | |
| 201 | async *chatStream( |
| 202 | options: TextOptions<CodexTextProviderOptions>, |
| 203 | ): AsyncIterable<StreamChunk> { |
| 204 | const { logger } = options |
| 205 | let bridge: HostToolBridge | undefined |
| 206 | const tempFiles: Array<string> = [] |
| 207 | let cleanupSandbox: SandboxHandle | undefined |
| 208 | const runId = options.runId ?? this.generateId() |
| 209 | const threadId = options.threadId ?? this.generateId() |
| 210 | // Surfaces custom events from bridged tools (e.g. code mode console logs) |
| 211 | // on this run's live output stream. |
| 212 | const channel = createBridgeEventChannel({ |
| 213 | model: this.model, |
| 214 | threadId, |
| 215 | runId, |
| 216 | }) |
| 217 | try { |
| 218 | const sandbox = this.sandboxFrom(options) |
| 219 | cleanupSandbox = sandbox |
| 220 | const cwd = this.workdir(options) |
| 221 | |
| 222 | // Project declarative workspace inputs (MCP/skills) into codex's native |
| 223 | // format. Re-runs each call so rotated secrets re-apply; idempotent ops |
| 224 | // are marker-gated inside the projector. |
| 225 | const projection = options.capabilities |
| 226 | ? getWorkspaceProjection(options.capabilities, { optional: true }) |
| 227 | : undefined |
| 228 | if (projection) await projectCodexWorkspace(sandbox, projection) |
| 229 | |
| 230 | if (options.tools && options.tools.length > 0) { |
| 231 | const provisioner = |
| 232 | (options.capabilities |
| 233 | ? getToolBridgeProvisioner(options.capabilities, { optional: true }) |
| 234 | : undefined) ?? nodeHttpBridgeProvisioner |
| 235 | bridge = await provisioner.provision(options.tools, { |
| 236 | provider: sandbox.provider, |
| 237 | context: options.context, |
| 238 | emitCustomEvent: channel.emitCustomEvent, |
| 239 | ...(options.abortController?.signal |
| 240 | ? { signal: options.abortController.signal } |
| 241 | : {}), |
| 242 | }) |
| 243 | } |
| 244 | |
| 245 | const { prompt, resume } = buildPrompt( |
| 246 | options.messages, |
| 247 | options.modelOptions?.sessionId, |
| 248 | ) |
| 249 | const systemPrompts = normalizeSystemPrompts(options.systemPrompts) |
| 250 | .map((p) => p.content) |
| 251 | .filter((c) => c.trim() !== '') |
| 252 | const fullPrompt = |
| 253 | systemPrompts.length > 0 |
| 254 | ? `${systemPrompts.join('\n\n')}\n\n${prompt}` |
| 255 | : prompt |
| 256 | |
| 257 | const policy = options.capabilities |
| 258 | ? getSandboxPolicy(options.capabilities, { optional: true }) |
no test coverage detected