mirror of
https://github.com/instructkr/claw-code.git
synced 2026-05-18 13:31:28 +08:00
omx(team): merge worker-1
This commit is contained in:
@@ -221,9 +221,9 @@ const SLASH_COMMAND_SPECS: &[SlashCommandSpec] = &[
|
|||||||
SlashCommandSpec {
|
SlashCommandSpec {
|
||||||
name: "session",
|
name: "session",
|
||||||
aliases: &[],
|
aliases: &[],
|
||||||
summary: "List, switch, fork, or delete managed local sessions",
|
summary: "List, check, switch, fork, or delete managed local sessions",
|
||||||
argument_hint: Some(
|
argument_hint: Some(
|
||||||
"[list|switch <session-id>|fork [branch-name]|delete <session-id> [--force]]",
|
"[list|exists <session-id>|switch <session-id>|fork [branch-name]|delete <session-id> [--force]]",
|
||||||
),
|
),
|
||||||
resume_supported: false,
|
resume_supported: false,
|
||||||
},
|
},
|
||||||
@@ -1590,7 +1590,17 @@ fn parse_session_command(args: &[&str]) -> Result<SlashCommand, SlashCommandPars
|
|||||||
action: Some("list".to_string()),
|
action: Some("list".to_string()),
|
||||||
target: None,
|
target: None,
|
||||||
}),
|
}),
|
||||||
["list", ..] => Err(usage_error("session", "[list|switch <session-id>|fork [branch-name]|delete <session-id> [--force]]")),
|
["list", ..] => Err(usage_error("session", "[list|exists <session-id>|switch <session-id>|fork [branch-name]|delete <session-id> [--force]]")),
|
||||||
|
["exists"] => Err(usage_error("session exists", "<session-id>")),
|
||||||
|
["exists", target] => Ok(SlashCommand::Session {
|
||||||
|
action: Some("exists".to_string()),
|
||||||
|
target: Some((*target).to_string()),
|
||||||
|
}),
|
||||||
|
["exists", ..] => Err(command_error(
|
||||||
|
"Unexpected arguments for /session exists.",
|
||||||
|
"session",
|
||||||
|
"/session exists <session-id>",
|
||||||
|
)),
|
||||||
["switch"] => Err(usage_error("session switch", "<session-id>")),
|
["switch"] => Err(usage_error("session switch", "<session-id>")),
|
||||||
["switch", target] => Ok(SlashCommand::Session {
|
["switch", target] => Ok(SlashCommand::Session {
|
||||||
action: Some("switch".to_string()),
|
action: Some("switch".to_string()),
|
||||||
@@ -1637,10 +1647,10 @@ fn parse_session_command(args: &[&str]) -> Result<SlashCommand, SlashCommandPars
|
|||||||
)),
|
)),
|
||||||
[action, ..] => Err(command_error(
|
[action, ..] => Err(command_error(
|
||||||
&format!(
|
&format!(
|
||||||
"Unknown /session action '{action}'. Use list, switch <session-id>, fork [branch-name], or delete <session-id> [--force]."
|
"Unknown /session action '{action}'. Use list, exists <session-id>, switch <session-id>, fork [branch-name], or delete <session-id> [--force]."
|
||||||
),
|
),
|
||||||
"session",
|
"session",
|
||||||
"/session [list|switch <session-id>|fork [branch-name]|delete <session-id> [--force]]",
|
"/session [list|exists <session-id>|switch <session-id>|fork [branch-name]|delete <session-id> [--force]]",
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4585,6 +4595,13 @@ mod tests {
|
|||||||
path: Some("notes.txt".to_string())
|
path: Some("notes.txt".to_string())
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
SlashCommand::parse("/session exists abc123"),
|
||||||
|
Ok(Some(SlashCommand::Session {
|
||||||
|
action: Some("exists".to_string()),
|
||||||
|
target: Some("abc123".to_string())
|
||||||
|
}))
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
SlashCommand::parse("/session switch abc123"),
|
SlashCommand::parse("/session switch abc123"),
|
||||||
Ok(Some(SlashCommand::Session {
|
Ok(Some(SlashCommand::Session {
|
||||||
|
|||||||
@@ -163,6 +163,16 @@ impl SessionStore {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn session_exists(&self, reference: &str) -> bool {
|
||||||
|
self.resolve_reference(reference).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_session(&self, reference: &str) -> Result<SessionHandle, SessionControlError> {
|
||||||
|
let handle = self.resolve_reference(reference)?;
|
||||||
|
fs::remove_file(&handle.path)?;
|
||||||
|
Ok(handle)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load_session(
|
pub fn load_session(
|
||||||
&self,
|
&self,
|
||||||
reference: &str,
|
reference: &str,
|
||||||
@@ -480,6 +490,30 @@ pub fn load_managed_session(reference: &str) -> Result<LoadedManagedSession, Ses
|
|||||||
load_managed_session_for(env::current_dir()?, reference)
|
load_managed_session_for(env::current_dir()?, reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn managed_session_exists(reference: &str) -> Result<bool, SessionControlError> {
|
||||||
|
managed_session_exists_for(env::current_dir()?, reference)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn managed_session_exists_for(
|
||||||
|
base_dir: impl AsRef<Path>,
|
||||||
|
reference: &str,
|
||||||
|
) -> Result<bool, SessionControlError> {
|
||||||
|
let store = SessionStore::from_cwd(base_dir)?;
|
||||||
|
Ok(store.session_exists(reference))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_managed_session(reference: &str) -> Result<SessionHandle, SessionControlError> {
|
||||||
|
delete_managed_session_for(env::current_dir()?, reference)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_managed_session_for(
|
||||||
|
base_dir: impl AsRef<Path>,
|
||||||
|
reference: &str,
|
||||||
|
) -> Result<SessionHandle, SessionControlError> {
|
||||||
|
let store = SessionStore::from_cwd(base_dir)?;
|
||||||
|
store.delete_session(reference)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load_managed_session_for(
|
pub fn load_managed_session_for(
|
||||||
base_dir: impl AsRef<Path>,
|
base_dir: impl AsRef<Path>,
|
||||||
reference: &str,
|
reference: &str,
|
||||||
@@ -569,9 +603,10 @@ fn path_is_within_workspace(path: &Path, workspace_root: &Path) -> bool {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{
|
use super::{
|
||||||
create_managed_session_handle_for, fork_managed_session_for, is_session_reference_alias,
|
create_managed_session_handle_for, delete_managed_session_for, fork_managed_session_for,
|
||||||
list_managed_sessions_for, load_managed_session_for, resolve_session_reference_for,
|
is_session_reference_alias, list_managed_sessions_for, load_managed_session_for,
|
||||||
workspace_fingerprint, ManagedSessionSummary, SessionControlError, SessionStore,
|
managed_session_exists_for, resolve_session_reference_for, workspace_fingerprint,
|
||||||
|
ManagedSessionSummary, SessionControlError, SessionStore,
|
||||||
LATEST_SESSION_REFERENCE,
|
LATEST_SESSION_REFERENCE,
|
||||||
};
|
};
|
||||||
use crate::session::Session;
|
use crate::session::Session;
|
||||||
@@ -996,6 +1031,33 @@ mod tests {
|
|||||||
fs::remove_dir_all(base).expect("temp dir should clean up");
|
fs::remove_dir_all(base).expect("temp dir should clean up");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn session_exists_and_delete_are_scoped_to_workspace_store() {
|
||||||
|
// given
|
||||||
|
let base = temp_dir();
|
||||||
|
fs::create_dir_all(&base).expect("base dir should exist");
|
||||||
|
let store = SessionStore::from_cwd(&base).expect("store should build");
|
||||||
|
let session = persist_session_via_store(&store, "delete me");
|
||||||
|
|
||||||
|
// when
|
||||||
|
assert!(
|
||||||
|
managed_session_exists_for(&base, &session.session_id).expect("exists should run"),
|
||||||
|
"persisted session should exist before deletion"
|
||||||
|
);
|
||||||
|
let deleted =
|
||||||
|
delete_managed_session_for(&base, &session.session_id).expect("delete should succeed");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(deleted.id, session.session_id);
|
||||||
|
assert!(!deleted.path.exists(), "session file should be removed");
|
||||||
|
assert!(
|
||||||
|
!managed_session_exists_for(&base, &session.session_id).expect("exists should run"),
|
||||||
|
"deleted session should not exist"
|
||||||
|
);
|
||||||
|
fs::remove_dir_all(base).expect("temp dir should clean up");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn session_store_fork_stays_in_same_namespace() {
|
fn session_store_fork_stays_in_same_namespace() {
|
||||||
// given
|
// given
|
||||||
|
|||||||
Reference in New Issue
Block a user