Synced from monorepo
Synced from monorepo Changes: - Shell: accept target response id on rewind execute - Shell: stamp response id on chat user message chunks - Worktree: optional rebuild and stale git registration cleanup in auto-GC - Worktree: kind-aware auto-GC TTLs and config knobs - Worktree: macOS process CWD scan and Unix PID liveness for GC guards - Worktree: automatic throttled GC on startup (Linux age-based; non-Linux dead-only) - Pager: add `[ui].combine_queued_prompts` to batch queued follow-ups - Shell: stop overwriting user skills - Tools: read markdown in `skills/` directories untruncated - `/usage` shows per-session token and dollar usage in the TUI - Security: prompt on environment-dumping `ps` variants - Security: always-safe `kubectl` no longer runs arbitrary kubeconfig credential plugins without permission - Tools: make scheduler deletion durable - Shell: add relocation storage primitives - Shell: give side model calls their own conversation ids - Fix five workflow-runtime bugs (budget, pause, cancel, reconnect) - Security: peel `env -S` / `--split-string` operands in the Bash permission gate (managed deny/ask) - Pager: expose doctor in the TUI - Security: block unauthorized RCE via abused safe commands - Pager idle watcher cue: "1 subagent still running" instead of "watching · 1 subagent" - Security: block `rg --pre` arbitrary code execution in auto-mode - Voice: diagnose silent-mic failures (macOS permission) and add doctor/terminal-setup Voice section - App builder deployer: `allow_forking` and `show_built_with_grok` - Pager: stop stacking duplicate "Worked for" markers on parked turns - Shell: support `max` as a distinct reasoning effort tier - Tools: serialize background `/loop` fires on the whole work unit - Shell: add working-directory relocation state primitives - Proto: `ClientToolResult` and `ChatConfig` client-side tools - Shell: model providers - Chat: select App Builder product on the Build path - Shell: attach author identity to feedback when the deployment opts in - Doctor: fix for SSH wrap setup - Workflow authoring skills: create-workflow and import-claude-workflow docs - Add read-only grok doctor - Sandbox: apply Landlock without a controlling TTY - Pager: recover image paste over grok wrap on headless remotes - Pager: make actions screen-mode aware - Shell: resume sessions when the working directory moves - Pager: centralize terminal diagnostics - Workspace: gate inline shell file access - Pager: centralize terminal probes - Pager: edit minimal prompts in an external editor - Pager: standardize backgrounding on Ctrl+B - Shell: recap rides the parent turn's prompt cache - Tools: add scheduler lifecycle version clock Source-Revision: 0f4d7c91b8b2b408333f6de1e8a76cb8eaa71899
This commit is contained in:
parent
a881e6703f
commit
3af4d5d398
556 changed files with 56609 additions and 21892 deletions
|
|
@ -32,6 +32,6 @@ pub mod resume;
|
|||
pub mod types;
|
||||
|
||||
pub use config::{PersonaIOField, SubagentPersona, SubagentRole};
|
||||
pub use overrides::resolve_effective_overrides;
|
||||
pub use overrides::{intersect_capability_modes, resolve_effective_overrides};
|
||||
pub use resume::{ResumeValidationError, validate_resume_identity};
|
||||
pub use types::{ContextSource, EffectiveRuntimeConfig, ResolutionError, ResumeSourceData};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,23 @@ fn parse_enum_from_str<T: DeserializeOwned>(s: &str) -> Option<T> {
|
|||
serde_json::from_value::<T>(serde_json::Value::String(s.to_string())).ok()
|
||||
}
|
||||
|
||||
pub fn intersect_capability_modes(
|
||||
requested: Option<SubagentCapabilityMode>,
|
||||
ceiling: Option<SubagentCapabilityMode>,
|
||||
) -> Option<SubagentCapabilityMode> {
|
||||
use SubagentCapabilityMode as Mode;
|
||||
match (requested, ceiling) {
|
||||
(None, None) => None,
|
||||
(Some(mode), None) | (None, Some(mode)) => Some(mode),
|
||||
(Some(Mode::All), Some(mode)) | (Some(mode), Some(Mode::All)) => Some(mode),
|
||||
(Some(Mode::ReadOnly), Some(_)) | (Some(_), Some(Mode::ReadOnly)) => Some(Mode::ReadOnly),
|
||||
(Some(Mode::ReadWrite), Some(Mode::ReadWrite)) => Some(Mode::ReadWrite),
|
||||
(Some(Mode::Execute), Some(Mode::Execute)) => Some(Mode::Execute),
|
||||
(Some(Mode::ReadWrite), Some(Mode::Execute))
|
||||
| (Some(Mode::Execute), Some(Mode::ReadWrite)) => Some(Mode::ReadOnly),
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve effective runtime config from explicit overrides, role defaults,
|
||||
/// and persona defaults.
|
||||
///
|
||||
|
|
@ -58,13 +75,13 @@ pub fn resolve_effective_overrides(
|
|||
.or_else(|| role.and_then(|r| r.reasoning_effort.clone()));
|
||||
|
||||
// ── Capability mode resolution ───────────────────────────────
|
||||
let capability_mode = overrides.capability_mode.or_else(|| {
|
||||
role.and_then(|r| {
|
||||
r.default_capability_mode
|
||||
.as_deref()
|
||||
.and_then(parse_enum_from_str::<SubagentCapabilityMode>)
|
||||
})
|
||||
let role_capability_mode = role.and_then(|r| {
|
||||
r.default_capability_mode
|
||||
.as_deref()
|
||||
.and_then(parse_enum_from_str::<SubagentCapabilityMode>)
|
||||
});
|
||||
let capability_mode =
|
||||
intersect_capability_modes(overrides.capability_mode, role_capability_mode);
|
||||
|
||||
// ── Persona resolution ───────────────────────────────────────
|
||||
let persona = overrides.persona.clone();
|
||||
|
|
@ -225,6 +242,9 @@ mod tests {
|
|||
harness_agent_type: None,
|
||||
completion_output_cap: None,
|
||||
spawn_depth: None,
|
||||
output_token_budget: None,
|
||||
output_schema: None,
|
||||
loop_task_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -282,16 +302,10 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_capability_mode_overrides_role() {
|
||||
let overrides = make_overrides(
|
||||
None,
|
||||
None,
|
||||
Some(SubagentCapabilityMode::ReadOnly),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
fn explicit_capability_mode_intersects_role_ceiling() {
|
||||
let overrides = make_overrides(None, None, Some(SubagentCapabilityMode::All), None, None);
|
||||
let role = SubagentRole {
|
||||
default_capability_mode: Some("all".into()),
|
||||
default_capability_mode: Some("read-only".into()),
|
||||
..Default::default()
|
||||
};
|
||||
let result =
|
||||
|
|
@ -302,6 +316,17 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn incompatible_write_and_execute_modes_intersect_to_read_only() {
|
||||
assert_eq!(
|
||||
intersect_capability_modes(
|
||||
Some(SubagentCapabilityMode::ReadWrite),
|
||||
Some(SubagentCapabilityMode::Execute),
|
||||
),
|
||||
Some(SubagentCapabilityMode::ReadOnly)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn role_capability_mode_used_when_no_explicit() {
|
||||
let overrides = make_overrides(None, None, None, None, None);
|
||||
|
|
|
|||
Loading…
Reference in a new issue