MCPcopy
hub / github.com/wshobson/agents / CodexAdapter

Class CodexAdapter

tools/adapters/codex.py:328–654  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

326
327
328class CodexAdapter(HarnessAdapter):
329 harness_id = "codex"
330 # Effective cap for the body. Codex's hard limit is 8192 bytes of *injected* skill
331 # content; we leave ~700 bytes of headroom for frontmatter + the pointer note we
332 # add when splitting, so the emitted SKILL.md file stays under the limit.
333 SKILL_BODY_CAP = 7400
334 AGENTS_MD_LINE_CAP = 150
335
336 def __init__(
337 self,
338 output_root: Path | None = None,
339 repo_root: Path | None = None,
340 ) -> None:
341 super().__init__(output_root=output_root)
342 # AGENTS.md is committed at the repo root, not under output_root.
343 # Tests override repo_root to point at a temp dir.
344 self.repo_root = repo_root if repo_root is not None else WORKTREE
345
346 def emit_plugin(self, plugin: PluginSource) -> EmitResult:
347 result = EmitResult()
348
349 # Detect skill/command name collisions before emitting — Codex maps both into
350 # `.codex/skills/<plugin>__<name>/`, so duplicates would silently overwrite.
351 skill_names = {s.name for s in plugin.skills}
352 command_collisions = {c.name for c in plugin.commands} & skill_names
353
354 # Second-order collision: if a skill is literally named `<x>__command`, the
355 # `__command` suffix the adapter uses for collision-resolution would clash
356 # with it. Detect and route the command-skill to `__cmd` instead.
357 skill_suffix_conflicts: set[str] = set()
358 for cmd_name in command_collisions:
359 if f"{cmd_name}__command" in skill_names:
360 skill_suffix_conflicts.add(cmd_name)
361 result.warnings.append(
362 f"plugin `{plugin.name}` has skill `{cmd_name}`, command `{cmd_name}`, "
363 f"AND skill `{cmd_name}__command` — command-skill routed to "
364 f"`{cmd_name}__cmd` to avoid second-order collision"
365 )
366
367 for skill in plugin.skills:
368 self._emit_skill(plugin, skill, result)
369 for agent in plugin.agents:
370 self._emit_agent(plugin, agent, result)
371 # Codex deprecated prompts in favor of skills. Synthesize a skill from each command.
372 for cmd in plugin.commands:
373 collides = cmd.name in command_collisions
374 suffix_conflict = cmd.name in skill_suffix_conflicts
375 self._emit_command_as_skill(
376 plugin,
377 cmd,
378 result,
379 collides=collides,
380 fallback_suffix=suffix_conflict,
381 )
382
383 # Per-plugin Codex manifest for native marketplace install (reads source skills).
384 self._emit_codex_plugin_manifest(plugin, result)
385

Calls

no outgoing calls