Move distill propose reads into bridge

This commit is contained in:
Meta Vens 2026-05-13 10:26:35 +01:00
commit 30a1e4aa19
5 changed files with 76 additions and 52 deletions

View file

@ -1,6 +1,10 @@
use std::path::Path;
use codex_app_server_protocol::*;
use codex_core::EpiphanyDistillInput;
use codex_core::EpiphanyMapProposalInput;
use codex_core::distill_observation;
use codex_core::propose_map_update;
use codex_protocol::protocol::EpiphanyRetrievalState;
use codex_protocol::protocol::EpiphanyThreadState;
use codex_protocol::protocol::TokenUsageInfo as CoreTokenUsageInfo;
@ -497,3 +501,60 @@ pub async fn map_epiphany_reorient_result_response(
note,
}
}
pub fn map_epiphany_distill_response(
expected_revision: u64,
params: ThreadEpiphanyDistillParams,
) -> std::result::Result<ThreadEpiphanyDistillResponse, String> {
let ThreadEpiphanyDistillParams {
source_kind,
status,
text,
subject,
evidence_kind,
code_refs,
..
} = params;
let proposal = distill_observation(EpiphanyDistillInput {
source_kind,
status,
text,
subject,
evidence_kind,
code_refs,
})
.map_err(|err| err.to_string())?;
Ok(ThreadEpiphanyDistillResponse {
expected_revision,
patch: ThreadEpiphanyUpdatePatch {
observations: vec![proposal.observation],
evidence: vec![proposal.evidence],
..Default::default()
},
})
}
pub fn map_epiphany_propose_response(
state: EpiphanyThreadState,
observation_ids: Vec<String>,
) -> std::result::Result<ThreadEpiphanyProposeResponse, String> {
let expected_revision = state.revision;
let proposal = propose_map_update(EpiphanyMapProposalInput {
state,
observation_ids,
})
.map_err(|err| err.to_string())?;
Ok(ThreadEpiphanyProposeResponse {
expected_revision,
patch: ThreadEpiphanyUpdatePatch {
observations: vec![proposal.observation],
evidence: vec![proposal.evidence],
graphs: Some(proposal.graphs),
graph_frontier: Some(proposal.graph_frontier),
churn: Some(proposal.churn),
..Default::default()
},
})
}

View file

@ -720,7 +720,11 @@ Freshness/context/graph-query response construction is also bridge-owned now.
`ThreadEpiphanyContextResponse`, and `ThreadEpiphanyGraphQueryResponse` from
typed state plus host-supplied watcher/retrieval inputs. App-server still owns
loading and watcher registration because those are host lifecycle seams.
`epiphany_read_routes.rs` is about 620 lines after this cut.
`epiphany_read_routes.rs` is about 620 lines after this cut. The distill and
propose patch-response builders have followed into the same bridge view module;
app-server still checks that the target thread is loaded and maps errors onto
JSON-RPC responses, but it no longer shapes those patches itself.
`epiphany_read_routes.rs` is about 579 lines after this cut.
Also: MCP itself is allowed to be JSON. The target is not "replace MCP JSON";
the target is an Epiphany-owned boundary that speaks typed Epiphany

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -1,10 +1,7 @@
use codex_app_server_protocol::*;
use codex_core::EPIPHANY_RETRIEVAL_DEFAULT_LIMIT;
use codex_core::EPIPHANY_RETRIEVAL_MAX_LIMIT;
use codex_core::EpiphanyDistillInput;
use codex_core::EpiphanyMapProposalInput;
use codex_core::EpiphanyRetrieveQuery;
use codex_core::distill_observation;
use codex_protocol::ThreadId;
use epiphany_codex_bridge::launch::EPIPHANY_REORIENT_LAUNCH_BINDING_ID;
use epiphany_codex_bridge::launch::epiphany_role_binding_id;
@ -19,8 +16,10 @@ use epiphany_codex_bridge::view::epiphany_view_needs_pressure;
use epiphany_codex_bridge::view::epiphany_view_needs_reorientation_inputs;
use epiphany_codex_bridge::view::epiphany_view_needs_runtime_store;
use epiphany_codex_bridge::view::map_epiphany_context_response;
use epiphany_codex_bridge::view::map_epiphany_distill_response;
use epiphany_codex_bridge::view::map_epiphany_freshness_response;
use epiphany_codex_bridge::view::map_epiphany_graph_query_response;
use epiphany_codex_bridge::view::map_epiphany_propose_response;
use epiphany_codex_bridge::view::map_epiphany_reorient_result_response;
use epiphany_codex_bridge::view::map_epiphany_role_result_response;
use epiphany_codex_bridge::view::map_epiphany_view_response;
@ -480,15 +479,7 @@ impl CodexMessageProcessor {
request_id: ConnectionRequestId,
params: ThreadEpiphanyDistillParams,
) {
let ThreadEpiphanyDistillParams {
thread_id,
source_kind,
status,
text,
subject,
evidence_kind,
code_refs,
} = params;
let thread_id = params.thread_id.clone();
let thread_uuid = match ThreadId::from_string(&thread_id) {
Ok(id) => id,
@ -516,15 +507,8 @@ impl CodexMessageProcessor {
.await
.map(|state| state.revision)
.unwrap_or(0);
let proposal = match distill_observation(EpiphanyDistillInput {
source_kind,
status,
text,
subject,
evidence_kind,
code_refs,
}) {
Ok(proposal) => proposal,
let response = match map_epiphany_distill_response(expected_revision, params) {
Ok(response) => response,
Err(err) => {
self.send_invalid_request_error(
request_id,
@ -534,14 +518,6 @@ impl CodexMessageProcessor {
return;
}
};
let response = ThreadEpiphanyDistillResponse {
expected_revision,
patch: ThreadEpiphanyUpdatePatch {
observations: vec![proposal.observation],
evidence: vec![proposal.evidence],
..Default::default()
},
};
self.outgoing.send_response(request_id, response).await;
}
@ -551,10 +527,8 @@ impl CodexMessageProcessor {
request_id: ConnectionRequestId,
params: ThreadEpiphanyProposeParams,
) {
let ThreadEpiphanyProposeParams {
thread_id,
observation_ids,
} = params;
let ThreadEpiphanyProposeParams { thread_id, .. } = &params;
let thread_id = thread_id.clone();
let thread_uuid = match ThreadId::from_string(&thread_id) {
Ok(id) => id,
@ -588,12 +562,8 @@ impl CodexMessageProcessor {
return;
}
};
let expected_revision = state.revision;
let proposal = match codex_core::propose_map_update(EpiphanyMapProposalInput {
state,
observation_ids,
}) {
Ok(proposal) => proposal,
let response = match map_epiphany_propose_response(state, params.observation_ids) {
Ok(response) => response,
Err(err) => {
self.send_invalid_request_error(
request_id,
@ -603,17 +573,6 @@ impl CodexMessageProcessor {
return;
}
};
let response = ThreadEpiphanyProposeResponse {
expected_revision,
patch: ThreadEpiphanyUpdatePatch {
observations: vec![proposal.observation],
evidence: vec![proposal.evidence],
graphs: Some(proposal.graphs),
graph_frontier: Some(proposal.graph_frontier),
churn: Some(proposal.churn),
..Default::default()
},
};
self.outgoing.send_response(request_id, response).await;
}