メモリーに関するクレート作成・ファイル構造の実装

This commit is contained in:
2026-04-27 13:33:31 +09:00
parent c7a873bcf9
commit f2e47629d0
33 changed files with 2780 additions and 32 deletions
+1
View File
@@ -25,6 +25,7 @@ include_dir = "0.7.4"
fs4 = { version = "0.13.1", features = ["sync"] }
libc = "0.2.185"
schemars = "1.2.1"
memory = { version = "0.1.0", path = "../memory" }
[dev-dependencies]
async-trait = "0.1.89"
+18
View File
@@ -117,6 +117,7 @@ impl PodController {
let pwd_for_tools = pod.pwd().to_path_buf();
let spawner_name = pod.manifest().pod.name.clone();
let spawner_model = pod.manifest().model.clone();
let memory_config = pod.manifest().memory.clone();
// Parent callback socket (this Pod's own parent, used for
// `PodEvent` upward reports). `None` for top-level Pods.
@@ -233,6 +234,23 @@ impl PodController {
let tracker = tools::Tracker::new();
worker.register_tools(tools::builtin_tools(fs, tracker.clone()));
// Memory subsystem opt-in. When `[memory]` is present in
// the manifest, register the memory-specific Read/Write/Edit
// tools that target `<workspace>/memory/` and
// `<workspace>/knowledge/` with their built-in linter. The
// companion deny rules on the generic CRUD scope were
// already applied during `Pod::from_manifest`.
if let Some(mem) = memory_config.as_ref() {
let workspace_root = mem
.workspace_root
.clone()
.unwrap_or_else(|| pwd_for_tools.clone());
let layout = memory::WorkspaceLayout::new(workspace_root);
worker.register_tool(memory::tool::read_tool(layout.clone()));
worker.register_tool(memory::tool::write_tool(layout.clone()));
worker.register_tool(memory::tool::edit_tool(layout));
}
// Pod-orchestration tools (SpawnPod + the four comm tools)
// share the Pod-scoped `SpawnedPodRegistry` hoisted above
// (also consumed by the main loop's `PodEvent` handler).
+21 -2
View File
@@ -1197,7 +1197,7 @@ impl<St: Store> Pod<Box<dyn LlmClient>, St> {
loader: PromptLoader,
) -> Result<Self, PodError> {
let pwd = current_pwd()?;
let scope = Scope::from_config(&manifest.scope).map_err(PodError::Scope)?;
let scope = build_scope_with_memory(&manifest, &pwd)?;
if !scope.is_readable(&pwd) {
return Err(PodError::PwdOutsideScope { pwd });
}
@@ -1279,7 +1279,7 @@ impl<St: Store> Pod<Box<dyn LlmClient>, St> {
callback_socket: PathBuf,
) -> Result<Self, PodError> {
let pwd = current_pwd()?;
let scope = Scope::from_config(&manifest.scope).map_err(PodError::Scope)?;
let scope = build_scope_with_memory(&manifest, &pwd)?;
if !scope.is_readable(&pwd) {
return Err(PodError::PwdOutsideScope { pwd });
}
@@ -1507,6 +1507,25 @@ pub enum PodError {
PromptCatalog(#[from] CatalogError),
}
/// Build the Pod's runtime [`Scope`] from the manifest, layering the
/// memory subsystem's deny-write rules on top when `[memory]` is
/// present. The deny rules cap generic CRUD tools so they cannot
/// touch `<workspace>/memory/` or `<workspace>/knowledge/` while the
/// memory tools (registered separately) bypass `ScopedFs` and write
/// through `std::fs` directly.
fn build_scope_with_memory(manifest: &PodManifest, pwd: &Path) -> Result<Scope, PodError> {
let mut scope_config = manifest.scope.clone();
if let Some(mem) = manifest.memory.as_ref() {
let root = mem
.workspace_root
.clone()
.unwrap_or_else(|| pwd.to_path_buf());
let layout = memory::WorkspaceLayout::new(root);
scope_config.deny.extend(memory::deny_write_rules(&layout));
}
Scope::from_config(&scope_config).map_err(PodError::Scope)
}
/// Snapshot the process's current working directory as the Pod's pwd,
/// canonicalising symlinks and any `.`/`..` components. The Pod keeps
/// this value for its lifetime; changes to the process-wide cwd after