Commit Graph
34 Commits
Author SHA1 Message Date
Anthony Tafoya 3fd08b5405 Back off failed cloud skill and plugin catalog refreshes (#55968)
## Why

Failed cloud discovery previously retried before each model step. Apply a cooldown across steps and turns to avoid repeated discovery requests while a provider remains unavailable.

## What changed

- Share per-thread retry backoff logic between cloud skill and plugin catalogs, starting at 30 seconds and doubling to a maximum of 5 minutes.
- Scope cooldowns to authentication and MCP resource generations so account changes and reconnects permit immediate recovery.
- Clear backoff after successful discovery or configuration resets, while allowing cancelled refreshes to retry immediately.

## Testing

Update lifecycle and concurrency tests to cover shared cooldowns, reconnect recovery, and cancellation. Use paused time to verify exponential delays, the 5-minute cap, and backoff across turns.

GitOrigin-RevId: 30dab5ceba51e8ad64c0794c1729719e99f577ce
2026-10-21 19:22:57 +00:00
Anthony Tafoya a309f9206a Integrate discovery V2 with step-scoped skill catalogs (#55322)
## What changed

- Build executor skill catalogs from discovery V2 inventories without reopening host paths or falling back to legacy discovery.
- Merge Cloud and executor skills by remote plugin identity and skill name, retaining Cloud metadata and accepted provider read routes. Apply plugin selection and disablement before merging.
- Share a stable catalog across each step's rendering, list/read tools, and explicit and implicit skill invocations.
- Preserve unmatched executor entries when Cloud catalogs are unavailable or partial; only complete Cloud catalogs disable unmatched remote entries.
- Bind discovery caches to captured environments and executor sessions, and refresh MCP when V2 inventories change. Preserve pending invalidations when forced MCP refreshes fail.

## Testing

Add regression coverage for V2 inventory sharing and refresh, environment isolation, catalog merging, partial Cloud results, disabled plugins, and catalog consistency across steps and read routes.

GitOrigin-RevId: 842bdcbc9e19364dd69a9abf9e48330b7425a76c
2026-10-19 17:02:20 +00:00
pakrym-oai ce0323f2f2 Support typed content in contextual prompt fragments (#54776)
## Why

Contextual fragments and extension-owned world-state sections currently return strings, limiting them to text content.

## What changed

- Return `ContentItem` from fragment bodies and rendering, preserving classification and attribution. Apply text markers only to `InputText`; pass other content through unchanged.
- Allow extension prompt and world-state contributions to carry typed content, and preserve media in context-window hints.
- Hash non-text world-state fragments by their serialized content and role while retaining the existing text hashing behavior.
- Add shared content-to-tool-output conversion that preserves image references, image detail, and audio.

## Testing

Add coverage for typed world-state hashing and preservation of image content and attribution. Expand code-mode output tests to cover input text, output text, file-backed and inline images, and audio.

GitOrigin-RevId: 2ed00d466a3f169b151202f3eef71e667ea64be1
2026-10-17 04:02:21 +00:00
Krish Chainani aabf13307a Store generated image items as attachment references (#54398)
## What changed

- Upload generated images to the attachment store and expose `fileId` in image-generation items when available, with inline `result` fallback on upload or decoding failure.
- Preserve file references through legacy events, persisted rollouts, thread history, and task output summaries. Keep model-facing image preparation separate.
- Add attachment request tags and mark generated-image uploads with `usage=image_gen`, preserving the thread's ephemeral setting.
- Update public schemas and SDK types to accept either image representation, retain the Python `ImageGenerationThreadItem` alias, and prefer `fileId` when reading records containing both fields.

## Testing

Add coverage for file-backed generation and rollout persistence, legacy history replay, inline and transitional serialization, task output visibility, and Python SDK alias compatibility.

GitOrigin-RevId: f7a2bb5707e2f277348a547a988bc33c8e96d891
2026-10-15 19:51:22 +00:00
Anthony Tafoya 20b4ff2f35 Enrich V2 capability discovery with resolved plugin and skill metadata (#53763)
## What changed

- Return qualified skill names such as `team:deploy` and parsed `dependencies` and `policy` instead of a separate namespace and raw metadata file. Share `agents/openai.yaml` parsing and validation between skill loaders and executor discovery.
- Include each standalone skill's search-root ID and path in `discoveryRoot`, while accepting responses from older executors that omit it.
- Add plugin `displayName`, falling back to the manifest name or installation directory.
- Materialize inline MCP declarations in `mcpConfig` with the manifest as their source path, and report incomplete discovery when declared MCP or Apps configuration files have no returned contents.

## Testing

Add coverage for JSON round trips, omitted `discoveryRoot`, optional and invalid skill metadata, qualified names, display-name fallbacks, and inline MCP configuration. Verify standalone search roots survive cached discovery and sandboxed RPC responses.

GitOrigin-RevId: 4124972444ad7c2fb8c6418acbf9a589d797fad2
2026-10-13 20:40:38 +00:00
sayan-oai 9561a34531 Keep plugin and skill snapshots scoped to each step (#50050)
## Why

Environment changes and overlapping catalog refreshes can cause a step to use another step's selected plugins or executor skills. Model context and skill tools need to agree on the capabilities captured for that step.

## What changed

- Resolve selected plugins from each step's ready capability roots, honoring disabled plugins, and retain the snapshot with the step's extension data.
- Use that snapshot for skill attribution in World State and the first step's active-plugin telemetry.
- Return executor skill catalogs directly from refresh so overlapping requests render their own results while retaining thread caches.

## Testing

Add regression coverage for overlapping executor catalogs and environment changes during step preparation. Verify that `skills.list` retains the original step's skills, the next step advertises the new skills, and disabled executor and plugin skills remain absent from model context.

GitOrigin-RevId: 37d3cbe8c7e062fd06290aa985ada4d3b3462d43
2026-10-01 17:44:52 +00:00
vkg-oai 0f8df3d214 Move shadow skill ranking off the turn preparation path (#49812)
## Why

Shadow skill selection runs synchronously during turn input construction, making turn preparation wait for experimental rankings.

## What changed

Run ranking on background blocking workers with a process-wide limit of two concurrent rankings. Wait for capacity in the background and hold each slot until its blocking worker finishes, even if the async evaluation is cancelled.

Freeze catalog, query, and relevance history at turn start. Record eligible invocations immediately for future turns, then score queued observations against the frozen rankings once they are ready, including observations queued before the turn state is dropped.

## Testing

Add tests for turn preparation and history updates while ranking is blocked, deferred invocation scoring against each turn's history, and shared ranking capacity that remains occupied until cancelled workers finish. Update existing metric assertions to collect asynchronous observations across snapshots.

GitOrigin-RevId: f7776e9aaeb45d3a792de167abbe35f7ec5a513e
2026-10-01 01:49:59 +00:00
vkg-oai e72da2b538 Stabilize skill catalogs across executor availability changes (#48353)
## Why

Changes in executor availability can alter cloud skill catalog rendering under a shared budget and repeat an unchanged executor catalog when it reconnects.

## What changed

- Cap cloud skills at three quarters of the metadata budget initially, leaving the remaining budget and unused cloud allowance for filesystem skills. Reduce the cloud cap only when doing so allows all skill entries to fit; description truncation alone does not trigger rebalancing.
- Persist the allocation across disconnects, compaction, and thread resume. Recompute it when the cloud inventory or total budget changes.
- Emit a short availability update when an unchanged selected-environment catalog returns and its full text remains in history. Reinject the full catalog when that text is missing.

## Testing

Add coverage for allocation stability, catalog and budget changes, omission handling, and full catalog reinjection after compaction and resume. Extend the selected capability stack test to verify reconnection avoids repeating the catalog.

GitOrigin-RevId: 839fe98024e00c4082a46e6a40675e15fd2c16c6
2026-09-26 04:19:46 +00:00
Anthony Tafoya f3037cafd3 Refresh host-supplied cloud skills at turn startup (#47074)
## What changed

- Replace the built-in orchestrator skill provider with a host-supplied cloud provider, using `cloud` authority and `c` root aliases in skill tools and prompts.
- Add `cloud.skills.enabled`, defaulting to true but requiring a supplied provider. Keep `orchestrator.skills` accepted as a legacy no-op setting, and remove the app server's automatic orchestrator provider registration.
- Discover cloud skills once per turn during cancellable startup. Serve catalog snapshots to prompts and tools without triggering discovery or retries.
- Scope cached catalogs and resources to authentication state. Preserve them on refresh failures within the same scope, invalidate them when that scope changes, and reject late discovery or read results from replaced cache generations.
- Reuse executor discovery catalogs only when successful discovery inputs and bundled-skill settings match.

## Testing

Add coverage for per-turn refresh, skill removal, same-account failures and reconnects, authentication changes, and stale in-flight results. Update configuration and tool tests for cloud authority, provider gating, and resource reads without an executor.

GitOrigin-RevId: c57e38ec7dcc880c0d4c8a2995adfd3e28301079
2026-09-21 17:28:14 +00:00
Tamir Duberstein c941572917 Honor response budgets when reading skill resources (#40491)
## Why

`skills.read` paginated resources against a fixed response limit, so a page could exceed a smaller tool-call response budget.

## What changed

- Size each serialized `skills.read` page to the current call's response budget, accounting for JSON escaping and UTF-8 boundaries.
- Cache one bounded executor-resource snapshot per thread so cursor continuations return consistent contents without rereading the file. Replace the snapshot when another resource is read, and reject stale cursors after a reread.
- Tie cached executor snapshots to the selected environment and sandbox context without keeping the environment alive.

## Testing

- Cover budget-constrained reads, escaped and multibyte contents, multi-page reconstruction, changed resources, snapshot eviction, and expired turn-scoped access.

GitOrigin-RevId: e515935b82771b3f29b3fb91ea7a7a72e19a65ee
2026-08-24 23:00:57 +00:00
rphilizaire-openai c8f673fddc Track resource-backed skill invocations (#38066)
## What changed

- Emit skill invocation analytics when a resource-backed skill is explicitly selected or its main resource is successfully read from the first page.
- Preserve provider-supplied skill IDs and user scope when available, and derive a stable ID from the main resource otherwise.
- Deduplicate repeated implicit reads of the same main resource within a turn.

## Testing

- Extend the orchestrator skill integration test to cover explicit and implicit invocation events, stable fallback IDs, failed reads, and repeated-read deduplication.

GitOrigin-RevId: 7d8453b31b5a2205847e65cda2c46183d6c97b45
2026-08-11 19:52:54 +00:00
felixxia-oai 45f8cafa4e Remove the codex-core-skills crate (#37505)
## What changed

- Move `SkillLoadOutcome` and its implicit-path indexing into
  `codex-skills-extension`.
- Import shared skill types directly from `codex-skills` and keep the skill
  prompt size limit with the extension renderer that uses it.
- Remove `codex-core-skills` from the Cargo workspace and dependent crates.

GitOrigin-RevId: 4e9e84909fa2f692bcc94af990bb4671affd776f
2026-08-07 21:36:33 +00:00
felixxia-oai 1a7519fa07 Move host skill root resolution into the skills extension (#36943)
## What changed

- Move config-layer, user, system, plugin, extra, and repository skill-root
  resolution from `core-skills` into the host skills extension.
- Keep the core loader focused on loading explicit `SkillRoot` values.
- Relocate and expand tests for root precedence, deduplication, repository
  ancestry, plugin metadata, and concurrent probing.

GitOrigin-RevId: 3b95cf28101b8b4d64d54079d202154dad560aab
2026-08-04 18:41:55 +00:00
felixxia-oai 02bc1dd796 Move the host skills service into the skills extension (#36921)
## What changed

- Move host skill discovery, snapshot caching, and configuration handling from
  `codex-core-skills` to `codex-skills-extension`.
- Rename `SkillsService` and `SkillsLoadInput` to `HostSkillsService` and
  `HostSkillsLoadInput` to distinguish the host implementation from other skill
  providers.
- Keep shared loading primitives and skill outcome modeling in
  `codex-core-skills`.

GitOrigin-RevId: d81a21791d2ef8c066e157e7e538b8cb7ee4c24b
2026-08-04 16:28:46 +00:00
felixxia-oai 1669c2403f Add host skill root loading (#36884)
## What changed

- Add a loader that discovers skills from canonical host roots and preserves their `SkillScope`.
- Skip hidden directories, follow directory symlinks for user, repo, and admin scopes, and ignore them for system skills.
- Load dependencies and policy from optional `agents/openai.yaml` metadata without rejecting a skill when that metadata is missing or invalid.
- Resolve plugin and symlink namespaces while retaining host paths and reporting per-skill errors outside system scope.

## Testing

Add coverage for frontmatter and metadata loading, invalid optional metadata, hidden directories, plugin namespaces, and scope-specific symlink discovery.

GitOrigin-RevId: ac436d93b5943b7eaae32143e43367921dd1c350
2026-08-04 11:19:27 +00:00
felixxia-oai 77ce1d10aa Move direct executor skill discovery into the skills extension (#36880)
## What changed

- Add extension-owned discovery and namespace resolution for skills loaded directly through an `ExecutorFileSystem`.
- Preserve hidden and symlinked skills, nested plugin namespaces, optional `agents/openai.yaml` metadata, product restrictions, and deterministic ordering.
- Reuse the filesystem walk inventory and bound concurrent skill, metadata, and manifest reads.
- Route direct executor catalog loading through the new extension loader.

## Testing

- Cover namespace lookup, metadata probing, walk reuse, concurrent reads, and parity with the existing environment loader.

GitOrigin-RevId: 4e0b821eb84d03f0dc1c2dee7b2b9a072ee3fd44
2026-08-04 11:04:45 +00:00
felixxia-oai 4c25d6cc5c Move executor skill bundle loading into the skills extension (#36877)
## What changed

- Move parsing of pre-discovered executor skill bundles from `core-skills` to
  the skills extension.
- Expose shared `SKILL.md` frontmatter parsing from `codex-skills` so direct
  and pre-discovered loading use the same validation and repair behavior.

## Testing

- Add parity coverage for direct and pre-discovered executor skill catalogs,
  including plugin namespaces, metadata, product policy, and warnings.
- Add a snapshot for the resulting pre-discovered executor catalog.

GitOrigin-RevId: c5f888226fa5600bd8b90f5682400da39a5db5ff
2026-08-04 10:41:01 +00:00
felixxia-oai 5e8b22488f Use the host skill provider catalog in world state (#36309)
## What changed

- Load and cache the host skill provider catalog during world-state contribution.
- Render host skill listings from that catalog with Core-compatible budgeting, while preserving Core's full prompt injection for selected host skills.
- Reuse the cached host catalog for shadow selection, including when skill listings are disabled.
- Preserve an empty Core-compatible skills fragment when every entry exceeds the metadata budget, and make budget warnings independent of the configured percentage.

## Testing

- Cover provider-backed host listings, selected-skill prompt injection, shadow selection, disabled listings, oversized prompts, empty fragments, metrics, and warnings.

GitOrigin-RevId: b6b2d8ea14386356094cff5783d121d74657e9e3
2026-07-31 11:01:47 +00:00
jif 7c71783135 Expose executor skills through skill tools (#35184)
## What changed

- Add executor authority support to `skills.list` and `skills.read` for skills from selected capability roots.
- Allow `skills.read` to load package-relative resources referenced by an executor skill while keeping reads within the selected package.
- Paginate skill listings and resource contents with bounded response sizes and stale-cursor validation.
- Resolve executor filesystems per sampling step so skill tools use the active selected capability roots.

## Testing

- Extend the app-server executor skill test to list an executor skill, read its main `SKILL.md`, and read a paginated reference resource.
- Cover visibility filtering, metadata bounds, pagination, invalid cursors, package boundaries, and resource size limits.

GitOrigin-RevId: 1b5de95d5d1b9f79c34d2879d6e67f24401e9c29
2026-07-24 13:46:20 +00:00
felixxia-oai 37eef7bacc Scale skill metadata budgets with model context windows (#34626)
## Why

A fixed character limit does not account for the different context-window sizes supported by models.

## What changed

- Budget extension-rendered skill metadata at 2% of the resolved model context window, capped at 4,000 tokens.
- Keep the existing 8,000-character fallback when model context metadata is unavailable.
- Include the omission marker in the budget and still emit it when no skill entry fits.
- Apply the same resolved budget to executor and host skill catalogs assembled for a turn.

## Testing

- Cover proportional and capped budgets, multibyte fallback accounting, and omission-marker behavior.
- Verify through the production turn path that larger model context windows include more catalog entries without exceeding the computed budget.

GitOrigin-RevId: 4667293f1594de4dd605b32b9fa4255d26772c0f
2026-07-21 22:16:27 +00:00
felixxia-oai 56c11cf658 Move shared skill models into codex-skills (#34429)
## What changed

- Define and export skill metadata, policy, dependency, interface, and configuration rule types from `codex-skills`.
- Update core, plugin, and extension consumers to use the shared models while retaining compatibility re-exports from `codex-core-skills`.
- Share product-restriction handling between host and environment skill metadata.

## Testing

- Add unit coverage for default and explicit implicit-invocation and product policies.

GitOrigin-RevId: 9093469f8fff8e2d902dc9781235f64709827a87
2026-07-20 23:22:48 +00:00
jif a47c661ea9 Add fielded BM25 to shadow skill selection (#33605)
## What changed

- Add a bounded BM25 selector that ranks skills across name, short-description,
  and description fields, weighting names most heavily and rare terms more highly.
- Run the selector alongside the weighted lexical method in the shadow-selection
  experiment, with deterministic tie-breaking and existing per-method metrics.
- Add unit coverage for field weighting, rare-term ranking, unmatched queries,
  and input limits.
- Remove the implicit-invocation integration test and its telemetry development
  dependency.

GitOrigin-RevId: e5ac6a1f0d6a1f68b194467ef7da48adf4a88d7c
2026-07-16 13:57:47 +00:00
jif c100109280 Add shadow metrics for lexical skill selection (#32761)
## What changed

- Add an opt-in `skill_search` feature that ranks prompt-visible skills against each turn's user input with a bounded weighted lexical selector.
- Keep the ranked selection out of model-visible context and record metrics for selection cost, catalog reduction, and whether later implicit or `skills.read` invocations matched the ranked candidates.
- Include host-provided skills in the experiment catalog without changing the rendered skill catalog.

## Testing

- Add selector unit tests covering ranking, limits, truncation, stop words, and deterministic tie-breaking.
- Add extension tests covering turn-local invocation recording and host-skill shadow selection.

GitOrigin-RevId: 4d00a1c805ea8b391d6c6ac6a8450afa88ca3e25
2026-07-13 10:38:37 +00:00
jif 220f5b76b2 Load executor skills without host path conversion (#29626)
## Why

After #28918, selected skill roots are `PathUri`, but the executor skill
provider still converts them to the app-server host's `AbsolutePathBuf`.
A foreign Windows root therefore cannot be discovered by a Unix host,
and the inverse has the same problem.

This PR keeps executor skill discovery and reads on the filesystem that
owns the selected root while reusing the existing skill rules.

## What changed

- Generalize the existing skill traversal to operate on `PathUri`
through `ExecutorFileSystem`, preserving its depth, directory, symlink,
and sibling-metadata concurrency behavior.
- Add a small environment skill loader that reuses the shared discovery,
frontmatter validation, dependency parsing, product policy, and
prompt-visibility rules.
- Keep the environment id and entrypoint `PathUri` in the skill catalog,
then route `skills.read` back through the same environment filesystem.
- Preserve the executor's path convention when deriving catalog handles,
including literal backslashes in POSIX filenames.
- Resolve plugin namespaces from nearby manifests through URI-native
filesystem reads.
- Cover foreign Windows roots, executor-owned reads, namespaces,
metadata, policy, and path identity.

```text
selected root (PathUri)
        |
        v
shared discovery over ExecutorFileSystem
        |
        v
environment-bound catalog entry --skills.read--> same ExecutorFileSystem
```

No second filesystem abstraction or duplicate traversal implementation
is introduced.

## Stack

1. #29614 — add lexical `PathUri` containment.
2. #29620 — share URI-native manifest path resolution.
3. #28918 — keep selected plugin roots and resources URI-native.
4. **This PR** — load executor skills without host path conversion.
5. #29628 — resolve executor MCP working directories without host path
conversion.
2026-06-23 23:26:06 +01:00
Adam Perry @ OpenAI 5a56caf18c [codex] Remove async_trait from first-party code (#27475)
## Why

First-party async traits should expose their `Send` contracts explicitly
without requiring `async_trait`. This completes the migration pattern
established in #27303 and #27304.

## What changed

- Replaced the remaining first-party `async_trait` traits with native
return-position `impl Future + Send` where statically dispatched and
explicit boxed `Send` futures where object safety is required.
- Kept implementations behavior-preserving, outlining existing async
bodies into inherent methods where that keeps the diff reviewable.
- Removed all direct first-party `async-trait` dependencies and the
workspace dependency declaration.
- Added a cargo-deny policy that permits `async-trait` only through the
remaining transitive wrapper crates.
- Updated `rand` from 0.8.5 to 0.8.6 to resolve RUSTSEC-2026-0097 and
keep the full cargo-deny check passing.

## Validation

- `just test -p codex-exec-server`: 216 passed, 2 skipped.
- `just test -p codex-model-provider`: 39 passed.
- `just test -p codex-core` and `just test`: changed tests passed;
remaining failures are environment-sensitive suites unrelated to this
migration.
- `cargo deny check`
- `just fix`
- `just fmt`
- `cargo shear`
- `just bazel-lock-check`
2026-06-11 18:16:39 -07:00
Adam Perry @ OpenAI b2a4e3be27 [codex] migrate ExecutorFileSystem paths to PathUri (#27424)
## Why

We're moving exec-server to use PathUri for its internal path
representations.

## What

Move `ExecutorFileSystem` APIs to use `PathUri` instead of
`AbsolutePathBuf`. Future changes will convert higher-level parts of
exec-server.
2026-06-11 18:44:18 +00:00
jif 7c2394808e skills: decouple the skills extension from core (#27413)
## Why

`ext/skills` currently depends on `codex-core` for two host concerns:
reading the concrete `Config` type and borrowing core-owned
model-context fragment types. That coupling prevents the extension from
being assembled independently above core and leaves context that belongs
to the skills feature owned by core.

This stacked PR introduces the host boundary needed for the broader
extension migration while intentionally preserving existing skills
behavior. It is stacked on #27404.

## What changed

- Adds a small public `SkillsExtensionConfig` view and makes skills
installation generic over the host config type.
- Requires the host to map its config into that view; app-server
supplies the current `Config` values.
- Moves the available-skills and selected-skill context fragment
implementations into `ext/skills`, preserving their roles, markers, and
rendered bytes.
- Removes the direct `codex-core` dependency from
`codex-skills-extension`.
- Keeps local discovery, invocation, side effects, and the
`codex-core-skills` compatibility types unchanged for later staged PRs.

## Behavior

This adds no capability and is intended to have no user-visible or
model-visible behavior change. The install API and ownership boundary
change internally; emitted skills context remains byte-for-byte
compatible.

## Validation

- Updates the skills extension integration coverage to use a host-owned
test config.
- Asserts the complete rendered catalog and selected-skill fragments,
including their roles and markers.
- `just bazel-lock-check`
- Rust tests and Clippy were not run locally per request; CI will run
them.
2026-06-11 14:03:53 +02:00
jif e6757bba91 nit: cap error (#27585)
Just cap an error that could end up in the model context
2026-06-11 12:52:46 +02:00
jif 7b3eb8e4bc skills: expose remote skill resource tools (#27388)
## Why

PR #27387 makes backend plugin skills discoverable and invocable without
an executor, but resources referenced by those skills still sit behind
the generic MCP resource surface. The model needs a skills-owned API
that preserves the provider authority and package boundary instead of
treating remote resources like local files.

This is stacked on #27387.

## What

- Adds one `skills` namespace with bounded `list` and `read` tools for
remote skill providers.
- Revalidates `authority + package` against the live remote catalog on
every read, then routes the opaque resource ID back through that
provider.
- Allows the backend provider to read canonical child `skill://`
resources while rejecting cross-package, non-canonical, query, fragment,
and traversal-shaped URIs.
- Caps each serialized tool result at 8 KB. Lists are paginated; reads
return an opaque continuation cursor.
- Marks the JSON output as external context so memory generation can
apply its normal suppression policy.
- Deliberately does not add `skills.search`; that waits for a bounded
plugin-service search contract.

## Tool contract

Pseudo-Python matching the wire shape:

```python
from typing import Literal, NotRequired, TypedDict


class RemoteSkillAuthority(TypedDict):
    kind: Literal["remote"]
    id: str  # e.g. "codex_apps"


class RemoteSkill(TypedDict):
    authority: RemoteSkillAuthority
    package: str  # opaque provider-owned package ID
    name: str
    description: str
    main_resource: str  # opaque provider-owned SKILL.md ID


class SkillsListParams(TypedDict):
    cursor: NotRequired[str]


class SkillsListResult(TypedDict):
    skills: list[RemoteSkill]
    next_cursor: str | None
    warnings: list[str]
    truncated: bool


class SkillsReadParams(TypedDict):
    authority: RemoteSkillAuthority  # copied from skills.list
    package: str  # copied from skills.list
    resource: str  # provider-owned child resource ID
    cursor: NotRequired[str]  # copy next_cursor to continue


class SkillsReadResult(TypedDict):
    resource: str
    contents: str
    next_cursor: str | None
    truncated: bool


class Skills:
    def list(self, params: SkillsListParams) -> SkillsListResult: ...
    def read(self, params: SkillsReadParams) -> SkillsReadResult: ...
```

There is one namespace for all remote skills, not one tool or MCP server
per skill. No resource ID is converted into a filesystem path.

## Backend dependency

`/ps/mcp` must support direct reads of child resources such as
`skill://plugin_demo/deploy/references/deploy.md`. This PR implements
and tests the Codex side of that contract; production child reads remain
dependent on the corresponding plugin-service support. Search remains
out of scope until that service exposes a bounded search/resource API.

## Validation

- Added an app-server integration test covering `skills.list` followed
by `skills.read` with no executor.
- Ran `just fmt`.
- Ran `just bazel-lock-update` and `just bazel-lock-check`.
- Did not run Rust tests or Clippy locally, per request; CI will run
them.
2026-06-11 12:38:04 +02:00
jif a287c5dffd skills: make backend plugin skills invocable without an executor (#27387)
## Why

#27198 made the extension-owned `codex_apps` MCP connection the hosted
plugin runtime, but its `mcp/skill` resources still bypassed the skills
extension. App-server could list and read those resources through
generic MCP APIs, but a thread with no selected environment did not
expose them in the model's skills catalog or load their `SKILL.md`
through `$skill`.

Hosted skills should stay remote while using the same typed catalog,
source authority, deduplication, bounded contextual catalog, and
selected-skill prompt injection as host and executor skills. They should
not be downloaded or exposed as ambient filesystem paths.

## What changed

- Add a session-scoped `McpResourceClient` over the replaceable MCP
connection manager so resource list/read calls follow startup and
refresh replacements.
- Add a `BackendSkillProvider` that pages `codex_apps` resources,
accepts bounded and validated `mcp/skill` entries, and reads a selected
skill's `SKILL.md` through the same MCP connection.
- Register the remote provider in app-server and include it in the
skills catalog even when a thread has no selected capability roots or
executor.
- Contribute hosted skill metadata through the bounded
`AvailableSkillsInstructions` developer-context path, exclude remote
entries from per-turn catalog injection, and classify `<skills>`
messages as contextual developer content so rollback can trim and
rebuild them correctly.

## Testing

- Extend the app-server MCP resource integration test with
`environments: []` to exercise two-page discovery, filter a
non-`mcp/skill` resource, verify the escaped developer catalog entry and
user-role `<skill>` fragment containing the fetched `SKILL.md`, and
preserve generic MCP resource reads.
- Add core event-mapping coverage that classifies `<skills>` developer
messages as contextual history.
2026-06-11 11:28:16 +02:00
jif d2f6d23c6c Remove async-trait from extension contributors (#27383)
## Why

Extension contributors are registered behind `dyn Trait` objects, so
native `async fn`/RPITIT methods would make these traits
non-object-safe. Spell out the boxed, `Send` future contract directly so
`extension-api` no longer needs `async-trait` while retaining the
existing runtime model.

## What changed

- add a shared `ExtensionFuture` alias and use it for asynchronous
contributor methods
- migrate production and test implementations to return `Box::pin(async
move { ... })`
- remove `async-trait` dependencies where they are no longer used,
keeping it dev-only where unrelated test executors still require it

## Behavior

No behavior change is intended. Contributor futures remain boxed,
`Send`, dynamically dispatched, and lazily executed; cancellation and
callback ordering stay unchanged.

## Testing

- `just test -p codex-extension-api` (11 passed)
- affected extension crates (64 passed)
- targeted `codex-core` contributor tests (14 passed)
- `just fmt`
- `just bazel-lock-update`
- `just bazel-lock-check`

A broad local `codex-core` run compiled successfully but encountered
unrelated sandbox and missing test-binary fixture failures; CI will run
the full checks.
2026-06-10 14:31:09 +02:00
jif 89ac3ec27c Load selected executor skills through extensions (#27184)
## Why

CCA is moving toward a split runtime where the orchestrator may not have
a filesystem, while executors can expose preinstalled plugins and
skills. A thread therefore needs to select capabilities without asking
app-server or core to interpret executor-owned paths through the
orchestrator's filesystem.

The longer-term model is broader than executor skills:

- A plugin is a bundle of skills, MCP servers, connectors/apps, and
hooks.
- A plugin root can be local, executor-owned, or hosted by a backend.
- Components inside one plugin can use different access and execution
mechanisms. A skill may be read from a filesystem or through backend
tools; an HTTP MCP server can run without an executor; a stdio MCP
server or hook needs an execution environment.
- Core should carry generic extension initialization data. The extension
that owns a component should discover it, expose it to the model, and
invoke it through the appropriate runtime.

This PR establishes that architecture through one complete vertical:
selecting a root on an executor, discovering the skills beneath it,
exposing those skills to the model, and reading an explicitly invoked
`SKILL.md` through the same executor.

## Contract

`thread/start` gains an experimental `selectedCapabilityRoots` field:

```json
{
  "selectedCapabilityRoots": [
    {
      "id": "deploy-plugin@1",
      "location": {
        "type": "environment",
        "environmentId": "workspace",
        "path": "/opt/codex/plugins/deploy"
      }
    }
  ]
}
```

The root is intentionally not classified as a "plugin" or "skill" in the
API. It can point at a standalone skill, a directory containing several
skills, or a plugin containing skills and other components. This PR only
teaches the skills extension how to consume it; later extensions can
resolve MCP, connector, and hook components from the same selection.

The platform-supplied `id` is stable selection identity. The location
says which runtime owns the root and gives that runtime an opaque path.
App-server does not inspect or canonicalize the path.

## What changed

### Generic thread extension initialization

App-server converts selected roots into `ExtensionDataInit`. Core
carries that generic initialization value until the final thread ID is
known, then creates thread-scoped `ExtensionData` before lifecycle
contributors run.

This keeps `Session` and core independent of the capability-selection
contract. The initialization value is consumed during construction; it
is not retained as another long-lived `Session` field.

### Executor-backed skills

The skills extension now owns an `ExecutorSkillProvider` that:

- resolves the selected environment through `EnvironmentManager`
- discovers, canonicalizes, and reads skills through that environment's
`ExecutorFileSystem`
- contributes the bounded selected-skill catalog as stable developer
context
- reads an explicitly invoked skill body through the authority that
listed it
- warns when an environment or root is unavailable
- never falls back to the orchestrator filesystem for an executor-owned
root

Skill catalog and instruction fragments have hard byte bounds, which
also bound them below the 10K-token per-item context limit. If a
selected executor skill has the same name as a legacy local skill, the
executor selection owns that invocation and the local body is not
injected a second time.

Existing local and bundled skill loading remains in place. Omitting
`selectedCapabilityRoots` therefore preserves current local-only
behavior.

## Current semantics

- Only environment-owned locations are represented in this first
contract.
- Roots are resolved by the destination extension, not by app-server or
core.
- An unavailable executor or invalid root produces a warning and no
capabilities from that root; it does not trigger a local-filesystem
fallback.
- Selection applies to a newly started active thread.
- MCP servers, connectors, and hooks beneath a selected plugin root are
not activated yet.
- Selection is not yet persisted or inherited across resume, fork, or
subagent creation. Existing local capabilities continue to behave as
they do today in those flows.

## Planned vertical follow-ups

1. **Hosted HTTP MCP:** add an extension-backed HTTP MCP source that
works without an executor, then replace the special-purpose MCP plugins
loader with that implementation.
2. **Executor MCP:** register and execute stdio MCP servers through the
environment that owns the selected plugin root.
3. **Backend skills:** add a hosted skill source whose catalog and
bodies are accessed through extension tools rather than a filesystem.
4. **Connectors and hooks:** activate those components through their
owning extensions, using the same selected-root boundary and
component-specific runtime.
5. **Durable selection:** define the desired-selection lifecycle,
persist it, and make resume, fork, and subagent inheritance explicit
rather than accidental.
6. **Local convergence:** incrementally route existing local plugin,
skill, and MCP loading through the same extension model while preserving
current local behavior.

Each follow-up remains reviewable as an end-to-end capability. The
platform selects roots, generic thread extension data carries the
selection, and the owning extension resolves and operates its component.

## Verification

Coverage added for:

- app-server end-to-end discovery and explicit invocation of a skill
inside an executor-selected plugin root
- exclusive invocation when a selected executor skill collides with a
local skill name
- executor filesystem authority for discovery, canonicalization, and
reads
- thread extension initialization before lifecycle contributors run
- stable executor catalog context, explicit invocation, context
rebuilding, hidden skills, and preserved host/remote catalog behavior

Targeted protocol, core-skills, skills-extension, core lifecycle, and
app-server executor-skill tests were run during development.
2026-06-09 19:51:54 +02:00
jif 96d2d2f68c Implement v1 skills extension prompt injection (#26167)
## Why

The skills extension needs a real turn-time path before host, executor,
or remote skills can be routed through it. The previous code was mostly
a placeholder catalog/provider sketch, so there was no bounded
available-skills fragment, no source-owned `SKILL.md` read, and no place
for warnings or per-turn selection state to live.

This PR makes `ext/skills` the authority-preserving flow for listing
candidate skills and injecting only explicitly selected main prompts,
without adding more of that logic to `codex-core`.

## What changed

- Expands catalog entries with `main_prompt`, display path, short
description, dependency metadata, enabled/prompt visibility flags, and
authority/package-aware read requests.
- Replaces the placeholder `providers/*` modules with
`SkillProviderSource` and `SkillProviders`, routing list/read/search
calls by source kind and surfacing provider failures as warnings.
- Adds bounded available-skills rendering and `SKILL.md` main-prompt
truncation before the fragments enter model context.
- Resolves explicit skill selections from structured `UserInput::Skill`,
skill-file mentions, `skill://...` paths, and plain `$skill` text
mentions, then reads selected prompts through their owning provider.
- Stores mutable per-thread skills config and per-turn
catalog/selection/warning state.
- Adds `install_with_providers` so tests and future host wiring can
supply concrete providers.

## Testing

- Not run locally.
- Added `codex-rs/ext/skills/tests/skills_extension.rs` coverage for
available-catalog injection, selected prompt injection through the
owning provider, and prompt-hidden skills that remain invokable.
2026-06-03 16:24:16 +02:00
jif 2d385e166c feat: add skills extension scaffold (#25953)
## Disclaimer
This is only here for iteration purpose! Do not make any code rely on
this

## Why

Skills still live behind `codex-core` discovery and injection paths, but
the extension system needs an authority-aware home before that logic can
move. This adds that boundary without changing current skills behavior,
and keeps host, executor, and remote skills distinct so future
list/read/search flows do not collapse back to ambient local paths.

## What changed

- Add the `codex-skills-extension` workspace/Bazel crate under
`ext/skills`.
- Define the initial catalog, authority, provider, and turn-state types
for authority-bound skill packages and resources.
- Register placeholder thread/config/prompt/turn lifecycle contributors
plus host, executor, and remote provider aggregation points.
- Capture the remaining extraction work as TODOs, including the missing
extension API hooks needed for per-turn catalog construction and typed
skill injection.
- Keep plugins outside the runtime skills model: plugin-installed skills
are treated as materialized host-owned skill sources once available.

## Verification

- Not run locally.
2026-06-03 01:10:26 +02:00