P3 backend: files, skills, routines, claw chat with LIVE taint plumbing
- tc-files: BlobStore trait + LocalBlobStore (traversal-proof keys); wired through Runtime (config storage.data_dir in deployments) - File tools: files.write/files.list (workspace-internal) + files.delete (gated FileDeletion — tested: file survives pending, gone after approve); GET /api/openclaw/files + /api/shared-drive/files (drive/agent scoped) - Skills: catalog/library + idempotent install with counter, uninstall; GET /api/skills[?clawId=], POST install/uninstall - tc-scheduler: croner cron math (clock-controlled tests), SKIP LOCKED claim-and-advance firing REAL runs into dedicated '⏰ name' sessions (reused, exactly-once), paused routines skipped; routines API + agent tool routine.schedule; loop spawned in server - Claw chat: 1:1 threads, chat.send enforcing the target's Other-Claws policy, chat.inbox whose output carries inter_agent taint; the run loop now ACCUMULATES taint from tool outputs into LoopState, classifies with it, and stamps steps + approvals — a poisoned inbox followed by email.send produces an approval whose taint_sources says inter_agent - ScriptedProvider scenario selection now keys on the most recent marker (session history kept earlier markers alive) 132 Rust tests green. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ea5162ac65
commit
67f918439c
@@ -87,16 +87,21 @@ impl ScriptedProvider {
|
||||
#[async_trait::async_trait]
|
||||
impl LlmProvider for ScriptedProvider {
|
||||
async fn stream(&self, request: ChatRequest) -> Result<EventStream, LlmError> {
|
||||
// Scenario selection keys on the MOST RECENT text carrying any
|
||||
// marker: earlier turns keep their markers in session history, and
|
||||
// the latest user intent must win.
|
||||
let prompt_text: String = request
|
||||
.messages
|
||||
.iter()
|
||||
.rev()
|
||||
.flat_map(|m| m.parts.iter())
|
||||
.filter_map(|p| match p {
|
||||
ContentPart::Text { text } => Some(text.as_str()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
.find(|text| self.scenarios.iter().any(|s| text.contains(&s.marker)))
|
||||
.unwrap_or_default()
|
||||
.to_owned();
|
||||
// Which leg of a multi-tool conversation is this? One ToolResult in
|
||||
// the request means turn 0 already played; play turn 1, and so on.
|
||||
let turn_index = request
|
||||
|
||||
Reference in New Issue
Block a user