feat: add lua profile authoring
This commit is contained in:
parent
20f72214d7
commit
cba46c6a39
102
Cargo.lock
generated
102
Cargo.lock
generated
|
|
@ -721,6 +721,17 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "erased-serde"
|
||||||
|
version = "0.4.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"typeid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.14"
|
version = "0.3.14"
|
||||||
|
|
@ -1714,6 +1725,25 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lua-src"
|
||||||
|
version = "550.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e836dc8ae16806c9bdcf42003a88da27d163433e3f9684c52f0301258004a4fb"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "luajit-src"
|
||||||
|
version = "210.6.6+707c12b"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a86cc925d4053d0526ae7f5bc765dbd0d7a5d1a63d43974f4966cb349ca63295"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"which",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mac_address"
|
name = "mac_address"
|
||||||
version = "1.1.8"
|
version = "1.1.8"
|
||||||
|
|
@ -1730,6 +1760,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"llm-worker",
|
"llm-worker",
|
||||||
|
"mlua",
|
||||||
"protocol",
|
"protocol",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_ignored",
|
"serde_ignored",
|
||||||
|
|
@ -1841,6 +1872,39 @@ dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua"
|
||||||
|
version = "0.11.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ccd36acfa49ce6ee56d1307a061dd302c564eee757e6e4cd67eb4f7204846fab"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"either",
|
||||||
|
"erased-serde",
|
||||||
|
"libc",
|
||||||
|
"mlua-sys",
|
||||||
|
"num-traits",
|
||||||
|
"parking_lot",
|
||||||
|
"rustc-hash",
|
||||||
|
"rustversion",
|
||||||
|
"serde",
|
||||||
|
"serde-value",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua-sys"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f1c3a7fc7580227ece249fd90aa2fa3b39eb2b49d3aec5e103b3e85f2c3dfc8"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"lua-src",
|
||||||
|
"luajit-src",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "native-tls"
|
name = "native-tls"
|
||||||
version = "0.2.18"
|
version = "0.2.18"
|
||||||
|
|
@ -1997,6 +2061,15 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-float"
|
||||||
|
version = "2.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "4.6.0"
|
version = "4.6.0"
|
||||||
|
|
@ -2876,6 +2949,16 @@ dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde-value"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||||
|
dependencies = [
|
||||||
|
"ordered-float 2.10.1",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_core"
|
name = "serde_core"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
|
|
@ -3288,7 +3371,7 @@ dependencies = [
|
||||||
"nix",
|
"nix",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"ordered-float",
|
"ordered-float 4.6.0",
|
||||||
"pest",
|
"pest",
|
||||||
"pest_derive",
|
"pest_derive",
|
||||||
"phf",
|
"phf",
|
||||||
|
|
@ -3679,6 +3762,12 @@ dependencies = [
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typeid"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.19.0"
|
version = "1.19.0"
|
||||||
|
|
@ -4024,7 +4113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac"
|
checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"ordered-float",
|
"ordered-float 4.6.0",
|
||||||
"strsim",
|
"strsim",
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
"wezterm-dynamic-derive",
|
"wezterm-dynamic-derive",
|
||||||
|
|
@ -4054,6 +4143,15 @@ dependencies = [
|
||||||
"wezterm-dynamic",
|
"wezterm-dynamic",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "which"
|
||||||
|
version = "8.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81995fafaaaf6ae47a7d0cc83c67caf92aeb7e5331650ae6ff856f7c0c60c459"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ pub struct SpawnConfig {
|
||||||
/// (`manifest::paths::pod_runtime_dir`) の解決と、ready 行に乗る
|
/// (`manifest::paths::pod_runtime_dir`) の解決と、ready 行に乗る
|
||||||
/// 名前との突き合わせに使う。
|
/// 名前との突き合わせに使う。
|
||||||
pub pod_name: String,
|
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`; the Pod name is supplied through `--profile-pod-name` so
|
||||||
/// profile evaluation stays separate from `--pod` restore semantics.
|
/// profile evaluation stays separate from `--pod` restore semantics.
|
||||||
pub profile: Option<String>,
|
pub profile: Option<String>,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ license.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
arc-swap = "1"
|
arc-swap = "1"
|
||||||
llm-worker = { workspace = true }
|
llm-worker = { workspace = true }
|
||||||
|
mlua = { version = "0.11.4", features = ["lua54", "vendored", "serialize"] }
|
||||||
protocol = { workspace = true }
|
protocol = { workspace = true }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@ pub use paths::{
|
||||||
user_profiles_path,
|
user_profiles_path,
|
||||||
};
|
};
|
||||||
pub use profile::{
|
pub use profile::{
|
||||||
NixProfileResolver, ProfileDiscovery, ProfileError, ProfileManifestSnapshot, ProfileMetadata,
|
ProfileDiscovery, ProfileError, ProfileManifestSnapshot, ProfileMetadata, ProfileRegistry,
|
||||||
ProfileRegistry, ProfileRegistryEntry, ProfileRegistrySource, ProfileSelector, ProfileSource,
|
ProfileRegistryEntry, ProfileRegistrySource, ProfileResolveOptions, ProfileResolver,
|
||||||
ResolvedProfile, resolve_profile_artifact,
|
ProfileSelector, ProfileSource, ResolvedProfile, resolve_profile_artifact,
|
||||||
};
|
};
|
||||||
pub use protocol::{Permission, ScopeRule};
|
pub use protocol::{Permission, ScopeRule};
|
||||||
pub use scope::{Scope, ScopeError, SharedScope};
|
pub use scope::{Scope, ScopeError, SharedScope};
|
||||||
|
|
@ -74,7 +74,7 @@ pub struct PodManifest {
|
||||||
/// there is no implicit `$config_dir/skills/` or builtin probe.
|
/// there is no implicit `$config_dir/skills/` or builtin probe.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub skills: Option<SkillsConfig>,
|
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
|
/// Stored only after profile resolution so Pod restore can prefer the
|
||||||
/// validated snapshot over ambient manifest cascade state.
|
/// validated snapshot over ambient manifest cascade state.
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
|
|
||||||
|
|
@ -145,10 +145,10 @@ pub fn resource_dir() -> Option<PathBuf> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bundled profile registry directory. Missing directories are treated as an
|
/// Bundled Lua profile registry directory. Missing directories are treated as
|
||||||
/// empty builtin registry by discovery.
|
/// an empty builtin registry by discovery.
|
||||||
pub fn builtin_profiles_dir() -> Option<PathBuf> {
|
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。
|
/// `<config_dir>/prompts.toml` — user prompt pack。
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -2,7 +2,9 @@ use std::path::{Path, PathBuf};
|
||||||
use std::process::ExitCode;
|
use std::process::ExitCode;
|
||||||
|
|
||||||
use clap::Parser;
|
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::{Pod, PodController, PromptLoader};
|
||||||
use pod_store::{CombinedStore, FsPodStore, PodMetadataStore};
|
use pod_store::{CombinedStore, FsPodStore, PodMetadataStore};
|
||||||
use session_store::{FsStore, SegmentId, Store};
|
use session_store::{FsStore, SegmentId, Store};
|
||||||
|
|
@ -10,10 +12,10 @@ use session_store::{FsStore, SegmentId, Store};
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(
|
#[command(
|
||||||
name = "insomnia-pod",
|
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 {
|
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
|
/// discovered profile name, `default`, or a source-qualified name such as
|
||||||
/// `project:coder`.
|
/// `project:coder`.
|
||||||
#[arg(
|
#[arg(
|
||||||
|
|
@ -145,16 +147,16 @@ fn load_profile(
|
||||||
) -> Result<(PodManifest, PromptLoader), String> {
|
) -> Result<(PodManifest, PromptLoader), String> {
|
||||||
let cwd = std::env::current_dir()
|
let cwd = std::env::current_dir()
|
||||||
.map_err(|e| format!("failed to resolve current directory for profile: {e}"))?;
|
.map_err(|e| format!("failed to resolve current directory for profile: {e}"))?;
|
||||||
let resolver = NixProfileResolver::new().with_workspace_base(cwd);
|
let resolver = ProfileResolver::new().with_workspace_base(cwd);
|
||||||
let mut resolved = resolver.resolve(selector).map_err(|e| {
|
let options = pod_name_override
|
||||||
|
.map(ProfileResolveOptions::with_pod_name)
|
||||||
|
.unwrap_or_default();
|
||||||
|
let resolved = resolver.resolve(selector, options).map_err(|e| {
|
||||||
format!(
|
format!(
|
||||||
"failed to resolve profile {}: {e}",
|
"failed to resolve profile {}: {e}",
|
||||||
selector.display_label()
|
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()))
|
Ok((resolved.manifest, PromptLoader::builtins_only()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -415,7 +415,7 @@ struct Form {
|
||||||
/// When true, launch the child with `--pod <name>` so the pod process
|
/// When true, launch the child with `--pod <name>` so the pod process
|
||||||
/// resolves name-keyed state before falling back to fresh creation.
|
/// resolves name-keyed state before falling back to fresh creation.
|
||||||
resume_by_pod_name: bool,
|
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
|
/// fresh spawns. This is not used for resume/attach flows because those must
|
||||||
/// restore Pod state rather than re-evaluate a profile source.
|
/// restore Pod state rather than re-evaluate a profile source.
|
||||||
profile_choices: Vec<ProfileChoice>,
|
profile_choices: Vec<ProfileChoice>,
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ permission = "write"
|
||||||
|
|
||||||
### Manifest / profile 入力
|
### Manifest / profile 入力
|
||||||
|
|
||||||
通常の Pod 起動は Nix profile discovery/default から `PodManifest` を生成する。bundled `builtin:default` が fallback default で、user/project `profiles.toml` は profile registry と default selection だけを担う。user/project `manifest.toml` の ambient cascade は通常起動では使わない。
|
通常の Pod 起動は Lua profile discovery/default から `PodManifest` を生成する。bundled `builtin:default` が fallback default で、user/project `profiles.toml` は profile registry と default selection だけを担う。user/project `manifest.toml` の ambient cascade は通常起動では使わない。
|
||||||
|
|
||||||
`insomnia-pod --manifest <PATH>` は explicit one-file compatibility/debug input で、指定 TOML 1 枚だけに builtin defaults を merge し、`PodManifestConfig -> PodManifest` の required validation を通す。
|
`insomnia-pod --manifest <PATH>` は explicit one-file compatibility/debug input で、指定 TOML 1 枚だけに builtin defaults を merge し、`PodManifestConfig -> PodManifest` の required validation を通す。
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,55 @@
|
||||||
# Manifest profiles
|
# Manifest profiles
|
||||||
|
|
||||||
Manifest profiles are the human-authored Nix entrypoint for generating an Insomnia runtime manifest. The Rust side evaluates a selected profile with `nix eval --json --file <path>`, deserializes the resulting JSON artifact, and validates it through the existing `PodManifest` pipeline.
|
Profiles are reusable Lua-authored recipes for generating an Insomnia runtime manifest. The Rust resolver evaluates a selected `.lua` profile in-process, validates that it is Profile-shaped rather than a complete Manifest, then binds runtime values such as Pod name and concrete scope to produce the persisted `PodManifest` snapshot.
|
||||||
|
|
||||||
This keeps composition/import/common logic in Nix. Insomnia does not add an implicit profile cascade or merge TOML profile layers into the selected runtime manifest.
|
Profiles are intentionally not authority-bearing manifests. `pod.name`, concrete `scope.allow` / `scope.deny`, runtime directories, sockets, active session state, and raw secret material do not belong in reusable profiles. Use `--manifest` when you need the explicit low-level complete Manifest escape hatch.
|
||||||
|
|
||||||
## Minimal profile
|
## Minimal profile
|
||||||
|
|
||||||
```nix
|
```lua
|
||||||
let
|
local profile = require("insomnia.profile")
|
||||||
insomnia = import ./resources/nix/profile-lib.nix {};
|
local models = require("insomnia.models")
|
||||||
in
|
local scope = require("insomnia.scope")
|
||||||
insomnia.mkProfile {
|
|
||||||
name = "coder";
|
return profile {
|
||||||
description = "Example coding Pod";
|
slug = "coder",
|
||||||
manifest = insomnia.mkManifest {
|
description = "Example coding Pod",
|
||||||
pod.name = "coder";
|
|
||||||
model = {
|
model = models.catalog("codex-oauth/gpt-5.5"),
|
||||||
scheme = "anthropic";
|
worker = {
|
||||||
model_id = "claude-sonnet-4-20250514";
|
reasoning = "high",
|
||||||
auth = insomnia.secrets.ref "llm.anthropic.default";
|
},
|
||||||
};
|
scope = scope.workspace_write(),
|
||||||
scope.allow = [
|
|
||||||
{ target = "."; permission = "write"; }
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Run an explicit path with:
|
Run an explicit path with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
insomnia-pod --profile ./coder.nix
|
insomnia-pod --profile ./coder.lua
|
||||||
# or through the TUI fresh-spawn dialog
|
# or through the TUI fresh-spawn dialog
|
||||||
insomnia --profile ./coder.nix
|
insomnia --profile ./coder.lua
|
||||||
```
|
```
|
||||||
|
|
||||||
`--profile` accepts an explicit path, `path:<path>`, a discovered profile name, `default`, or a source-qualified name such as `project:coder`, `user:coder`, or `builtin:coder`. Path-like values containing `/`, starting with `.`, or ending in `.nix` preserve the original explicit-path behavior.
|
`--profile` accepts an explicit path, `path:<path>`, a discovered profile name, `default`, or a source-qualified name such as `project:coder`, `user:coder`, or `builtin:coder`. Path-like values containing `/`, starting with `.`, or ending in `.lua` are explicit paths. `.nix` paths are no longer the primary profile layer and fail with a diagnostic that points users at Lua profiles or `--manifest`.
|
||||||
|
|
||||||
`--profile` conflicts with `insomnia-pod --manifest` and with restore/session/adopt modes. Use `--profile-pod-name <name>` when a launcher needs a creation-time Pod name override without invoking `--pod` restore semantics. Profile evaluation is a creation-time path; Pod resume restores saved Pod state/resolved snapshots rather than re-evaluating the Nix source.
|
`--profile` conflicts with `insomnia-pod --manifest` and with restore/session/adopt modes. Use `--profile-pod-name <name>` when a launcher needs a creation-time Pod name override without invoking `--pod` restore semantics. Profile evaluation is a creation-time path; Pod resume restores saved Pod state/resolved snapshots rather than re-evaluating the profile source.
|
||||||
|
|
||||||
|
## Controlled Lua environment
|
||||||
|
|
||||||
|
Profiles run in a restricted Lua VM. Host virtual modules are available through controlled `require`:
|
||||||
|
|
||||||
|
- `require("insomnia")`
|
||||||
|
- `require("insomnia.profile")`
|
||||||
|
- `require("insomnia.models")`
|
||||||
|
- `require("insomnia.compact")`
|
||||||
|
- `require("insomnia.scope")`
|
||||||
|
|
||||||
|
Profile-local modules may be required by dotted names such as `require("shared")` or `require("shared.models")`; those resolve only under the selected profile file's directory. Unsafe/unrestricted Lua facilities such as `os`, `io`, `debug`, `package`, `dofile`, and `loadfile` are unavailable by default.
|
||||||
|
|
||||||
## Profile discovery
|
## Profile discovery
|
||||||
|
|
||||||
Profile discovery is separate from runtime manifest merging. User/project `profiles.toml` files may declare profile registry metadata, but those files are application/project UX configuration and are not merged into the Nix profile artifact.
|
Profile discovery is separate from runtime manifest merging. User/project `profiles.toml` files may declare profile registry metadata, but those files are application/project UX configuration and are not merged into the selected profile artifact.
|
||||||
|
|
||||||
Example project config at `.insomnia/profiles.toml`:
|
Example project config at `.insomnia/profiles.toml`:
|
||||||
|
|
||||||
|
|
@ -49,15 +57,15 @@ Example project config at `.insomnia/profiles.toml`:
|
||||||
default = "coder"
|
default = "coder"
|
||||||
|
|
||||||
[profile]
|
[profile]
|
||||||
coder = "profiles/coder.nix"
|
coder = "profiles/coder.lua"
|
||||||
reviewer = "profiles/reviewer.nix"
|
reviewer = "profiles/reviewer.lua"
|
||||||
```
|
```
|
||||||
|
|
||||||
Table entries can carry descriptions:
|
Table entries can carry descriptions:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[profile.coder]
|
[profile.coder]
|
||||||
path = "profiles/coder.nix"
|
path = "profiles/coder.lua"
|
||||||
description = "Project coding assistant"
|
description = "Project coding assistant"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -77,22 +85,8 @@ The fresh-spawn TUI also uses discovery. The new Pod dialog defaults to the sele
|
||||||
|
|
||||||
Ambient user/project `manifest.toml` cascade startup has been removed. Normal fresh spawns use profile discovery/default selection, with `profiles.toml` acting only as a profile registry/default selector.
|
Ambient user/project `manifest.toml` cascade startup has been removed. Normal fresh spawns use profile discovery/default selection, with `profiles.toml` acting only as a profile registry/default selector.
|
||||||
|
|
||||||
## Artifact contract
|
## Resolver contract
|
||||||
|
|
||||||
A profile should evaluate to one of:
|
A Lua profile should return either `profile { ... }` or a plain table containing Profile fields. The resolver converts reusable fields such as `model`, `worker`, `compaction`, `memory`, `web`, `permissions`, `session`, and scope intent into a concrete Manifest. Runtime Pod name and concrete scope authority are supplied by launch context, then the resolved Manifest snapshot is persisted for restore.
|
||||||
|
|
||||||
- `{ profile = { format = "insomnia.nix-profile.v1"; ... }; manifest = { ... }; }`
|
|
||||||
- `{ profile = { format = "insomnia.nix-profile.v1"; ... }; config = { ... }; }`
|
|
||||||
- a raw manifest/config object for debug/test paths.
|
|
||||||
|
|
||||||
The resolved artifact is deserialized into the same `PodManifestConfig -> PodManifest` boundary used by direct one-file manifests, so builtin defaults and required-field validation stay shared. Explicit profile paths and user/project registry profile artifacts resolve relative manifest paths against the profile file's directory. Builtin profile artifacts resolve manifest-relative paths against the launch workspace/current directory so the bundled default can grant `scope.allow target = "."` for the workspace rather than for `resources/nix/profiles`.
|
|
||||||
|
|
||||||
Profile and one-file manifest CLI paths currently use builtin prompt assets only. `$insomnia/...` instruction refs work; `$user/...` and `$workspace/...` prompt refs need a future explicit prompt-loader source design instead of reviving ambient manifest discovery.
|
Profile and one-file manifest CLI paths currently use builtin prompt assets only. `$insomnia/...` instruction refs work; `$user/...` and `$workspace/...` prompt refs need a future explicit prompt-loader source design instead of reviving ambient manifest discovery.
|
||||||
|
|
||||||
Secret values must stay as typed references. `resources/nix/profile-lib.nix` emits secret references as JSON like:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "kind": "secret_ref", "ref": "llm.anthropic.default" }
|
|
||||||
```
|
|
||||||
|
|
||||||
The encrypted secret store is intentionally not implemented by this profile foundation; attempting to use a `secret_ref` as a live provider credential currently fails with a clear diagnostic at provider construction time.
|
|
||||||
|
|
|
||||||
|
|
@ -345,8 +345,8 @@ insomnia-pod [--profile <selector>] [--profile-pod-name <name>] [-s/--store <pat
|
||||||
|
|
||||||
| フラグ | 説明 |
|
| フラグ | 説明 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `--profile <selector>` | builtin/user/project profile registry から Nix profile を選択。省略時は registry default(通常は `builtin:default`) |
|
| `--profile <selector>` | builtin/user/project profile registry から Lua profile を選択。省略時は registry default(通常は `builtin:default`) |
|
||||||
| `--profile-pod-name <name>` | profile 由来 manifest の `pod.name` を fresh spawn 用に上書き |
|
| `--profile-pod-name <name>` | profile resolution 時に fresh spawn 用の runtime `pod.name` を指定 |
|
||||||
| `-s, --store <path>` | セッション永続化ディレクトリ(デフォルト: `<data_dir>/sessions/`、`manifest::paths` で解決) |
|
| `-s, --store <path>` | セッション永続化ディレクトリ(デフォルト: `<data_dir>/sessions/`、`manifest::paths` で解決) |
|
||||||
| `--session <uuid>` | 既存 session id から Pod を復元し、同じ jsonl に後続 turn を追記する |
|
| `--session <uuid>` | 既存 session id から Pod を復元し、同じ jsonl に後続 turn を追記する |
|
||||||
|
|
||||||
|
|
|
||||||
42
resources/profiles/default.lua
Normal file
42
resources/profiles/default.lua
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
local profile = require("insomnia.profile")
|
||||||
|
local scope = require("insomnia.scope")
|
||||||
|
local compact = require("insomnia.compact")
|
||||||
|
|
||||||
|
return profile {
|
||||||
|
slug = "default",
|
||||||
|
description = "Bundled default Insomnia coding profile",
|
||||||
|
|
||||||
|
scope = scope.workspace_write(),
|
||||||
|
|
||||||
|
session = {
|
||||||
|
record_event_trace = true,
|
||||||
|
},
|
||||||
|
|
||||||
|
worker = {
|
||||||
|
reasoning = "high",
|
||||||
|
},
|
||||||
|
|
||||||
|
model = {
|
||||||
|
ref = "codex-oauth/gpt-5.5",
|
||||||
|
},
|
||||||
|
|
||||||
|
compaction = compact.tokens {
|
||||||
|
threshold = 200000,
|
||||||
|
request_threshold = 240000,
|
||||||
|
worker_context_max_tokens = 100000,
|
||||||
|
},
|
||||||
|
|
||||||
|
memory = {
|
||||||
|
extract_threshold = 50000,
|
||||||
|
consolidation_threshold_files = 5,
|
||||||
|
consolidation_threshold_bytes = 50000,
|
||||||
|
},
|
||||||
|
|
||||||
|
web = {
|
||||||
|
enabled = true,
|
||||||
|
search = {
|
||||||
|
provider = "brave",
|
||||||
|
api_key_env = "BRAVE_SEARCH_API_KEY",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user