diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index d6a5c586..1cb0222c 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -805,6 +805,11 @@ skill instruction fragments, or emit implicit skill invocation analytics from shell/unified-exec commands. The old skill-MCP dependency installer module is deleted. +The prompt/router product layer is cold too. Model turns no longer load +plugin/app capability summaries, inject available-skill/available-plugin/plugin +instructions, parse plugin/app mentions, record app/plugin invocation telemetry, +or filter MCP tools through Codex app connectors. + The Phase 6 freshness slice is landed. It exposes read-only `thread/epiphany/freshness` from live retrieval summaries plus graph frontier/churn state and, for loaded threads, watcher-backed invalidation diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 9051780b..c89c8edb 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index 4ad6db50..262c056e 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -280,5 +280,5 @@ rejected_paths: reason: making Epiphany cleaner inside Codex still preserves the wrong organ; Codex must be starved down to OpenAI subscription auth/model transport, while Epiphany data and subsystem communication move to typed CultCache/CultNet. current_status: - summary: The Codex starvation pass has five typing receipts, thirty-seven processor/foundation cuts, a real physical extraction in `epiphany-codex-bridge`, a root `epiphany-state-model` crate for durable Epiphany state, a source-grounded Codex auth spine inventory, the native `epiphany-openai-adapter` document boundary, a buildable Codex auth/model wrapper in `epiphany-openai-codex-spine`, the first native runtime caller in `epiphany-openai-runtime`, native heartbeat launch planning/job opening in `epiphany-core`, native state-update contract/validation/application in `epiphany-core`, native exact retrieval path matching in `epiphany-core`, and the route-facing mutation/view/coordinator projection services in `epiphany-codex-bridge`. `codex-protocol` no longer defines the durable `Epiphany*` state structs; it re-exports the native model for legacy rollout/API compatibility while `epiphany-core` imports the native model directly. `epiphany-core` now has no direct vendored Codex dependency: pressure derivation accepts native `EpiphanyTokenUsageSnapshot`, Codex rollout replay moved to `codex-core::epiphany_rollout`, and exact retrieval search uses Epiphany-owned workspace walking/path scoring instead of `codex-file-search`. The bridge owns Codex-facing Epiphany adapters for scene, jobs, context/planning/graph query, retrieval/indexing projection, result projection, runtime-spine result adaptation, launch/prompt doctrine, mutation document mechanics, mutation service update/promote/role-accept/reorient-accept/role-launch/reorient-launch/job-launch/job-interrupt application, live-state projection, pressure/pre-compaction rendering, freshness/reorientation projection, CRRC/coordinator/role-board projection, watcher invalidation adaptation, full `thread/epiphany/view` response construction, freshness/context/graph-query response construction, role/reorient result response construction, distill/propose patch-response construction, coordinator status/view construction, and acceptance/evidence signal helpers. Vendored app-server no longer retains root Epiphany modules; `codex_message_processor.rs` still contains route dispatch, JSON-RPC response shaping, watcher registration/snapshotting calls, and notification emission, but its root no longer imports the evacuated Epiphany policy/protocol registry or owns the watcher invalidation manager. Codex product surfaces for apps, skills, plugins, marketplace, and external agent config import are now inert in the app-server compatibility path: list routes return empty lists, mutation/detail/import routes report disabled, `externalAgentConfig/detect` returns no import candidates, helper/import modules and stale implementation-shape tests were deleted, runtime feature enablement no longer supports `apps` or `plugins`, config writes no longer emit plugin-toggle analytics, plugin/skill cache invalidation on config writes is gone, plugin startup warmups and app-list refreshes were removed, and app-server no longer directly depends on `codex-plugin`, `codex-chatgpt`, or `codex-core-plugins`. `Config::to_mcp_config` now keeps user-declared MCP servers but no longer accepts `PluginsManager`, folds plugin MCP servers into the runtime, enables Codex apps, enables skill MCP dependency install, or advertises plugin capability summaries; `TurnContext::apps_enabled()` now returns false so model turns cannot awaken Codex Apps through ChatGPT auth or feature flags; session startup and per-turn context no longer load skills, turns receive an empty `SkillLoadOutcome`, internal `Op::ListSkills` returns empty compatibility entries without loading config layers, plugin roots, skill files, or conversion helpers, the Codex skill watcher has been collapsed to a no-op marker with no file watcher, skill-root registration, cache-clear task, or `SkillsUpdateAvailable` session listener, and model turns no longer run skill mention collection, skill env-var prompts, skill MCP dependency installation, skill instruction injection, or implicit skill invocation analytics from shell tools. `codex_message_processor.rs` is about 9,637 lines; root `message_processor.rs` is about 1,292 lines after the external-agent/config-product cuts; `epiphany_read_routes.rs` is about 579 lines after the full view and read-response extractions; `epiphany_mutation_routes.rs` is about 694 lines after route-load/notification helper cuts and product-surface starvation; `epiphany_state_helpers.rs` is down to a 19-line rollout-state loader; and `codex_thread.rs` is about 1,425 lines after state-update law moved native. `epiphany-openai-adapter` defines CultCache `DatabaseEntry` request/event/receipt/auth-status documents with no Codex app-server or generic JSON dependency. `epiphany-openai-codex-spine` owns all direct Codex auth/model-transport imports for the native OpenAI path: it exposes `default_codex_home` and `auth_manager`, projects `AuthManager` / `CodexAuth` into typed `EpiphanyOpenAiAdapterStatus`, maps typed `EpiphanyOpenAiModelRequest` into Codex API `ResponsesApiRequest`, resolves auth/provider through keeper Codex crates, opens HTTP Responses streams through `codex-api`, maps deltas / completion into typed stream events and receipts, and no longer directly depends on `codex-app-server-protocol` just to name auth mode. `epiphany-openai-runtime` no longer depends directly on `codex-login`; it writes OpenAI status/request/stream-event/receipt records plus runtime sessions/jobs/results/events into `epiphany-core::runtime_spine_cache`, can emit the assistant text artifact for legacy result consumers, is now the default executor for startup-only repo birth specialists, and now has `run-worker` to load a durable `EpiphanyRuntimeWorkerLaunchRequest`, call the typed OpenAI runtime through the spine, persist typed `EpiphanyRuntimeRoleWorkerResult` / `EpiphanyRuntimeReorientWorkerResult` documents, and complete the original heartbeat/specialist runtime job without Codex worker execution; `codex exec` survives only as explicit fallback in repo-birth startup. `epiphany-mvp-coordinator` now invokes `epiphany-openai-runtime run-worker` for launched runtime job ids and no longer creates a second coordinator-owned shadow runtime job/result as a compensator. `epiphany-core::plan_runtime_spine_heartbeat_launch` validates launch contracts/conflicts and projects durable job bindings/runtime links; `epiphany-core::open_runtime_spine_heartbeat_job` owns the initialize-runtime/ensure-session/create-job sequence and now persists `EpiphanyRuntimeWorkerLaunchRequest` CultCache records keyed by runtime job id, with indexed kind/contract fields plus MessagePack-encoded typed launch documents instead of discarding work intent after queue receipt creation; `roleResult` and `reorientResult` now prefer typed worker result documents and fall back only to generic job summaries for older receipts; `epiphany-core::EpiphanyStateUpdate`, `epiphany_state_update_validation_errors`, and `apply_epiphany_state_update` own state-update document shape and mutation law while `codex-core` calls them for compatibility. Vendored `CodexThread::epiphany_launch_job` is now mostly revision check, persistence validation, launch request handoff, and rollout/session writeback for the compatibility route. Vendored `codex-core` no longer has `epiphany_distillation`, `epiphany_promotion`, `epiphany_proposal`, or `epiphany_retrieval` husk modules; it re-exports native surfaces from `epiphany-core` directly, and now owns only the real Codex rollout adapter because it is a host seam. `epiphany-runtime-spine` advertises OpenAI adapter status/model-request/stream-event/receipt CultNet schemas and mutation contracts, so the native caller now has a real storage route instead of only JSON-RPC. MCP itself is correctly JSON at its protocol edge; the target is typed Epiphany intent/result/receipt wrappers around MCP, not replacing MCP JSON. The current OpenAI spine still pulls `codex-api` and a large transport dependency stack, so its next cut is dependency starvation after richer live callers move. + summary: The Codex starvation pass has five typing receipts, thirty-eight processor/foundation cuts, a real physical extraction in `epiphany-codex-bridge`, a root `epiphany-state-model` crate for durable Epiphany state, a source-grounded Codex auth spine inventory, the native `epiphany-openai-adapter` document boundary, a buildable Codex auth/model wrapper in `epiphany-openai-codex-spine`, the first native runtime caller in `epiphany-openai-runtime`, native heartbeat launch planning/job opening in `epiphany-core`, native state-update contract/validation/application in `epiphany-core`, native exact retrieval path matching in `epiphany-core`, and the route-facing mutation/view/coordinator projection services in `epiphany-codex-bridge`. `codex-protocol` no longer defines the durable `Epiphany*` state structs; it re-exports the native model for legacy rollout/API compatibility while `epiphany-core` imports the native model directly. `epiphany-core` now has no direct vendored Codex dependency: pressure derivation accepts native `EpiphanyTokenUsageSnapshot`, Codex rollout replay moved to `codex-core::epiphany_rollout`, and exact retrieval search uses Epiphany-owned workspace walking/path scoring instead of `codex-file-search`. The bridge owns Codex-facing Epiphany adapters for scene, jobs, context/planning/graph query, retrieval/indexing projection, result projection, runtime-spine result adaptation, launch/prompt doctrine, mutation document mechanics, mutation service update/promote/role-accept/reorient-accept/role-launch/reorient-launch/job-launch/job-interrupt application, live-state projection, pressure/pre-compaction rendering, freshness/reorientation projection, CRRC/coordinator/role-board projection, watcher invalidation adaptation, full `thread/epiphany/view` response construction, freshness/context/graph-query response construction, role/reorient result response construction, distill/propose patch-response construction, coordinator status/view construction, and acceptance/evidence signal helpers. Vendored app-server no longer retains root Epiphany modules; `codex_message_processor.rs` still contains route dispatch, JSON-RPC response shaping, watcher registration/snapshotting calls, and notification emission, but its root no longer imports the evacuated Epiphany policy/protocol registry or owns the watcher invalidation manager. Codex product surfaces for apps, skills, plugins, marketplace, and external agent config import are now inert in the app-server compatibility path: list routes return empty lists, mutation/detail/import routes report disabled, `externalAgentConfig/detect` returns no import candidates, helper/import modules and stale implementation-shape tests were deleted, runtime feature enablement no longer supports `apps` or `plugins`, config writes no longer emit plugin-toggle analytics, plugin/skill cache invalidation on config writes is gone, plugin startup warmups and app-list refreshes were removed, and app-server no longer directly depends on `codex-plugin`, `codex-chatgpt`, or `codex-core-plugins`. `Config::to_mcp_config` now keeps user-declared MCP servers but no longer accepts `PluginsManager`, folds plugin MCP servers into the runtime, enables Codex apps, enables skill MCP dependency install, or advertises plugin capability summaries; `TurnContext::apps_enabled()` now returns false so model turns cannot awaken Codex Apps through ChatGPT auth or feature flags; session startup and per-turn context no longer load skills, turns receive an empty `SkillLoadOutcome`, internal `Op::ListSkills` returns empty compatibility entries without loading config layers, plugin roots, skill files, or conversion helpers, the Codex skill watcher has been collapsed to a no-op marker with no file watcher, skill-root registration, cache-clear task, or `SkillsUpdateAvailable` session listener, model turns no longer run skill mention collection, skill env-var prompts, skill MCP dependency installation, skill instruction injection, or implicit skill invocation analytics from shell tools, and the turn prompt/router path no longer loads plugin/app capability summaries, injects available-skill/available-plugin/plugin instruction fragments, parses plugin/app mentions, records app/plugin invocation telemetry, or filters MCP tools through Codex app connectors. `codex_message_processor.rs` is about 9,637 lines; root `message_processor.rs` is about 1,292 lines after the external-agent/config-product cuts; `epiphany_read_routes.rs` is about 579 lines after the full view and read-response extractions; `epiphany_mutation_routes.rs` is about 694 lines after route-load/notification helper cuts and product-surface starvation; `epiphany_state_helpers.rs` is down to a 19-line rollout-state loader; and `codex_thread.rs` is about 1,425 lines after state-update law moved native. `epiphany-openai-adapter` defines CultCache `DatabaseEntry` request/event/receipt/auth-status documents with no Codex app-server or generic JSON dependency. `epiphany-openai-codex-spine` owns all direct Codex auth/model-transport imports for the native OpenAI path: it exposes `default_codex_home` and `auth_manager`, projects `AuthManager` / `CodexAuth` into typed `EpiphanyOpenAiAdapterStatus`, maps typed `EpiphanyOpenAiModelRequest` into Codex API `ResponsesApiRequest`, resolves auth/provider through keeper Codex crates, opens HTTP Responses streams through `codex-api`, maps deltas / completion into typed stream events and receipts, and no longer directly depends on `codex-app-server-protocol` just to name auth mode. `epiphany-openai-runtime` no longer depends directly on `codex-login`; it writes OpenAI status/request/stream-event/receipt records plus runtime sessions/jobs/results/events into `epiphany-core::runtime_spine_cache`, can emit the assistant text artifact for legacy result consumers, is now the default executor for startup-only repo birth specialists, and now has `run-worker` to load a durable `EpiphanyRuntimeWorkerLaunchRequest`, call the typed OpenAI runtime through the spine, persist typed `EpiphanyRuntimeRoleWorkerResult` / `EpiphanyRuntimeReorientWorkerResult` documents, and complete the original heartbeat/specialist runtime job without Codex worker execution; `codex exec` survives only as explicit fallback in repo-birth startup. `epiphany-mvp-coordinator` now invokes `epiphany-openai-runtime run-worker` for launched runtime job ids and no longer creates a second coordinator-owned shadow runtime job/result as a compensator. `epiphany-core::plan_runtime_spine_heartbeat_launch` validates launch contracts/conflicts and projects durable job bindings/runtime links; `epiphany-core::open_runtime_spine_heartbeat_job` owns the initialize-runtime/ensure-session/create-job sequence and now persists `EpiphanyRuntimeWorkerLaunchRequest` CultCache records keyed by runtime job id, with indexed kind/contract fields plus MessagePack-encoded typed launch documents instead of discarding work intent after queue receipt creation; `roleResult` and `reorientResult` now prefer typed worker result documents and fall back only to generic job summaries for older receipts; `epiphany-core::EpiphanyStateUpdate`, `epiphany_state_update_validation_errors`, and `apply_epiphany_state_update` own state-update document shape and mutation law while `codex-core` calls them for compatibility. Vendored `CodexThread::epiphany_launch_job` is now mostly revision check, persistence validation, launch request handoff, and rollout/session writeback for the compatibility route. Vendored `codex-core` no longer has `epiphany_distillation`, `epiphany_promotion`, `epiphany_proposal`, or `epiphany_retrieval` husk modules; it re-exports native surfaces from `epiphany-core` directly, and now owns only the real Codex rollout adapter because it is a host seam. `epiphany-runtime-spine` advertises OpenAI adapter status/model-request/stream-event/receipt CultNet schemas and mutation contracts, so the native caller now has a real storage route instead of only JSON-RPC. MCP itself is correctly JSON at its protocol edge; the target is typed Epiphany intent/result/receipt wrappers around MCP, not replacing MCP JSON. The current OpenAI spine still pulls `codex-api` and a large transport dependency stack, so its next cut is dependency starvation after richer live callers move. next_action: Continue starving coordinator/runtime execution and operator surfaces off app-server JSON-RPC and out of `codex_message_processor.rs`; keep the vestigial Codex organ narrowed to subscription auth/model transport. diff --git a/vendor/codex/codex-rs/core/src/compact_remote.rs b/vendor/codex/codex-rs/core/src/compact_remote.rs index 962b3e67..5af40d55 100644 --- a/vendor/codex/codex-rs/core/src/compact_remote.rs +++ b/vendor/codex/codex-rs/core/src/compact_remote.rs @@ -1,4 +1,3 @@ -use std::collections::HashSet; use std::sync::Arc; use crate::Prompt; @@ -159,8 +158,6 @@ async fn run_remote_compact_task_inner_impl( sess.as_ref(), turn_context.as_ref(), &prompt_input, - &HashSet::new(), - /*skills_outcome*/ None, &CancellationToken::new(), ) .await?; diff --git a/vendor/codex/codex-rs/core/src/context/available_plugins_instructions.rs b/vendor/codex/codex-rs/core/src/context/available_plugins_instructions.rs deleted file mode 100644 index 52f9c8df..00000000 --- a/vendor/codex/codex-rs/core/src/context/available_plugins_instructions.rs +++ /dev/null @@ -1,58 +0,0 @@ -use codex_plugin::PluginCapabilitySummary; -use codex_protocol::protocol::PLUGINS_INSTRUCTIONS_CLOSE_TAG; -use codex_protocol::protocol::PLUGINS_INSTRUCTIONS_OPEN_TAG; - -use super::ContextualUserFragment; - -#[derive(Debug, Clone, PartialEq)] -pub(crate) struct AvailablePluginsInstructions { - plugins: Vec, -} - -impl AvailablePluginsInstructions { - pub(crate) fn from_plugins(plugins: &[PluginCapabilitySummary]) -> Option { - if plugins.is_empty() { - return None; - } - - Some(Self { - plugins: plugins.to_vec(), - }) - } -} - -impl ContextualUserFragment for AvailablePluginsInstructions { - const ROLE: &'static str = "developer"; - const START_MARKER: &'static str = PLUGINS_INSTRUCTIONS_OPEN_TAG; - const END_MARKER: &'static str = PLUGINS_INSTRUCTIONS_CLOSE_TAG; - - fn body(&self) -> String { - let mut lines = vec![ - "## Plugins".to_string(), - "A plugin is a local bundle of skills, MCP servers, and apps. Below is the list of plugins that are enabled and available in this session.".to_string(), - "### Available plugins".to_string(), - ]; - - lines.extend( - self.plugins - .iter() - .map(|plugin| match plugin.description.as_deref() { - Some(description) => format!("- `{}`: {description}", plugin.display_name), - None => format!("- `{}`", plugin.display_name), - }), - ); - - lines.push("### How to use plugins".to_string()); - lines.push( - r###"- Discovery: The list above is the plugins available in this session. -- Skill naming: If a plugin contributes skills, those skill entries are prefixed with `plugin_name:` in the Skills list. -- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn. -- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task. -- Preference: When a relevant plugin is available, prefer using capabilities associated with that plugin over standalone capabilities that provide similar functionality. -- Missing/blocked: If the user requests a plugin that is not listed above, or the plugin does not have relevant callable capabilities for the task, say so briefly and continue with the best fallback."### - .to_string(), - ); - - format!("\n{}\n", lines.join("\n")) - } -} diff --git a/vendor/codex/codex-rs/core/src/context/available_skills_instructions.rs b/vendor/codex/codex-rs/core/src/context/available_skills_instructions.rs deleted file mode 100644 index aba4b201..00000000 --- a/vendor/codex/codex-rs/core/src/context/available_skills_instructions.rs +++ /dev/null @@ -1,56 +0,0 @@ -use codex_core_skills::AvailableSkills; -use codex_protocol::protocol::SKILLS_INSTRUCTIONS_CLOSE_TAG; -use codex_protocol::protocol::SKILLS_INSTRUCTIONS_OPEN_TAG; - -use super::ContextualUserFragment; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) struct AvailableSkillsInstructions { - skill_lines: Vec, -} - -impl From for AvailableSkillsInstructions { - fn from(available_skills: AvailableSkills) -> Self { - Self { - skill_lines: available_skills.skill_lines, - } - } -} - -impl ContextualUserFragment for AvailableSkillsInstructions { - const ROLE: &'static str = "developer"; - const START_MARKER: &'static str = SKILLS_INSTRUCTIONS_OPEN_TAG; - const END_MARKER: &'static str = SKILLS_INSTRUCTIONS_CLOSE_TAG; - - fn body(&self) -> String { - let mut lines: Vec = Vec::new(); - lines.push("## Skills".to_string()); - lines.push("A skill is a set of local instructions to follow that is stored in a `SKILL.md` file. Below is the list of skills that can be used. Each entry includes a name, description, and file path so you can open the source for full instructions when using a specific skill.".to_string()); - lines.push("### Available skills".to_string()); - lines.extend(self.skill_lines.iter().cloned()); - - lines.push("### How to use skills".to_string()); - lines.push( - r###"- Discovery: The list above is the skills available in this session (name + description + file path). Skill bodies live on disk at the listed paths. -- Trigger rules: If the user names a skill (with `$SkillName` or plain text) OR the task clearly matches a skill's description shown above, you must use that skill for that turn. Multiple mentions mean use them all. Do not carry skills across turns unless re-mentioned. -- Missing/blocked: If a named skill isn't in the list or the path can't be read, say so briefly and continue with the best fallback. -- How to use a skill (progressive disclosure): - 1) After deciding to use a skill, open its `SKILL.md`. Read only enough to follow the workflow. - 2) When `SKILL.md` references relative paths (e.g., `scripts/foo.py`), resolve them relative to the skill directory listed above first, and only consider other paths if needed. - 3) If `SKILL.md` points to extra folders such as `references/`, load only the specific files needed for the request; don't bulk-load everything. - 4) If `scripts/` exist, prefer running or patching them instead of retyping large code blocks. - 5) If `assets/` or templates exist, reuse them instead of recreating from scratch. -- Coordination and sequencing: - - If multiple skills apply, choose the minimal set that covers the request and state the order you'll use them. - - Announce which skill(s) you're using and why (one short line). If you skip an obvious skill, say why. -- Context hygiene: - - Keep context small: summarize long sections instead of pasting them; only load extra files when needed. - - Avoid deep reference-chasing: prefer opening only files directly linked from `SKILL.md` unless you're blocked. - - When variants exist (frameworks, providers, domains), pick only the relevant reference file(s) and note that choice. -- Safety and fallback: If a skill can't be applied cleanly (missing files, unclear instructions), state the issue, pick the next-best approach, and continue."### - .to_string(), - ); - - format!("\n{}\n", lines.join("\n")) - } -} diff --git a/vendor/codex/codex-rs/core/src/context/mod.rs b/vendor/codex/codex-rs/core/src/context/mod.rs index da2816c9..fdb59c7f 100644 --- a/vendor/codex/codex-rs/core/src/context/mod.rs +++ b/vendor/codex/codex-rs/core/src/context/mod.rs @@ -2,8 +2,6 @@ mod approved_command_prefix_saved; mod apps_instructions; -mod available_plugins_instructions; -mod available_skills_instructions; mod collaboration_mode_instructions; mod contextual_user_message; mod environment_context; @@ -16,7 +14,6 @@ mod model_switch_instructions; mod network_rule_saved; mod permissions_instructions; mod personality_spec_instructions; -mod plugin_instructions; mod realtime_end_instructions; mod realtime_start_instructions; mod realtime_start_with_instructions; @@ -29,8 +26,6 @@ mod user_shell_command; pub(crate) use approved_command_prefix_saved::ApprovedCommandPrefixSaved; pub(crate) use apps_instructions::AppsInstructions; -pub(crate) use available_plugins_instructions::AvailablePluginsInstructions; -pub(crate) use available_skills_instructions::AvailableSkillsInstructions; pub(crate) use collaboration_mode_instructions::CollaborationModeInstructions; pub(crate) use contextual_user_message::is_contextual_user_fragment; pub(crate) use contextual_user_message::is_memory_excluded_contextual_user_fragment; @@ -47,7 +42,6 @@ pub(crate) use model_switch_instructions::ModelSwitchInstructions; pub(crate) use network_rule_saved::NetworkRuleSaved; pub use permissions_instructions::PermissionsInstructions; pub(crate) use personality_spec_instructions::PersonalitySpecInstructions; -pub(crate) use plugin_instructions::PluginInstructions; pub(crate) use realtime_end_instructions::RealtimeEndInstructions; pub(crate) use realtime_start_instructions::RealtimeStartInstructions; pub(crate) use realtime_start_with_instructions::RealtimeStartWithInstructions; diff --git a/vendor/codex/codex-rs/core/src/context/plugin_instructions.rs b/vendor/codex/codex-rs/core/src/context/plugin_instructions.rs deleted file mode 100644 index 0678033b..00000000 --- a/vendor/codex/codex-rs/core/src/context/plugin_instructions.rs +++ /dev/null @@ -1,22 +0,0 @@ -use super::ContextualUserFragment; - -#[derive(Debug, Clone, PartialEq)] -pub(crate) struct PluginInstructions { - text: String, -} - -impl PluginInstructions { - pub(crate) fn new(text: impl Into) -> Self { - Self { text: text.into() } - } -} - -impl ContextualUserFragment for PluginInstructions { - const ROLE: &'static str = "developer"; - const START_MARKER: &'static str = ""; - const END_MARKER: &'static str = ""; - - fn body(&self) -> String { - self.text.clone() - } -} diff --git a/vendor/codex/codex-rs/core/src/lib.rs b/vendor/codex/codex-rs/core/src/lib.rs index 9599d0dd..00d02305 100644 --- a/vendor/codex/codex-rs/core/src/lib.rs +++ b/vendor/codex/codex-rs/core/src/lib.rs @@ -93,13 +93,6 @@ pub mod plugins; pub(crate) mod prompt_debug; #[doc(hidden)] pub use prompt_debug::build_prompt_input; -pub(crate) mod mentions { - pub(crate) use crate::plugins::build_connector_slug_counts; - pub(crate) use crate::plugins::build_skill_name_counts; - pub(crate) use crate::plugins::collect_explicit_app_ids; - pub(crate) use crate::plugins::collect_explicit_plugin_mentions; - pub(crate) use crate::plugins::collect_tool_mentions_from_messages; -} mod sandbox_tags; pub mod sandboxing; mod session_prefix; @@ -109,10 +102,6 @@ pub mod skills; pub(crate) use skills::SkillLoadOutcome; pub(crate) use skills::SkillMetadata; pub(crate) use skills::SkillsManager; -pub(crate) use skills::build_available_skills; -pub(crate) use skills::build_skill_name_counts; -pub(crate) use skills::default_skill_metadata_budget; -pub(crate) use skills::injection; pub(crate) use skills::manager; mod skills_watcher; mod stream_events_utils; diff --git a/vendor/codex/codex-rs/core/src/plugins/injection.rs b/vendor/codex/codex-rs/core/src/plugins/injection.rs deleted file mode 100644 index 4ce50631..00000000 --- a/vendor/codex/codex-rs/core/src/plugins/injection.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::collections::BTreeSet; -use std::collections::HashMap; - -use codex_connectors::metadata::connector_display_label; -use codex_protocol::models::ResponseItem; - -use crate::connectors; -use crate::context::ContextualUserFragment; -use crate::context::PluginInstructions; -use crate::plugins::PluginCapabilitySummary; -use crate::plugins::render_explicit_plugin_instructions; -use codex_mcp::CODEX_APPS_MCP_SERVER_NAME; -use codex_mcp::ToolInfo; - -pub(crate) fn build_plugin_injections( - mentioned_plugins: &[PluginCapabilitySummary], - mcp_tools: &HashMap, - available_connectors: &[connectors::AppInfo], -) -> Vec { - if mentioned_plugins.is_empty() { - return Vec::new(); - } - - // Turn each explicit plugin mention into a developer hint that points the - // model at the plugin's visible MCP servers, enabled apps, and skill prefix. - mentioned_plugins - .iter() - .filter_map(|plugin| { - let available_mcp_servers = mcp_tools - .values() - .filter(|tool| { - tool.server_name != CODEX_APPS_MCP_SERVER_NAME - && tool - .plugin_display_names - .iter() - .any(|plugin_name| plugin_name == &plugin.display_name) - }) - .map(|tool| tool.server_name.clone()) - .collect::>() - .into_iter() - .collect::>(); - let available_apps = available_connectors - .iter() - .filter(|connector| { - connector.is_enabled - && connector - .plugin_display_names - .iter() - .any(|plugin_name| plugin_name == &plugin.display_name) - }) - .map(connector_display_label) - .collect::>() - .into_iter() - .collect::>(); - render_explicit_plugin_instructions(plugin, &available_mcp_servers, &available_apps) - .map(PluginInstructions::new) - .map(ContextualUserFragment::into) - }) - .collect() -} diff --git a/vendor/codex/codex-rs/core/src/plugins/mentions.rs b/vendor/codex/codex-rs/core/src/plugins/mentions.rs deleted file mode 100644 index a5e94345..00000000 --- a/vendor/codex/codex-rs/core/src/plugins/mentions.rs +++ /dev/null @@ -1,120 +0,0 @@ -use std::collections::HashMap; -use std::collections::HashSet; - -use codex_connectors::metadata::connector_mention_slug; -use codex_protocol::user_input::UserInput; - -use crate::connectors; -use crate::injection::ToolMentionKind; -use crate::injection::app_id_from_path; -use crate::injection::extract_tool_mentions_with_sigil; -use crate::injection::plugin_config_name_from_path; -use crate::injection::tool_kind_for_path; -use crate::mention_syntax::PLUGIN_TEXT_MENTION_SIGIL; -use crate::mention_syntax::TOOL_MENTION_SIGIL; - -use super::PluginCapabilitySummary; - -pub(crate) struct CollectedToolMentions { - pub(crate) plain_names: HashSet, - pub(crate) paths: HashSet, -} - -pub(crate) fn collect_tool_mentions_from_messages(messages: &[String]) -> CollectedToolMentions { - collect_tool_mentions_from_messages_with_sigil(messages, TOOL_MENTION_SIGIL) -} - -fn collect_tool_mentions_from_messages_with_sigil( - messages: &[String], - sigil: char, -) -> CollectedToolMentions { - let mut plain_names = HashSet::new(); - let mut paths = HashSet::new(); - for message in messages { - let mentions = extract_tool_mentions_with_sigil(message, sigil); - plain_names.extend(mentions.plain_names().map(str::to_string)); - paths.extend(mentions.paths().map(str::to_string)); - } - CollectedToolMentions { plain_names, paths } -} - -pub(crate) fn collect_explicit_app_ids(input: &[UserInput]) -> HashSet { - let messages = input - .iter() - .filter_map(|item| match item { - UserInput::Text { text, .. } => Some(text.clone()), - _ => None, - }) - .collect::>(); - - input - .iter() - .filter_map(|item| match item { - UserInput::Mention { path, .. } => Some(path.clone()), - _ => None, - }) - .chain(collect_tool_mentions_from_messages(&messages).paths) - .filter(|path| tool_kind_for_path(path.as_str()) == ToolMentionKind::App) - .filter_map(|path| app_id_from_path(path.as_str()).map(str::to_string)) - .collect() -} - -/// Collect explicit structured or linked `plugin://...` mentions. -pub(crate) fn collect_explicit_plugin_mentions( - input: &[UserInput], - plugins: &[PluginCapabilitySummary], -) -> Vec { - if plugins.is_empty() { - return Vec::new(); - } - - let messages = input - .iter() - .filter_map(|item| match item { - UserInput::Text { text, .. } => Some(text.clone()), - _ => None, - }) - .collect::>(); - - let mentioned_config_names: HashSet = input - .iter() - .filter_map(|item| match item { - UserInput::Mention { path, .. } => Some(path.clone()), - _ => None, - }) - .chain( - // Plugin plaintext links use `@`, not the default `$` tool sigil. - collect_tool_mentions_from_messages_with_sigil(&messages, PLUGIN_TEXT_MENTION_SIGIL) - .paths, - ) - .filter(|path| tool_kind_for_path(path.as_str()) == ToolMentionKind::Plugin) - .filter_map(|path| plugin_config_name_from_path(path.as_str()).map(str::to_string)) - .collect(); - - if mentioned_config_names.is_empty() { - return Vec::new(); - } - - plugins - .iter() - .filter(|plugin| mentioned_config_names.contains(plugin.config_name.as_str())) - .cloned() - .collect() -} - -pub(crate) use crate::build_skill_name_counts; - -pub(crate) fn build_connector_slug_counts( - connectors: &[connectors::AppInfo], -) -> HashMap { - let mut counts: HashMap = HashMap::new(); - for connector in connectors { - let slug = connector_mention_slug(connector); - *counts.entry(slug).or_insert(0) += 1; - } - counts -} - -#[cfg(test)] -#[path = "mentions_tests.rs"] -mod tests; diff --git a/vendor/codex/codex-rs/core/src/plugins/mentions_tests.rs b/vendor/codex/codex-rs/core/src/plugins/mentions_tests.rs deleted file mode 100644 index 37c9adb8..00000000 --- a/vendor/codex/codex-rs/core/src/plugins/mentions_tests.rs +++ /dev/null @@ -1,155 +0,0 @@ -use std::collections::HashSet; - -use codex_protocol::user_input::UserInput; -use pretty_assertions::assert_eq; - -use super::collect_explicit_app_ids; -use super::collect_explicit_plugin_mentions; -use crate::plugins::PluginCapabilitySummary; - -fn text_input(text: &str) -> UserInput { - UserInput::Text { - text: text.to_string(), - text_elements: Vec::new(), - } -} - -fn plugin(config_name: &str, display_name: &str) -> PluginCapabilitySummary { - PluginCapabilitySummary { - config_name: config_name.to_string(), - display_name: display_name.to_string(), - description: None, - has_skills: true, - mcp_server_names: Vec::new(), - app_connector_ids: Vec::new(), - } -} - -#[test] -fn collect_explicit_app_ids_from_linked_text_mentions() { - let input = vec![text_input("use [$calendar](app://calendar)")]; - - let app_ids = collect_explicit_app_ids(&input); - - assert_eq!(app_ids, HashSet::from(["calendar".to_string()])); -} - -#[test] -fn collect_explicit_app_ids_dedupes_structured_and_linked_mentions() { - let input = vec![ - text_input("use [$calendar](app://calendar)"), - UserInput::Mention { - name: "calendar".to_string(), - path: "app://calendar".to_string(), - }, - ]; - - let app_ids = collect_explicit_app_ids(&input); - - assert_eq!(app_ids, HashSet::from(["calendar".to_string()])); -} - -#[test] -fn collect_explicit_app_ids_ignores_non_app_paths() { - let input = vec![ - text_input( - "use [$docs](mcp://docs) and [$skill](skill://team/skill) and [$file](/tmp/file.txt)", - ), - UserInput::Mention { - name: "docs".to_string(), - path: "mcp://docs".to_string(), - }, - UserInput::Mention { - name: "skill".to_string(), - path: "skill://team/skill".to_string(), - }, - UserInput::Mention { - name: "file".to_string(), - path: "/tmp/file.txt".to_string(), - }, - ]; - - let app_ids = collect_explicit_app_ids(&input); - - assert_eq!(app_ids, HashSet::::new()); -} - -#[test] -fn collect_explicit_plugin_mentions_from_structured_paths() { - let plugins = vec![ - plugin("sample@test", "sample"), - plugin("other@test", "other"), - ]; - - let mentioned = collect_explicit_plugin_mentions( - &[UserInput::Mention { - name: "sample".to_string(), - path: "plugin://sample@test".to_string(), - }], - &plugins, - ); - - assert_eq!(mentioned, vec![plugin("sample@test", "sample")]); -} - -#[test] -fn collect_explicit_plugin_mentions_from_linked_text_mentions() { - let plugins = vec![ - plugin("sample@test", "sample"), - plugin("other@test", "other"), - ]; - - let mentioned = collect_explicit_plugin_mentions( - &[text_input("use [@sample](plugin://sample@test)")], - &plugins, - ); - - assert_eq!(mentioned, vec![plugin("sample@test", "sample")]); -} - -#[test] -fn collect_explicit_plugin_mentions_dedupes_structured_and_linked_mentions() { - let plugins = vec![ - plugin("sample@test", "sample"), - plugin("other@test", "other"), - ]; - - let mentioned = collect_explicit_plugin_mentions( - &[ - text_input("use [@sample](plugin://sample@test)"), - UserInput::Mention { - name: "sample".to_string(), - path: "plugin://sample@test".to_string(), - }, - ], - &plugins, - ); - - assert_eq!(mentioned, vec![plugin("sample@test", "sample")]); -} - -#[test] -fn collect_explicit_plugin_mentions_ignores_non_plugin_paths() { - let plugins = vec![plugin("sample@test", "sample")]; - - let mentioned = collect_explicit_plugin_mentions( - &[text_input( - "use [$app](app://calendar) and [$skill](skill://team/skill) and [$file](/tmp/file.txt)", - )], - &plugins, - ); - - assert_eq!(mentioned, Vec::::new()); -} - -#[test] -fn collect_explicit_plugin_mentions_ignores_dollar_linked_plugin_mentions() { - let plugins = vec![plugin("sample@test", "sample")]; - - let mentioned = collect_explicit_plugin_mentions( - &[text_input("use [$sample](plugin://sample@test)")], - &plugins, - ); - - assert_eq!(mentioned, Vec::::new()); -} diff --git a/vendor/codex/codex-rs/core/src/plugins/mod.rs b/vendor/codex/codex-rs/core/src/plugins/mod.rs index a8fbcdf9..7cf9bc0e 100644 --- a/vendor/codex/codex-rs/core/src/plugins/mod.rs +++ b/vendor/codex/codex-rs/core/src/plugins/mod.rs @@ -1,13 +1,10 @@ use codex_config::types::McpServerConfig; mod discoverable; -mod injection; mod installed_marketplaces; mod manager; mod marketplace_add; mod marketplace_remove; -mod mentions; -mod render; mod startup_sync; #[cfg(test)] pub(crate) mod test_support; @@ -26,7 +23,6 @@ pub type LoadedPlugin = codex_plugin::LoadedPlugin; pub type PluginLoadOutcome = codex_plugin::PluginLoadOutcome; pub(crate) use discoverable::list_tool_suggest_discoverable_plugins; -pub(crate) use injection::build_plugin_injections; pub use installed_marketplaces::INSTALLED_MARKETPLACES_DIR; pub use installed_marketplaces::marketplace_install_root; pub use manager::ConfiguredMarketplace; @@ -54,13 +50,6 @@ pub use marketplace_remove::MarketplaceRemoveError; pub use marketplace_remove::MarketplaceRemoveOutcome; pub use marketplace_remove::MarketplaceRemoveRequest; pub use marketplace_remove::remove_marketplace; -pub(crate) use render::render_explicit_plugin_instructions; pub(crate) use startup_sync::curated_plugins_repo_path; pub(crate) use startup_sync::read_curated_plugins_sha; pub(crate) use startup_sync::sync_openai_plugins_repo; - -pub(crate) use mentions::build_connector_slug_counts; -pub(crate) use mentions::build_skill_name_counts; -pub(crate) use mentions::collect_explicit_app_ids; -pub(crate) use mentions::collect_explicit_plugin_mentions; -pub(crate) use mentions::collect_tool_mentions_from_messages; diff --git a/vendor/codex/codex-rs/core/src/plugins/render.rs b/vendor/codex/codex-rs/core/src/plugins/render.rs deleted file mode 100644 index fc197dbb..00000000 --- a/vendor/codex/codex-rs/core/src/plugins/render.rs +++ /dev/null @@ -1,62 +0,0 @@ -#[cfg(test)] -use crate::context::AvailablePluginsInstructions; -#[cfg(test)] -use crate::context::ContextualUserFragment; -use crate::plugins::PluginCapabilitySummary; - -#[cfg(test)] -pub(crate) fn render_plugins_section(plugins: &[PluginCapabilitySummary]) -> Option { - AvailablePluginsInstructions::from_plugins(plugins).map(|instructions| instructions.render()) -} - -pub(crate) fn render_explicit_plugin_instructions( - plugin: &PluginCapabilitySummary, - available_mcp_servers: &[String], - available_apps: &[String], -) -> Option { - let mut lines = vec![format!( - "Capabilities from the `{}` plugin:", - plugin.display_name - )]; - - if plugin.has_skills { - lines.push(format!( - "- Skills from this plugin are prefixed with `{}:`.", - plugin.display_name - )); - } - - if !available_mcp_servers.is_empty() { - lines.push(format!( - "- MCP servers from this plugin available in this session: {}.", - available_mcp_servers - .iter() - .map(|server| format!("`{server}`")) - .collect::>() - .join(", ") - )); - } - - if !available_apps.is_empty() { - lines.push(format!( - "- Apps from this plugin available in this session: {}.", - available_apps - .iter() - .map(|app| format!("`{app}`")) - .collect::>() - .join(", ") - )); - } - - if lines.len() == 1 { - return None; - } - - lines.push("Use these plugin-associated capabilities to help solve the task.".to_string()); - - Some(lines.join("\n")) -} - -#[cfg(test)] -#[path = "render_tests.rs"] -mod tests; diff --git a/vendor/codex/codex-rs/core/src/prompt_debug.rs b/vendor/codex/codex-rs/core/src/prompt_debug.rs index b6c66410..c307b297 100644 --- a/vendor/codex/codex-rs/core/src/prompt_debug.rs +++ b/vendor/codex/codex-rs/core/src/prompt_debug.rs @@ -1,4 +1,3 @@ -use std::collections::HashSet; use std::sync::Arc; use codex_exec_server::EnvironmentManager; @@ -83,8 +82,6 @@ pub(crate) async fn build_prompt_input_from_session( sess, turn_context.as_ref(), &prompt_input, - &HashSet::new(), - Some(turn_context.turn_skills.outcome.as_ref()), &CancellationToken::new(), ) .await?; diff --git a/vendor/codex/codex-rs/core/src/session/mod.rs b/vendor/codex/codex-rs/core/src/session/mod.rs index 7916d15e..fdf36d82 100644 --- a/vendor/codex/codex-rs/core/src/session/mod.rs +++ b/vendor/codex/codex-rs/core/src/session/mod.rs @@ -14,22 +14,18 @@ use crate::agent::Mailbox; use crate::agent::MailboxReceiver; use crate::agent::agent_status_from_event; use crate::agent::status::is_final; -use crate::build_available_skills; use crate::commit_attribution::commit_message_trailer_instruction; use crate::compact; use crate::config::ManagedFeatures; use crate::connectors; use crate::context::ApprovedCommandPrefixSaved; use crate::context::AppsInstructions; -use crate::context::AvailablePluginsInstructions; -use crate::context::AvailableSkillsInstructions; use crate::context::CollaborationModeInstructions; use crate::context::ContextualUserFragment; use crate::context::EpiphanyStateInstructions; use crate::context::NetworkRuleSaved; use crate::context::PermissionsInstructions; use crate::context::PersonalitySpecInstructions; -use crate::default_skill_metadata_budget; use crate::exec_policy::ExecPolicyManager; use crate::installation_id::resolve_installation_id; use crate::parse_turn_item; @@ -37,7 +33,6 @@ use crate::path_utils::normalize_for_native_workdir; use crate::realtime_conversation::RealtimeConversationManager; use crate::rollout::find_thread_name_by_id; use crate::session_prefix::format_subagent_notification_message; -use crate::skills::SkillRenderSideEffects; use crate::turn_metadata::TurnMetadataState; use async_channel::Receiver; use async_channel::Sender; @@ -194,10 +189,6 @@ use self::session::SessionConfiguration; pub(crate) use self::session::SessionSettingsUpdate; #[cfg(test)] use self::turn::AssistantMessageStreamParsers; -#[cfg(test)] -use self::turn::collect_explicit_app_ids_from_skill_items; -#[cfg(test)] -use self::turn::filter_connectors_for_input; use self::turn::realtime_text_for_event; use self::turn_context::TurnContext; use self::turn_context::TurnSkillsContext; @@ -2499,43 +2490,6 @@ impl Session { developer_sections.push(apps_instructions.render()); } } - if turn_context.config.include_skill_instructions { - let implicit_skills = turn_context - .turn_skills - .outcome - .allowed_skills_for_implicit_invocation(); - let available_skills = build_available_skills( - &implicit_skills, - default_skill_metadata_budget(turn_context.model_info.context_window), - SkillRenderSideEffects::ThreadStart { - session_telemetry: &self.services.session_telemetry, - }, - ); - if let Some(available_skills) = available_skills { - let warning_message = available_skills.warning_message.clone(); - let skills_instructions = AvailableSkillsInstructions::from(available_skills); - if let Some(warning_message) = warning_message { - self.send_event_raw(Event { - id: String::new(), - msg: EventMsg::Warning(WarningEvent { - message: warning_message, - }), - }) - .await; - } - developer_sections.push(skills_instructions.render()); - } - } - let loaded_plugins = self - .services - .plugins_manager - .plugins_for_config(&turn_context.config) - .await; - if let Some(plugin_instructions) = - AvailablePluginsInstructions::from_plugins(loaded_plugins.capability_summaries()) - { - developer_sections.push(plugin_instructions.render()); - } if turn_context.features.enabled(Feature::CodexGitCommit) && let Some(commit_message_instruction) = commit_message_trailer_instruction( turn_context.config.commit_attribution.as_deref(), diff --git a/vendor/codex/codex-rs/core/src/session/tests.rs b/vendor/codex/codex-rs/core/src/session/tests.rs index f32f93eb..7a42728b 100644 --- a/vendor/codex/codex-rs/core/src/session/tests.rs +++ b/vendor/codex/codex-rs/core/src/session/tests.rs @@ -1380,117 +1380,6 @@ async fn reload_user_config_layer_updates_effective_apps_config() { assert_eq!(app.destructive_enabled, Some(false)); } -#[test] -fn filter_connectors_for_input_skips_duplicate_slug_mentions() { - let connectors = vec![ - make_connector("one", "Foo Bar"), - make_connector("two", "Foo-Bar"), - ]; - let input = vec![user_message("use $foo-bar")]; - let explicitly_enabled_connectors = HashSet::new(); - let skill_name_counts_lower = HashMap::new(); - - let selected = filter_connectors_for_input( - &connectors, - &input, - &explicitly_enabled_connectors, - &skill_name_counts_lower, - ); - - assert_eq!(selected, Vec::new()); -} - -#[test] -fn filter_connectors_for_input_skips_when_skill_name_conflicts() { - let connectors = vec![make_connector("one", "Todoist")]; - let input = vec![user_message("use $todoist")]; - let explicitly_enabled_connectors = HashSet::new(); - let skill_name_counts_lower = HashMap::from([("todoist".to_string(), 1)]); - - let selected = filter_connectors_for_input( - &connectors, - &input, - &explicitly_enabled_connectors, - &skill_name_counts_lower, - ); - - assert_eq!(selected, Vec::new()); -} - -#[test] -fn filter_connectors_for_input_skips_disabled_connectors() { - let mut connector = make_connector("calendar", "Calendar"); - connector.is_enabled = false; - let input = vec![user_message("use $calendar")]; - let explicitly_enabled_connectors = HashSet::new(); - let selected = filter_connectors_for_input( - &[connector], - &input, - &explicitly_enabled_connectors, - &HashMap::new(), - ); - - assert_eq!(selected, Vec::new()); -} - -#[test] -fn filter_connectors_for_input_skips_plugin_mentions() { - let connectors = vec![make_connector("figma", "Figma")]; - let input = vec![user_message("use [@figma](plugin://figma@openai-curated)")]; - let explicitly_enabled_connectors = HashSet::new(); - let selected = filter_connectors_for_input( - &connectors, - &input, - &explicitly_enabled_connectors, - &HashMap::new(), - ); - - assert_eq!(selected, Vec::new()); -} - -#[test] -fn collect_explicit_app_ids_from_skill_items_includes_linked_mentions() { - let connectors = vec![make_connector("calendar", "Calendar")]; - let skill_items = vec![skill_message( - "\ndemo\n/tmp/skills/demo/SKILL.md\nuse [$calendar](app://calendar)\n", - )]; - - let connector_ids = - collect_explicit_app_ids_from_skill_items(&skill_items, &connectors, &HashMap::new()); - - assert_eq!(connector_ids, HashSet::from(["calendar".to_string()])); -} - -#[test] -fn collect_explicit_app_ids_from_skill_items_resolves_unambiguous_plain_mentions() { - let connectors = vec![make_connector("calendar", "Calendar")]; - let skill_items = vec![skill_message( - "\ndemo\n/tmp/skills/demo/SKILL.md\nuse $calendar\n", - )]; - - let connector_ids = - collect_explicit_app_ids_from_skill_items(&skill_items, &connectors, &HashMap::new()); - - assert_eq!(connector_ids, HashSet::from(["calendar".to_string()])); -} - -#[test] -fn collect_explicit_app_ids_from_skill_items_skips_plain_mentions_with_skill_conflicts() { - let connectors = vec![make_connector("calendar", "Calendar")]; - let skill_items = vec![skill_message( - "\ndemo\n/tmp/skills/demo/SKILL.md\nuse $calendar\n", - )]; - let skill_name_counts_lower = HashMap::from([("calendar".to_string(), 1)]); - - let connector_ids = collect_explicit_app_ids_from_skill_items( - &skill_items, - &connectors, - &skill_name_counts_lower, - ); - - assert_eq!(connector_ids, HashSet::::new()); -} - #[tokio::test] async fn reconstruct_history_matches_live_compactions() { let (session, turn_context) = make_session_and_context().await; diff --git a/vendor/codex/codex-rs/core/src/session/turn.rs b/vendor/codex/codex-rs/core/src/session/turn.rs index d2710771..1470bca9 100644 --- a/vendor/codex/codex-rs/core/src/session/turn.rs +++ b/vendor/codex/codex-rs/core/src/session/turn.rs @@ -2,16 +2,13 @@ use std::collections::HashMap; use std::collections::HashSet; use std::sync::Arc; -use crate::SkillLoadOutcome; use crate::client::ModelClientSession; use crate::client_common::Prompt; use crate::client_common::ResponseEvent; use crate::compact::InitialContextInjection; -use crate::compact::collect_user_messages; use crate::compact::run_inline_auto_compact_task; use crate::compact::should_use_remote_compact_task; use crate::compact_remote::run_inline_remote_auto_compact_task; -use crate::connectors; use crate::feedback_tags; use crate::hook_runtime::PendingInputHookDisposition; use crate::hook_runtime::emit_hook_completed_events; @@ -20,17 +17,8 @@ use crate::hook_runtime::record_additional_contexts; use crate::hook_runtime::record_pending_input; use crate::hook_runtime::run_pending_session_start_hooks; use crate::hook_runtime::run_user_prompt_submit_hooks; -use crate::injection::ToolMentionKind; -use crate::injection::app_id_from_path; -use crate::injection::tool_kind_for_path; use crate::mcp_tool_exposure::build_mcp_tool_exposure; -use crate::mentions::build_connector_slug_counts; -use crate::mentions::build_skill_name_counts; -use crate::mentions::collect_explicit_app_ids; -use crate::mentions::collect_explicit_plugin_mentions; -use crate::mentions::collect_tool_mentions_from_messages; use crate::parse_turn_item; -use crate::plugins::build_plugin_injections; use crate::session::PreviousTurnSettings; use crate::session::session::Session; use crate::session::turn_context::TurnContext; @@ -51,12 +39,9 @@ use crate::turn_timing::record_turn_ttft_metric; use crate::unavailable_tool::collect_unavailable_called_tools; use crate::util::backoff; use crate::util::error_or_panic; -use codex_analytics::AppInvocation; use codex_analytics::CompactionPhase; use codex_analytics::CompactionReason; -use codex_analytics::InvocationType; use codex_analytics::TurnResolvedConfigFact; -use codex_analytics::build_track_events_context; use codex_async_utils::OrCancelExt; use codex_features::Feature; use codex_hooks::HookEvent; @@ -90,7 +75,6 @@ use codex_protocol::user_input::UserInput; use codex_tools::ResponsesApiNamespaceTool; use codex_tools::ToolName; use codex_tools::ToolSpec; -use codex_tools::filter_tool_suggest_discoverable_tools_for_client; use codex_utils_stream_parser::AssistantTextChunk; use codex_utils_stream_parser::AssistantTextStreamParser; use codex_utils_stream_parser::ProposedPlanSegment; @@ -159,77 +143,6 @@ pub(crate) async fn run_turn( sess.record_context_updates_and_set_reference_context_item(turn_context.as_ref()) .await; - let loaded_plugins = sess - .services - .plugins_manager - .plugins_for_config(&turn_context.config) - .await; - // Structured plugin:// mentions are resolved from the current session's - // enabled plugins, then converted into turn-scoped guidance below. - let mentioned_plugins = - collect_explicit_plugin_mentions(&input, loaded_plugins.capability_summaries()); - let mcp_tools = if turn_context.apps_enabled() || !mentioned_plugins.is_empty() { - // Plugin mentions need raw MCP/app inventory even when app tools - // are normally hidden so we can describe the plugin's currently - // usable capabilities for this turn. - match sess - .services - .mcp_connection_manager - .read() - .await - .list_all_tools() - .or_cancel(&cancellation_token) - .await - { - Ok(mcp_tools) => mcp_tools, - Err(_) if turn_context.apps_enabled() => return None, - Err(_) => HashMap::new(), - } - } else { - HashMap::new() - }; - let available_connectors = if turn_context.apps_enabled() { - let connectors = codex_connectors::merge::merge_plugin_connectors_with_accessible( - loaded_plugins - .effective_apps() - .into_iter() - .map(|connector_id| connector_id.0), - connectors::accessible_connectors_from_mcp_tools(&mcp_tools), - ); - connectors::with_app_enabled_state(connectors, &turn_context.config) - } else { - Vec::new() - }; - let thread_id = sess.conversation_id.to_string(); - let tracking = build_track_events_context( - turn_context.model_info.slug.clone(), - thread_id, - turn_context.sub_id.clone(), - ); - - let plugin_items = - build_plugin_injections(&mentioned_plugins, &mcp_tools, &available_connectors); - let mentioned_plugin_metadata = mentioned_plugins - .iter() - .filter_map(crate::plugins::PluginCapabilitySummary::telemetry_metadata) - .collect::>(); - - let explicitly_enabled_connectors = collect_explicit_app_ids(&input); - let connector_names_by_id = available_connectors - .iter() - .map(|connector| (connector.id.as_str(), connector.name.as_str())) - .collect::>(); - let mentioned_app_invocations = explicitly_enabled_connectors - .iter() - .map(|connector_id| AppInvocation { - connector_id: Some(connector_id.clone()), - app_name: connector_names_by_id - .get(connector_id.as_str()) - .map(|name| (*name).to_string()), - invocation_type: Some(InvocationType::Explicit), - }) - .collect::>(); - if run_pending_session_start_hooks(&sess, &turn_context).await { return None; } @@ -257,16 +170,6 @@ pub(crate) async fn run_turn( .await; user_prompt_submit_outcome.additional_contexts }; - sess.services - .analytics_events_client - .track_app_mentioned(tracking.clone(), mentioned_app_invocations); - for plugin in mentioned_plugin_metadata { - sess.services - .analytics_events_client - .track_plugin_used(tracking.clone(), plugin); - } - sess.merge_connector_selection(explicitly_enabled_connectors.clone()) - .await; record_additional_contexts(&sess, &turn_context, additional_contexts).await; if !input.is_empty() { // Track the previous-turn baseline from the regular user-turn path only so @@ -278,14 +181,8 @@ pub(crate) async fn run_turn( })) .await; } - if !plugin_items.is_empty() { - sess.record_conversation_items(&turn_context, &plugin_items) - .await; - } - track_turn_resolved_config_analytics(&sess, &turn_context, &input).await; - let skills_outcome: Option<&SkillLoadOutcome> = None; sess.maybe_start_ghost_snapshot(Arc::clone(&turn_context), cancellation_token.child_token()) .await; let mut last_agent_message: Option = None; @@ -382,8 +279,6 @@ pub(crate) async fn run_turn( &mut client_session, turn_metadata_header.as_deref(), sampling_request_input, - &explicitly_enabled_connectors, - skills_outcome, &mut server_model_warning_emitted_for_turn, cancellation_token.child_token(), ) @@ -742,82 +637,6 @@ async fn run_auto_compact( Ok(()) } -pub(super) fn filter_connectors_for_input( - connectors: &[connectors::AppInfo], - input: &[ResponseItem], - explicitly_enabled_connectors: &HashSet, - skill_name_counts_lower: &HashMap, -) -> Vec { - let connectors: Vec = connectors - .iter() - .filter(|connector| connector.is_enabled) - .cloned() - .collect::>(); - if connectors.is_empty() { - return Vec::new(); - } - - let user_messages = collect_user_messages(input); - if user_messages.is_empty() && explicitly_enabled_connectors.is_empty() { - return Vec::new(); - } - - let mentions = collect_tool_mentions_from_messages(&user_messages); - let mention_names_lower = mentions - .plain_names - .iter() - .map(|name| name.to_ascii_lowercase()) - .collect::>(); - - let connector_slug_counts = build_connector_slug_counts(&connectors); - let mut allowed_connector_ids = explicitly_enabled_connectors.clone(); - for path in mentions - .paths - .iter() - .filter(|path| tool_kind_for_path(path) == ToolMentionKind::App) - { - if let Some(connector_id) = app_id_from_path(path) { - allowed_connector_ids.insert(connector_id.to_string()); - } - } - - connectors - .into_iter() - .filter(|connector| { - connector_inserted_in_messages( - connector, - &mention_names_lower, - &allowed_connector_ids, - &connector_slug_counts, - skill_name_counts_lower, - ) - }) - .collect() -} - -fn connector_inserted_in_messages( - connector: &connectors::AppInfo, - mention_names_lower: &HashSet, - allowed_connector_ids: &HashSet, - connector_slug_counts: &HashMap, - skill_name_counts_lower: &HashMap, -) -> bool { - if allowed_connector_ids.contains(&connector.id) { - return true; - } - - let mention_slug = codex_connectors::metadata::connector_mention_slug(connector); - let connector_count = connector_slug_counts - .get(&mention_slug) - .copied() - .unwrap_or(0); - let skill_count = skill_name_counts_lower - .get(&mention_slug) - .copied() - .unwrap_or(0); - connector_count == 1 && skill_count == 0 && mention_names_lower.contains(&mention_slug) -} - pub(crate) fn build_prompt( input: Vec, router: &ToolRouter, @@ -898,8 +717,6 @@ async fn run_sampling_request( client_session: &mut ModelClientSession, turn_metadata_header: Option<&str>, input: Vec, - explicitly_enabled_connectors: &HashSet, - skills_outcome: Option<&SkillLoadOutcome>, server_model_warning_emitted_for_turn: &mut bool, cancellation_token: CancellationToken, ) -> CodexResult { @@ -907,8 +724,6 @@ async fn run_sampling_request( sess.as_ref(), turn_context.as_ref(), &input, - explicitly_enabled_connectors, - skills_outcome, &cancellation_token, ) .await?; @@ -1042,8 +857,6 @@ pub(crate) async fn built_tools( sess: &Session, turn_context: &TurnContext, input: &[ResponseItem], - explicitly_enabled_connectors: &HashSet, - skills_outcome: Option<&SkillLoadOutcome>, cancellation_token: &CancellationToken, ) -> CodexResult> { let mcp_connection_manager = sess.services.mcp_connection_manager.read().await; @@ -1053,84 +866,10 @@ pub(crate) async fn built_tools( .or_cancel(cancellation_token) .await?; drop(mcp_connection_manager); - let loaded_plugins = sess - .services - .plugins_manager - .plugins_for_config(&turn_context.config) - .await; - - let mut effective_explicitly_enabled_connectors = explicitly_enabled_connectors.clone(); - effective_explicitly_enabled_connectors.extend(sess.get_connector_selection().await); - - let apps_enabled = turn_context.apps_enabled(); - let accessible_connectors = - apps_enabled.then(|| connectors::accessible_connectors_from_mcp_tools(&all_mcp_tools)); - let accessible_connectors_with_enabled_state = - accessible_connectors.as_ref().map(|connectors| { - connectors::with_app_enabled_state(connectors.clone(), &turn_context.config) - }); - let connectors = if apps_enabled { - let connectors = codex_connectors::merge::merge_plugin_connectors_with_accessible( - loaded_plugins - .effective_apps() - .into_iter() - .map(|connector_id| connector_id.0), - accessible_connectors.clone().unwrap_or_default(), - ); - Some(connectors::with_app_enabled_state( - connectors, - &turn_context.config, - )) - } else { - None - }; - let auth = sess.services.auth_manager.auth().await; - let discoverable_tools = if apps_enabled && turn_context.tools_config.tool_suggest { - if let Some(accessible_connectors) = accessible_connectors_with_enabled_state.as_ref() { - match connectors::list_tool_suggest_discoverable_tools_with_auth( - &turn_context.config, - auth.as_ref(), - accessible_connectors.as_slice(), - ) - .await - .map(|discoverable_tools| { - filter_tool_suggest_discoverable_tools_for_client( - discoverable_tools, - turn_context.app_server_client_name.as_deref(), - ) - }) { - Ok(discoverable_tools) if discoverable_tools.is_empty() => None, - Ok(discoverable_tools) => Some(discoverable_tools), - Err(err) => { - warn!("failed to load discoverable tool suggestions: {err:#}"); - None - } - } - } else { - None - } - } else { - None - }; - - let explicitly_enabled = if let Some(connectors) = connectors.as_ref() { - let skill_name_counts_lower = skills_outcome.map_or_else(HashMap::new, |outcome| { - build_skill_name_counts(&outcome.skills, &outcome.disabled_paths).1 - }); - - filter_connectors_for_input( - connectors, - input, - &effective_explicitly_enabled_connectors, - &skill_name_counts_lower, - ) - } else { - Vec::new() - }; let mcp_tool_exposure = build_mcp_tool_exposure( &all_mcp_tools, - connectors.as_deref(), - explicitly_enabled.as_slice(), + None, + &[], &turn_context.config, &turn_context.tools_config, ); @@ -1170,7 +909,7 @@ pub(crate) async fn built_tools( deferred_mcp_tools, unavailable_called_tools, parallel_mcp_server_names, - discoverable_tools, + discoverable_tools: None, dynamic_tools: turn_context.dynamic_tools.as_slice(), }, ))) diff --git a/vendor/codex/codex-rs/core/src/session_startup_prewarm.rs b/vendor/codex/codex-rs/core/src/session_startup_prewarm.rs index 71afdba6..a3ef2e42 100644 --- a/vendor/codex/codex-rs/core/src/session_startup_prewarm.rs +++ b/vendor/codex/codex-rs/core/src/session_startup_prewarm.rs @@ -1,4 +1,3 @@ -use std::collections::HashSet; use std::sync::Arc; use std::time::Duration; use std::time::Instant; @@ -208,8 +207,6 @@ async fn schedule_startup_prewarm_inner( session.as_ref(), startup_turn_context.as_ref(), &[], - &HashSet::new(), - /*skills_outcome*/ None, &startup_cancellation_token, ) .await?; diff --git a/vendor/codex/codex-rs/core/src/skills.rs b/vendor/codex/codex-rs/core/src/skills.rs index 23aac4d1..cefecfac 100644 --- a/vendor/codex/codex-rs/core/src/skills.rs +++ b/vendor/codex/codex-rs/core/src/skills.rs @@ -7,7 +7,6 @@ pub use codex_core_skills::SkillRenderReport; pub use codex_core_skills::SkillsLoadInput; pub use codex_core_skills::SkillsManager; pub use codex_core_skills::build_available_skills; -pub use codex_core_skills::build_skill_name_counts; pub use codex_core_skills::collect_env_var_dependencies; pub use codex_core_skills::config_rules; pub use codex_core_skills::default_skill_metadata_budget;