mirror of
https://github.com/instructkr/claw-code.git
synced 2026-04-09 01:24:49 +08:00
style: cargo fmt
This commit is contained in:
BIN
assets/sigrid-photo.png
Normal file
BIN
assets/sigrid-photo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
2
rust/.claw/sessions/session-1775386832313-0.jsonl
Normal file
2
rust/.claw/sessions/session-1775386832313-0.jsonl
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
{"created_at_ms":1775386832313,"session_id":"session-1775386832313-0","type":"session_meta","updated_at_ms":1775386832313,"version":1}
|
||||||
|
{"message":{"blocks":[{"text":"status --help","type":"text"}],"role":"user"},"type":"message"}
|
||||||
2
rust/.claw/sessions/session-1775386842352-0.jsonl
Normal file
2
rust/.claw/sessions/session-1775386842352-0.jsonl
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
{"created_at_ms":1775386842352,"session_id":"session-1775386842352-0","type":"session_meta","updated_at_ms":1775386842352,"version":1}
|
||||||
|
{"message":{"blocks":[{"text":"doctor --help","type":"text"}],"role":"user"},"type":"message"}
|
||||||
2
rust/.claw/sessions/session-1775386852257-0.jsonl
Normal file
2
rust/.claw/sessions/session-1775386852257-0.jsonl
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
{"created_at_ms":1775386852257,"session_id":"session-1775386852257-0","type":"session_meta","updated_at_ms":1775386852257,"version":1}
|
||||||
|
{"message":{"blocks":[{"text":"doctor --help","type":"text"}],"role":"user"},"type":"message"}
|
||||||
2
rust/.claw/sessions/session-1775386853666-0.jsonl
Normal file
2
rust/.claw/sessions/session-1775386853666-0.jsonl
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
{"created_at_ms":1775386853666,"session_id":"session-1775386853666-0","type":"session_meta","updated_at_ms":1775386853666,"version":1}
|
||||||
|
{"message":{"blocks":[{"text":"status --help","type":"text"}],"role":"user"},"type":"message"}
|
||||||
@@ -114,8 +114,12 @@ impl LaneEvent {
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn finished(emitted_at: impl Into<String>, detail: Option<String>) -> Self {
|
pub fn finished(emitted_at: impl Into<String>, detail: Option<String>) -> Self {
|
||||||
Self::new(LaneEventName::Finished, LaneEventStatus::Completed, emitted_at)
|
Self::new(
|
||||||
.with_optional_detail(detail)
|
LaneEventName::Finished,
|
||||||
|
LaneEventStatus::Completed,
|
||||||
|
emitted_at,
|
||||||
|
)
|
||||||
|
.with_optional_detail(detail)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@@ -161,19 +165,14 @@ impl LaneEvent {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use super::{
|
use super::{LaneEvent, LaneEventBlocker, LaneEventName, LaneEventStatus, LaneFailureClass};
|
||||||
LaneEvent, LaneEventBlocker, LaneEventName, LaneEventStatus, LaneFailureClass,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn canonical_lane_event_names_serialize_to_expected_wire_values() {
|
fn canonical_lane_event_names_serialize_to_expected_wire_values() {
|
||||||
let cases = [
|
let cases = [
|
||||||
(LaneEventName::Started, "lane.started"),
|
(LaneEventName::Started, "lane.started"),
|
||||||
(LaneEventName::Ready, "lane.ready"),
|
(LaneEventName::Ready, "lane.ready"),
|
||||||
(
|
(LaneEventName::PromptMisdelivery, "lane.prompt_misdelivery"),
|
||||||
LaneEventName::PromptMisdelivery,
|
|
||||||
"lane.prompt_misdelivery",
|
|
||||||
),
|
|
||||||
(LaneEventName::Blocked, "lane.blocked"),
|
(LaneEventName::Blocked, "lane.blocked"),
|
||||||
(LaneEventName::Red, "lane.red"),
|
(LaneEventName::Red, "lane.red"),
|
||||||
(LaneEventName::Green, "lane.green"),
|
(LaneEventName::Green, "lane.green"),
|
||||||
@@ -193,7 +192,10 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (event, expected) in cases {
|
for (event, expected) in cases {
|
||||||
assert_eq!(serde_json::to_value(event).expect("serialize event"), json!(expected));
|
assert_eq!(
|
||||||
|
serde_json::to_value(event).expect("serialize event"),
|
||||||
|
json!(expected)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -599,7 +599,10 @@ mod tests {
|
|||||||
));
|
));
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
McpPhaseResult::Failure { phase: failed_phase, error } => {
|
McpPhaseResult::Failure {
|
||||||
|
phase: failed_phase,
|
||||||
|
error,
|
||||||
|
} => {
|
||||||
assert_eq!(failed_phase, phase);
|
assert_eq!(failed_phase, phase);
|
||||||
assert_eq!(error.phase, phase);
|
assert_eq!(error.phase, phase);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -360,8 +360,10 @@ impl McpServerManagerError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn recoverable(&self) -> bool {
|
fn recoverable(&self) -> bool {
|
||||||
!matches!(self.lifecycle_phase(), McpLifecyclePhase::InitializeHandshake)
|
!matches!(
|
||||||
&& matches!(self, Self::Transport { .. } | Self::Timeout { .. })
|
self.lifecycle_phase(),
|
||||||
|
McpLifecyclePhase::InitializeHandshake
|
||||||
|
) && matches!(self, Self::Transport { .. } | Self::Timeout { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn discovery_failure(&self, server_name: &str) -> McpDiscoveryFailure {
|
fn discovery_failure(&self, server_name: &str) -> McpDiscoveryFailure {
|
||||||
@@ -417,10 +419,9 @@ impl McpServerManagerError {
|
|||||||
("method".to_string(), (*method).to_string()),
|
("method".to_string(), (*method).to_string()),
|
||||||
("timeout_ms".to_string(), timeout_ms.to_string()),
|
("timeout_ms".to_string(), timeout_ms.to_string()),
|
||||||
]),
|
]),
|
||||||
Self::UnknownTool { qualified_name } => BTreeMap::from([(
|
Self::UnknownTool { qualified_name } => {
|
||||||
"qualified_tool".to_string(),
|
BTreeMap::from([("qualified_tool".to_string(), qualified_name.clone())])
|
||||||
qualified_name.clone(),
|
}
|
||||||
)]),
|
|
||||||
Self::UnknownServer { server_name } => {
|
Self::UnknownServer { server_name } => {
|
||||||
BTreeMap::from([("server".to_string(), server_name.clone())])
|
BTreeMap::from([("server".to_string(), server_name.clone())])
|
||||||
}
|
}
|
||||||
@@ -1425,11 +1426,10 @@ mod tests {
|
|||||||
use crate::mcp_client::McpClientBootstrap;
|
use crate::mcp_client::McpClientBootstrap;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
spawn_mcp_stdio_process, JsonRpcId, JsonRpcRequest, JsonRpcResponse,
|
spawn_mcp_stdio_process, unsupported_server_failed_server, JsonRpcId, JsonRpcRequest,
|
||||||
McpInitializeClientInfo, McpInitializeParams, McpInitializeResult, McpInitializeServerInfo,
|
JsonRpcResponse, McpInitializeClientInfo, McpInitializeParams, McpInitializeResult,
|
||||||
McpListToolsResult, McpReadResourceParams, McpReadResourceResult, McpServerManager,
|
McpInitializeServerInfo, McpListToolsResult, McpReadResourceParams, McpReadResourceResult,
|
||||||
McpServerManagerError, McpStdioProcess, McpTool, McpToolCallParams,
|
McpServerManager, McpServerManagerError, McpStdioProcess, McpTool, McpToolCallParams,
|
||||||
unsupported_server_failed_server,
|
|
||||||
};
|
};
|
||||||
use crate::McpLifecyclePhase;
|
use crate::McpLifecyclePhase;
|
||||||
|
|
||||||
@@ -2698,7 +2698,10 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert!(!report.failed_servers[0].recoverable);
|
assert!(!report.failed_servers[0].recoverable);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
report.failed_servers[0].context.get("method").map(String::as_str),
|
report.failed_servers[0]
|
||||||
|
.context
|
||||||
|
.get("method")
|
||||||
|
.map(String::as_str),
|
||||||
Some("initialize")
|
Some("initialize")
|
||||||
);
|
);
|
||||||
assert!(report.failed_servers[0].error.contains("initialize"));
|
assert!(report.failed_servers[0].error.contains("initialize"));
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ use std::fs;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::UNIX_EPOCH;
|
use std::time::UNIX_EPOCH;
|
||||||
|
|
||||||
|
|
||||||
use crate::session::{Session, SessionError};
|
use crate::session::{Session, SessionError};
|
||||||
|
|
||||||
pub const PRIMARY_SESSION_EXTENSION: &str = "jsonl";
|
pub const PRIMARY_SESSION_EXTENSION: &str = "jsonl";
|
||||||
|
|||||||
@@ -66,11 +66,7 @@ pub fn validate_packet(packet: TaskPacket) -> Result<ValidatedPacket, TaskPacket
|
|||||||
&packet.reporting_contract,
|
&packet.reporting_contract,
|
||||||
&mut errors,
|
&mut errors,
|
||||||
);
|
);
|
||||||
validate_required(
|
validate_required("escalation_policy", &packet.escalation_policy, &mut errors);
|
||||||
"escalation_policy",
|
|
||||||
&packet.escalation_policy,
|
|
||||||
&mut errors,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (index, test) in packet.acceptance_tests.iter().enumerate() {
|
for (index, test) in packet.acceptance_tests.iter().enumerate() {
|
||||||
if test.trim().is_empty() {
|
if test.trim().is_empty() {
|
||||||
@@ -146,9 +142,9 @@ mod tests {
|
|||||||
assert!(error
|
assert!(error
|
||||||
.errors()
|
.errors()
|
||||||
.contains(&"repo must not be empty".to_string()));
|
.contains(&"repo must not be empty".to_string()));
|
||||||
assert!(error.errors().contains(
|
assert!(error
|
||||||
&"acceptance_tests contains an empty value at index 1".to_string()
|
.errors()
|
||||||
));
|
.contains(&"acceptance_tests contains an empty value at index 1".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -76,11 +76,7 @@ impl TaskRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(&self, prompt: &str, description: Option<&str>) -> Task {
|
pub fn create(&self, prompt: &str, description: Option<&str>) -> Task {
|
||||||
self.create_task(
|
self.create_task(prompt.to_owned(), description.map(str::to_owned), None)
|
||||||
prompt.to_owned(),
|
|
||||||
description.map(str::to_owned),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_from_packet(
|
pub fn create_from_packet(
|
||||||
|
|||||||
@@ -257,7 +257,9 @@ impl WorkerRegistry {
|
|||||||
let prompt_preview = prompt_preview(worker.last_prompt.as_deref().unwrap_or_default());
|
let prompt_preview = prompt_preview(worker.last_prompt.as_deref().unwrap_or_default());
|
||||||
let message = match observation.target {
|
let message = match observation.target {
|
||||||
WorkerPromptTarget::Shell => {
|
WorkerPromptTarget::Shell => {
|
||||||
format!("worker prompt landed in shell instead of coding agent: {prompt_preview}")
|
format!(
|
||||||
|
"worker prompt landed in shell instead of coding agent: {prompt_preview}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
WorkerPromptTarget::WrongTarget => format!(
|
WorkerPromptTarget::WrongTarget => format!(
|
||||||
"worker prompt landed in the wrong target instead of {}: {}",
|
"worker prompt landed in the wrong target instead of {}: {}",
|
||||||
@@ -312,7 +314,9 @@ impl WorkerRegistry {
|
|||||||
worker.last_error = None;
|
worker.last_error = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if detect_ready_for_prompt(screen_text, &lowered) && worker.status != WorkerStatus::ReadyForPrompt {
|
if detect_ready_for_prompt(screen_text, &lowered)
|
||||||
|
&& worker.status != WorkerStatus::ReadyForPrompt
|
||||||
|
{
|
||||||
worker.status = WorkerStatus::ReadyForPrompt;
|
worker.status = WorkerStatus::ReadyForPrompt;
|
||||||
worker.prompt_in_flight = false;
|
worker.prompt_in_flight = false;
|
||||||
if matches!(
|
if matches!(
|
||||||
@@ -412,7 +416,10 @@ impl WorkerRegistry {
|
|||||||
worker_id: worker.worker_id.clone(),
|
worker_id: worker.worker_id.clone(),
|
||||||
status: worker.status,
|
status: worker.status,
|
||||||
ready: worker.status == WorkerStatus::ReadyForPrompt,
|
ready: worker.status == WorkerStatus::ReadyForPrompt,
|
||||||
blocked: matches!(worker.status, WorkerStatus::TrustRequired | WorkerStatus::Failed),
|
blocked: matches!(
|
||||||
|
worker.status,
|
||||||
|
WorkerStatus::TrustRequired | WorkerStatus::Failed
|
||||||
|
),
|
||||||
replay_prompt_ready: worker.replay_prompt.is_some(),
|
replay_prompt_ready: worker.replay_prompt.is_some(),
|
||||||
last_error: worker.last_error.clone(),
|
last_error: worker.last_error.clone(),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -67,9 +67,7 @@ pub(crate) fn detect_lane_completion(
|
|||||||
|
|
||||||
/// Evaluates policy actions for a completed lane.
|
/// Evaluates policy actions for a completed lane.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn evaluate_completed_lane(
|
pub(crate) fn evaluate_completed_lane(context: &LaneContext) -> Vec<PolicyAction> {
|
||||||
context: &LaneContext,
|
|
||||||
) -> Vec<PolicyAction> {
|
|
||||||
let engine = PolicyEngine::new(vec![
|
let engine = PolicyEngine::new(vec![
|
||||||
PolicyRule::new(
|
PolicyRule::new(
|
||||||
"closeout-completed-lane",
|
"closeout-completed-lane",
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ use runtime::{
|
|||||||
permission_enforcer::{EnforcementResult, PermissionEnforcer},
|
permission_enforcer::{EnforcementResult, PermissionEnforcer},
|
||||||
read_file,
|
read_file,
|
||||||
summary_compression::compress_summary_text,
|
summary_compression::compress_summary_text,
|
||||||
TaskPacket,
|
|
||||||
task_registry::TaskRegistry,
|
task_registry::TaskRegistry,
|
||||||
team_cron_registry::{CronRegistry, TeamRegistry},
|
team_cron_registry::{CronRegistry, TeamRegistry},
|
||||||
worker_boot::{WorkerReadySnapshot, WorkerRegistry},
|
worker_boot::{WorkerReadySnapshot, WorkerRegistry},
|
||||||
@@ -25,7 +24,7 @@ use runtime::{
|
|||||||
BranchFreshness, ContentBlock, ConversationMessage, ConversationRuntime, GrepSearchInput,
|
BranchFreshness, ContentBlock, ConversationMessage, ConversationRuntime, GrepSearchInput,
|
||||||
LaneEvent, LaneEventBlocker, LaneEventName, LaneEventStatus, LaneFailureClass,
|
LaneEvent, LaneEventBlocker, LaneEventName, LaneEventStatus, LaneFailureClass,
|
||||||
McpDegradedReport, MessageRole, PermissionMode, PermissionPolicy, PromptCacheEvent,
|
McpDegradedReport, MessageRole, PermissionMode, PermissionPolicy, PromptCacheEvent,
|
||||||
RuntimeError, Session, ToolError, ToolExecutor,
|
RuntimeError, Session, TaskPacket, ToolError, ToolExecutor,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
@@ -1878,27 +1877,25 @@ fn branch_divergence_output(
|
|||||||
dangerously_disable_sandbox: None,
|
dangerously_disable_sandbox: None,
|
||||||
return_code_interpretation: Some("preflight_blocked:branch_divergence".to_string()),
|
return_code_interpretation: Some("preflight_blocked:branch_divergence".to_string()),
|
||||||
no_output_expected: Some(false),
|
no_output_expected: Some(false),
|
||||||
structured_content: Some(vec![
|
structured_content: Some(vec![serde_json::to_value(
|
||||||
serde_json::to_value(
|
LaneEvent::new(
|
||||||
LaneEvent::new(
|
LaneEventName::BranchStaleAgainstMain,
|
||||||
LaneEventName::BranchStaleAgainstMain,
|
LaneEventStatus::Blocked,
|
||||||
LaneEventStatus::Blocked,
|
iso8601_now(),
|
||||||
iso8601_now(),
|
|
||||||
)
|
|
||||||
.with_failure_class(LaneFailureClass::BranchDivergence)
|
|
||||||
.with_detail(stderr.clone())
|
|
||||||
.with_data(json!({
|
|
||||||
"branch": branch,
|
|
||||||
"mainRef": main_ref,
|
|
||||||
"commitsBehind": commits_behind,
|
|
||||||
"commitsAhead": commits_ahead,
|
|
||||||
"missingCommits": missing_fixes,
|
|
||||||
"blockedCommand": command,
|
|
||||||
"recommendedAction": format!("merge or rebase {main_ref} before workspace tests")
|
|
||||||
})),
|
|
||||||
)
|
)
|
||||||
.expect("lane event should serialize"),
|
.with_failure_class(LaneFailureClass::BranchDivergence)
|
||||||
]),
|
.with_detail(stderr.clone())
|
||||||
|
.with_data(json!({
|
||||||
|
"branch": branch,
|
||||||
|
"mainRef": main_ref,
|
||||||
|
"commitsBehind": commits_behind,
|
||||||
|
"commitsAhead": commits_ahead,
|
||||||
|
"missingCommits": missing_fixes,
|
||||||
|
"blockedCommand": command,
|
||||||
|
"recommendedAction": format!("merge or rebase {main_ref} before workspace tests")
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.expect("lane event should serialize")]),
|
||||||
persisted_output_path: None,
|
persisted_output_path: None,
|
||||||
persisted_output_size: None,
|
persisted_output_size: None,
|
||||||
sandbox_status: None,
|
sandbox_status: None,
|
||||||
@@ -3297,12 +3294,12 @@ fn persist_agent_terminal_state(
|
|||||||
next_manifest.current_blocker = blocker.clone();
|
next_manifest.current_blocker = blocker.clone();
|
||||||
next_manifest.error = error;
|
next_manifest.error = error;
|
||||||
if let Some(blocker) = blocker {
|
if let Some(blocker) = blocker {
|
||||||
next_manifest.lane_events.push(
|
next_manifest
|
||||||
LaneEvent::blocked(iso8601_now(), &blocker),
|
.lane_events
|
||||||
);
|
.push(LaneEvent::blocked(iso8601_now(), &blocker));
|
||||||
next_manifest.lane_events.push(
|
next_manifest
|
||||||
LaneEvent::failed(iso8601_now(), &blocker),
|
.lane_events
|
||||||
);
|
.push(LaneEvent::failed(iso8601_now(), &blocker));
|
||||||
} else {
|
} else {
|
||||||
next_manifest.current_blocker = None;
|
next_manifest.current_blocker = None;
|
||||||
let compressed_detail = result
|
let compressed_detail = result
|
||||||
@@ -4952,8 +4949,8 @@ mod tests {
|
|||||||
agent_permission_policy, allowed_tools_for_subagent, classify_lane_failure,
|
agent_permission_policy, allowed_tools_for_subagent, classify_lane_failure,
|
||||||
execute_agent_with_spawn, execute_tool, final_assistant_text, mvp_tool_specs,
|
execute_agent_with_spawn, execute_tool, final_assistant_text, mvp_tool_specs,
|
||||||
permission_mode_from_plugin, persist_agent_terminal_state, push_output_block,
|
permission_mode_from_plugin, persist_agent_terminal_state, push_output_block,
|
||||||
run_task_packet, AgentInput, AgentJob, GlobalToolRegistry, LaneEventName,
|
run_task_packet, AgentInput, AgentJob, GlobalToolRegistry, LaneEventName, LaneFailureClass,
|
||||||
LaneFailureClass, SubagentToolExecutor,
|
SubagentToolExecutor,
|
||||||
};
|
};
|
||||||
use api::OutputContentBlock;
|
use api::OutputContentBlock;
|
||||||
use runtime::{
|
use runtime::{
|
||||||
@@ -5977,7 +5974,10 @@ mod tests {
|
|||||||
"gateway routing rejected the request",
|
"gateway routing rejected the request",
|
||||||
LaneFailureClass::GatewayRouting,
|
LaneFailureClass::GatewayRouting,
|
||||||
),
|
),
|
||||||
("tool failed: denied tool execution from hook", LaneFailureClass::ToolRuntime),
|
(
|
||||||
|
"tool failed: denied tool execution from hook",
|
||||||
|
LaneFailureClass::ToolRuntime,
|
||||||
|
),
|
||||||
("thread creation failed", LaneFailureClass::Infra),
|
("thread creation failed", LaneFailureClass::Infra),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -6000,11 +6000,17 @@ mod tests {
|
|||||||
(LaneEventName::MergeReady, "lane.merge.ready"),
|
(LaneEventName::MergeReady, "lane.merge.ready"),
|
||||||
(LaneEventName::Finished, "lane.finished"),
|
(LaneEventName::Finished, "lane.finished"),
|
||||||
(LaneEventName::Failed, "lane.failed"),
|
(LaneEventName::Failed, "lane.failed"),
|
||||||
(LaneEventName::BranchStaleAgainstMain, "branch.stale_against_main"),
|
(
|
||||||
|
LaneEventName::BranchStaleAgainstMain,
|
||||||
|
"branch.stale_against_main",
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (event, expected) in cases {
|
for (event, expected) in cases {
|
||||||
assert_eq!(serde_json::to_value(event).expect("serialize lane event"), json!(expected));
|
assert_eq!(
|
||||||
|
serde_json::to_value(event).expect("serialize lane event"),
|
||||||
|
json!(expected)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user