use super::*;
impl Controller {
pub(super) fn subagent_parent_worktree(
&self,
id: &str,
) -> Option<&mj_core::state::ManagedWorktree> {
let relation = self.state.subagents.get(id)?;
self.state
.sessions
.get(&relation.parent_session_id)?
.managed_worktree
.as_ref()
}
}
pub(super) fn project_memory_launch(
session: &mj_core::state::SessionRecord,
bundle: Option<&ProjectBundle>,
workspace: &(String, Vec<String>),
target_profile_home: &str,
parent_worktree: Option<&mj_core::state::ManagedWorktree>,
) -> Result<ProjectMemoryLaunchConfig> {
let identity = if let Some(project) = &session.project {
project.memory_identity()?
} else {
ProjectMemoryIdentity::for_legacy_session(session, bundle, parent_worktree)?
};
let project_key = identity.key()?;
let replica_slug = project_memory_replica_slug(&project_key, &session.id);
let project_root = PathBuf::from(target_profile_home)
.join("projects")
.join(replica_slug);
let root = project_root.join("memory");
let baseline_root = project_root.join(".hel-memory-baseline");
let mut repository_roots = std::collections::BTreeMap::new();
if let Some(bundle) = bundle {
let target_roots =
std::iter::once(workspace.0.as_str()).chain(workspace.1.iter().map(String::as_str));
let repositories = std::iter::once(bundle.primary().context("bundle primary is missing")?)
.chain(
bundle
.repositories
.iter()
.filter(|repository| repository.id != bundle.primary_repo),
);
repository_roots.extend(
repositories
.zip(target_roots)
.map(|(repository, root)| (repository.id.clone(), PathBuf::from(root))),
);
}
Ok(ProjectMemoryLaunchConfig {
history_socket: None,
project_key,
root,
baseline_root,
repository_roots,
mcp_delivery: ProjectMemoryMcpDelivery::Acp,
})
}
pub(super) fn project_memory_replica_slug(project_key: &str, session_id: &str) -> String {
format!("hel-{}-{session_id}", &project_key[..16])
}
pub(super) fn project_memory_mcp_delivery(
harness: mj_core::config::HarnessKind,
target: &targets::TargetLocator,
) -> ProjectMemoryMcpDelivery {
if harness == mj_core::config::HarnessKind::Kimi
&& !matches!(target, targets::TargetLocator::LocalBare { .. })
{
ProjectMemoryMcpDelivery::HarnessProfile
} else {
ProjectMemoryMcpDelivery::Acp
}
}
pub(super) fn canonical_memory_root(project_key: &str) -> PathBuf {
data_dir().join("projects").join(project_key).join("memory")
}
pub(super) fn stage_memory_replica(
memory: &ProjectMemoryLaunchConfig,
target_profile_home: &Path,
profile_stage: &Path,
) -> Result<()> {
let canonical = mj_core::project_memory::resolve_canonical_root(&canonical_memory_root(
&memory.project_key,
))?;
std::fs::create_dir_all(&canonical)?;
let replica = memory.root.strip_prefix(target_profile_home)?;
let baseline = memory.baseline_root.strip_prefix(target_profile_home)?;
copy_profile_entry(&canonical, &profile_stage.join(replica))?;
copy_profile_entry(&canonical, &profile_stage.join(baseline))
}