feat(sdk,plugins): API publique d'accès fichiers/workspace + analyse structure (#124,#129)

This commit is contained in:
2026-08-02 13:34:54 +02:00
parent 033e9a86d5
commit dce61ae1aa
27 changed files with 5895 additions and 94 deletions

View File

@ -366,6 +366,15 @@ pub enum DomainEvent {
/// The project.
project_id: ProjectId,
},
/// A file under a project workspace changed through a public plugin workspace API.
PluginWorkspaceFileChanged {
/// The owning project.
project_id: ProjectId,
/// Normalized path relative to the project root.
path: String,
/// Public operation label, for example `changed`.
operation: String,
},
/// An orchestrator request (dropped under `.ideai/requests/`) was processed
/// by IdeA on behalf of a requester agent (ARCHITECTURE §14.3). Relayed so the
/// frontend can surface orchestration activity; the resulting cell/tab opens

View File

@ -480,6 +480,17 @@ pub struct DirEntry {
pub is_dir: bool,
}
/// Basic metadata returned by [`FileSystem::metadata`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileMetadata {
/// Whether the path points to a regular file.
pub is_file: bool,
/// Whether the path points to a directory.
pub is_dir: bool,
/// File length in bytes when known.
pub len: Option<u64>,
}
/// An owned, boxed stream of PTY output chunks.
///
/// Concrete adapters decide the underlying transport; the domain only sees a
@ -1281,6 +1292,12 @@ pub trait ProcessSpawner: Send + Sync {
async fn run(&self, spec: SpawnSpec) -> Result<Output, ProcessError>;
}
/// Reads host environment variables through an injected adapter.
pub trait EnvironmentReader: Send + Sync {
/// Returns one environment variable value, if present.
fn get(&self, name: &str) -> Option<String>;
}
/// Read a local structured CLI version using only the allowed `--version` probe.
#[async_trait]
pub trait CliVersionReader: Send + Sync {
@ -1526,6 +1543,25 @@ pub trait FileSystem: Send + Sync {
/// [`FsError`] on failure.
async fn exists(&self, path: &RemotePath) -> Result<bool, FsError>;
/// Returns basic metadata for a path.
///
/// The default keeps older remote/test adapters source-compatible. Concrete
/// adapters that can cheaply stat paths should override it.
///
/// # Errors
/// [`FsError`] on failure.
async fn metadata(&self, path: &RemotePath) -> Result<FileMetadata, FsError> {
if self.exists(path).await? {
Ok(FileMetadata {
is_file: false,
is_dir: false,
len: None,
})
} else {
Err(FsError::NotFound(path.as_str().to_owned()))
}
}
/// Removes a single file. A **missing** file is treated as success (idempotent
/// delete), so this is safe to call best-effort.
///