Skip to content
← Public packages

@kody/codex

Create and manage OpenAI Agents API (Codex harness) cloud agent sessions.

src/environments/openai-hosted.ts

106 lines · 3.3 KB · TypeScript
import { any, boolean, number, object, optional, parse, string } from 'remix/data-schema'
import { DOCS_DEFAULT_MODEL, DOCS_QUICKSTART } from '../client.ts'
import createSession from '../sessions/create.ts'

const hostedInput = object(
	{
		/** Task for the agent (required unless dryRun) */
		input: optional(any()),
		instructions: optional(string()),
		model: optional(string()),
		/** Extra agent fields (tools, multi_agent, …) */
		agent: optional(any()),
		/** Extra openai_hosted environment fields from docs */
		environment: optional(any()),
		stream: optional(boolean()),
		maxEvents: optional(number()),
		apiKeySecret: optional(string()),
		dryRun: optional(boolean()),
	},
	{ unknownKeys: 'error' },
)

/**
 * Pit-of-success quickstart: create a session with `environment.type:
 * openai_hosted` (OpenAI-managed sandbox). Thin wrapper over
 * `./sessions/create` matching the official Agents API quickstart.
 *
 * @param raw.input - Task string or message array
 * @param raw.instructions - Agent instructions (sensible coding default)
 * @param raw.model - Model id (docs placeholder gpt-6-astra — use one your project allows)
 * @param raw.agent - Extra/override agent fields
 * @param raw.environment - Extra openai_hosted fields merged under type openai_hosted
 * @param raw.stream - Bounded SSE collect on create
 * @param raw.dryRun - Preview without calling OpenAI
 * @param raw.apiKeySecret - Optional alternate secret name
 * @returns Same shape as sessions/create
 *
 * @example
 * import openaiHosted from 'kody:@kody/codex/environments/openai-hosted'
 * const result = await openaiHosted({
 *   input: 'Create tree.py, run it, and show the directory tree output.',
 * })
 */
export default async function openaiHosted(raw: unknown = {}) {
	const input = parse(hostedInput, raw ?? {})
	const model = (input.model || DOCS_DEFAULT_MODEL).trim()
	const instructions =
		(input.instructions ||
			'Write clean code, run it, and report the actual output.').trim()

	const agentExtras =
		input.agent && typeof input.agent === 'object' && !Array.isArray(input.agent)
			? (input.agent as Record<string, unknown>)
			: {}
	const envExtras =
		input.environment &&
		typeof input.environment === 'object' &&
		!Array.isArray(input.environment)
			? (input.environment as Record<string, unknown>)
			: {}

	const agent = {
		...agentExtras,
		model: typeof agentExtras.model === 'string' ? agentExtras.model : model,
		instructions:
			typeof agentExtras.instructions === 'string'
				? agentExtras.instructions
				: instructions,
	}
	const environment = {
		...envExtras,
		type: 'openai_hosted',
	}

	if (input.dryRun === true) {
		return {
			dryRun: true as const,
			wrapper: 'environments/openai-hosted',
			docs: DOCS_QUICKSTART,
			wouldCall: 'sessions/create',
			body: {
				agent,
				environment,
				input: input.input,
				stream: input.stream === true,
			},
			modelNote:
				'Replace model with an id available on your OpenAI project if the docs placeholder is not enabled.',
		}
	}

	if (input.input === undefined || input.input === null || input.input === '') {
		throw new Error(
			'input is required for openai-hosted quickstart (string task or message array).',
		)
	}

	return createSession({
		agent,
		environment,
		input: input.input,
		stream: input.stream,
		maxEvents: typeof input.maxEvents === 'number' ? input.maxEvents : undefined,
		apiKeySecret: input.apiKeySecret,
	})
}