feat: add lua profile authoring

This commit is contained in:
2026-05-30 11:45:49 +09:00
parent 20f72214d7
commit cba46c6a39
12 changed files with 1058 additions and 567 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ pub struct SpawnConfig {
/// (`manifest::paths::pod_runtime_dir`) の解決と、ready 行に乗る
/// 名前との突き合わせに使う。
pub pod_name: String,
/// Optional Nix profile selector. When present the child is launched with
/// Optional profile selector. When present the child is launched with
/// `--profile`; the Pod name is supplied through `--profile-pod-name` so
/// profile evaluation stays separate from `--pod` restore semantics.
pub profile: Option<String>,
+1
View File
@@ -7,6 +7,7 @@ license.workspace = true
[dependencies]
arc-swap = "1"
llm-worker = { workspace = true }
mlua = { version = "0.11.4", features = ["lua54", "vendored", "serialize"] }
protocol = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
+4 -4
View File
@@ -20,9 +20,9 @@ pub use paths::{
user_profiles_path,
};
pub use profile::{
NixProfileResolver, ProfileDiscovery, ProfileError, ProfileManifestSnapshot, ProfileMetadata,
ProfileRegistry, ProfileRegistryEntry, ProfileRegistrySource, ProfileSelector, ProfileSource,
ResolvedProfile, resolve_profile_artifact,
ProfileDiscovery, ProfileError, ProfileManifestSnapshot, ProfileMetadata, ProfileRegistry,
ProfileRegistryEntry, ProfileRegistrySource, ProfileResolveOptions, ProfileResolver,
ProfileSelector, ProfileSource, ResolvedProfile, resolve_profile_artifact,
};
pub use protocol::{Permission, ScopeRule};
pub use scope::{Scope, ScopeError, SharedScope};
@@ -74,7 +74,7 @@ pub struct PodManifest {
/// there is no implicit `$config_dir/skills/` or builtin probe.
#[serde(default)]
pub skills: Option<SkillsConfig>,
/// Optional profile provenance for manifests produced by a Nix profile.
/// Optional profile provenance for manifests produced by profile resolution.
/// Stored only after profile resolution so Pod restore can prefer the
/// validated snapshot over ambient manifest cascade state.
#[serde(default, skip_serializing_if = "Option::is_none")]
+3 -3
View File
@@ -145,10 +145,10 @@ pub fn resource_dir() -> Option<PathBuf> {
)
}
/// Bundled profile registry directory. Missing directories are treated as an
/// empty builtin registry by discovery.
/// Bundled Lua profile registry directory. Missing directories are treated as
/// an empty builtin registry by discovery.
pub fn builtin_profiles_dir() -> Option<PathBuf> {
Some(resource_dir()?.join("nix").join("profiles"))
Some(resource_dir()?.join("profiles"))
}
/// `<config_dir>/prompts.toml` — user prompt pack。
File diff suppressed because it is too large Load Diff
+10 -8
View File
@@ -2,7 +2,9 @@ use std::path::{Path, PathBuf};
use std::process::ExitCode;
use clap::Parser;
use manifest::{NixProfileResolver, PodManifest, PodManifestConfig, ProfileSelector, paths};
use manifest::{
PodManifest, PodManifestConfig, ProfileResolveOptions, ProfileResolver, ProfileSelector, paths,
};
use pod::{Pod, PodController, PromptLoader};
use pod_store::{CombinedStore, FsPodStore, PodMetadataStore};
use session_store::{FsStore, SegmentId, Store};
@@ -10,10 +12,10 @@ use session_store::{FsStore, SegmentId, Store};
#[derive(Debug, Parser)]
#[command(
name = "insomnia-pod",
about = "Spawn a Pod process from a Nix profile or a single manifest file"
about = "Spawn a Pod process from a profile or a single manifest file"
)]
struct Cli {
/// Nix profile to evaluate. Accepts an explicit path, `path:<path>`, a
/// Profile to evaluate. Accepts an explicit path, `path:<path>`, a
/// discovered profile name, `default`, or a source-qualified name such as
/// `project:coder`.
#[arg(
@@ -145,16 +147,16 @@ fn load_profile(
) -> Result<(PodManifest, PromptLoader), String> {
let cwd = std::env::current_dir()
.map_err(|e| format!("failed to resolve current directory for profile: {e}"))?;
let resolver = NixProfileResolver::new().with_workspace_base(cwd);
let mut resolved = resolver.resolve(selector).map_err(|e| {
let resolver = ProfileResolver::new().with_workspace_base(cwd);
let options = pod_name_override
.map(ProfileResolveOptions::with_pod_name)
.unwrap_or_default();
let resolved = resolver.resolve(selector, options).map_err(|e| {
format!(
"failed to resolve profile {}: {e}",
selector.display_label()
)
})?;
if let Some(pod_name) = pod_name_override {
resolved.manifest.pod.name = pod_name.to_string();
}
Ok((resolved.manifest, PromptLoader::builtins_only()))
}
+1 -1
View File
@@ -415,7 +415,7 @@ struct Form {
/// When true, launch the child with `--pod <name>` so the pod process
/// resolves name-keyed state before falling back to fresh creation.
resume_by_pod_name: bool,
/// Optional Nix profile choices passed to `insomnia-pod --profile` for
/// Optional profile choices passed to `insomnia-pod --profile` for
/// fresh spawns. This is not used for resume/attach flows because those must
/// restore Pod state rather than re-evaluate a profile source.
profile_choices: Vec<ProfileChoice>,