cargo fmt
This commit is contained in:
parent
cb1d3e72e4
commit
d2ee84775b
|
|
@ -3,8 +3,12 @@
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::llm_client::{
|
use crate::llm_client::{
|
||||||
ClientError, auth::AuthRequirement, capability::ModelCapability,
|
ClientError,
|
||||||
client::ConfigWarning, event::Event, scheme::Scheme,
|
auth::AuthRequirement,
|
||||||
|
capability::ModelCapability,
|
||||||
|
client::ConfigWarning,
|
||||||
|
event::Event,
|
||||||
|
scheme::Scheme,
|
||||||
types::{Request, RequestConfig},
|
types::{Request, RequestConfig},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,7 @@ pub struct ExtractPointerPayload {
|
||||||
|
|
||||||
/// `RestoredState.extensions` から最新の Phase 1 pointer を取り出す。
|
/// `RestoredState.extensions` から最新の Phase 1 pointer を取り出す。
|
||||||
/// 未抽出セッションでは `None`。
|
/// 未抽出セッションでは `None`。
|
||||||
pub fn fold_pointer(
|
pub fn fold_pointer(extensions: &[(String, serde_json::Value)]) -> Option<ExtractPointerPayload> {
|
||||||
extensions: &[(String, serde_json::Value)],
|
|
||||||
) -> Option<ExtractPointerPayload> {
|
|
||||||
extensions
|
extensions
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
|
|
@ -48,10 +46,7 @@ mod tests {
|
||||||
"staging_id": "old"
|
"staging_id": "old"
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
(
|
("other.domain".to_string(), serde_json::json!({ "x": 1 })),
|
||||||
"other.domain".to_string(),
|
|
||||||
serde_json::json!({ "x": 1 }),
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
EXTRACT_DOMAIN.to_string(),
|
EXTRACT_DOMAIN.to_string(),
|
||||||
serde_json::json!({
|
serde_json::json!({
|
||||||
|
|
@ -69,21 +64,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fold_returns_none_when_absent() {
|
fn fold_returns_none_when_absent() {
|
||||||
let exts = vec![(
|
let exts = vec![("other.domain".to_string(), serde_json::json!({ "x": 1 }))];
|
||||||
"other.domain".to_string(),
|
|
||||||
serde_json::json!({ "x": 1 }),
|
|
||||||
)];
|
|
||||||
assert!(fold_pointer(&exts).is_none());
|
assert!(fold_pointer(&exts).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fold_skips_malformed_entries() {
|
fn fold_skips_malformed_entries() {
|
||||||
let exts = vec![
|
let exts = vec![(
|
||||||
(
|
|
||||||
EXTRACT_DOMAIN.to_string(),
|
EXTRACT_DOMAIN.to_string(),
|
||||||
serde_json::json!({ "wrong_shape": true }),
|
serde_json::json!({ "wrong_shape": true }),
|
||||||
),
|
)];
|
||||||
];
|
|
||||||
// 現状は最新を取り出して JSON 不一致なら None。古いものに fallback
|
// 現状は最新を取り出して JSON 不一致なら None。古いものに fallback
|
||||||
// しないのは、壊れた最新を黙って無視すると意図しない再抽出を招くため。
|
// しないのは、壊れた最新を黙って無視すると意図しない再抽出を招くため。
|
||||||
assert!(fold_pointer(&exts).is_none());
|
assert!(fold_pointer(&exts).is_none());
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,12 @@ mod tests {
|
||||||
};
|
};
|
||||||
let (id, path) = write_staging(&layout, source.clone(), payload).unwrap();
|
let (id, path) = write_staging(&layout, source.clone(), payload).unwrap();
|
||||||
assert_eq!(path.parent().unwrap(), layout.staging_dir());
|
assert_eq!(path.parent().unwrap(), layout.staging_dir());
|
||||||
assert!(path.file_name().unwrap().to_string_lossy().contains(&id.to_string()));
|
assert!(
|
||||||
|
path.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_string_lossy()
|
||||||
|
.contains(&id.to_string())
|
||||||
|
);
|
||||||
|
|
||||||
let written: StagingRecord =
|
let written: StagingRecord =
|
||||||
serde_json::from_str(&fs::read_to_string(&path).unwrap()).unwrap();
|
serde_json::from_str(&fs::read_to_string(&path).unwrap()).unwrap();
|
||||||
|
|
@ -101,8 +106,7 @@ mod tests {
|
||||||
session_id: "sess".into(),
|
session_id: "sess".into(),
|
||||||
range: [0, 0],
|
range: [0, 0],
|
||||||
};
|
};
|
||||||
let (_, path) =
|
let (_, path) = write_staging(&layout, source, ExtractedPayload::default()).unwrap();
|
||||||
write_staging(&layout, source, ExtractedPayload::default()).unwrap();
|
|
||||||
let written: StagingRecord =
|
let written: StagingRecord =
|
||||||
serde_json::from_str(&fs::read_to_string(&path).unwrap()).unwrap();
|
serde_json::from_str(&fs::read_to_string(&path).unwrap()).unwrap();
|
||||||
assert!(written.payload.is_empty());
|
assert!(written.payload.is_empty());
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,8 @@ mod tests {
|
||||||
let ctx = Arc::new(ExtractWorkerContext::new());
|
let ctx = Arc::new(ExtractWorkerContext::new());
|
||||||
let tool: Arc<dyn Tool> = Arc::new(WriteExtractedTool { ctx: ctx.clone() });
|
let tool: Arc<dyn Tool> = Arc::new(WriteExtractedTool { ctx: ctx.clone() });
|
||||||
|
|
||||||
let first = serde_json::json!({"decisions": [], "discussions": [], "attempts": [], "requests": []})
|
let first =
|
||||||
|
serde_json::json!({"decisions": [], "discussions": [], "attempts": [], "requests": []})
|
||||||
.to_string();
|
.to_string();
|
||||||
tool.execute(&first).await.unwrap();
|
tool.execute(&first).await.unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -548,7 +548,8 @@ mod tests {
|
||||||
// `db-pol` (1 deletion), `db-pools` (1 insertion).
|
// `db-pol` (1 deletion), `db-pools` (1 insertion).
|
||||||
for slug in ["db-pol", "db-pools"] {
|
for slug in ["db-pol", "db-pools"] {
|
||||||
write(
|
write(
|
||||||
&dir.path().join(format!(".insomnia/memory/decisions/{slug}.md")),
|
&dir.path()
|
||||||
|
.join(format!(".insomnia/memory/decisions/{slug}.md")),
|
||||||
&format!(
|
&format!(
|
||||||
"---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n",
|
"---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n",
|
||||||
n = iso_now()
|
n = iso_now()
|
||||||
|
|
@ -577,7 +578,8 @@ mod tests {
|
||||||
let (dir, linter) = workspace();
|
let (dir, linter) = workspace();
|
||||||
for slug in ["alpha", "bravo"] {
|
for slug in ["alpha", "bravo"] {
|
||||||
write(
|
write(
|
||||||
&dir.path().join(format!(".insomnia/memory/decisions/{slug}.md")),
|
&dir.path()
|
||||||
|
.join(format!(".insomnia/memory/decisions/{slug}.md")),
|
||||||
&format!(
|
&format!(
|
||||||
"---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n",
|
"---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n",
|
||||||
n = iso_now()
|
n = iso_now()
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,11 @@ mod tests {
|
||||||
fn non_md_files_ignored() {
|
fn non_md_files_ignored() {
|
||||||
let (dir, layout) = setup();
|
let (dir, layout) = setup();
|
||||||
write_knowledge(dir.path(), "good", "ok", true, "");
|
write_knowledge(dir.path(), "good", "ok", true, "");
|
||||||
std::fs::write(dir.path().join(".insomnia/knowledge/note.txt"), "not markdown\n").unwrap();
|
std::fs::write(
|
||||||
|
dir.path().join(".insomnia/knowledge/note.txt"),
|
||||||
|
"not markdown\n",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let got = collect_resident_knowledge(&layout);
|
let got = collect_resident_knowledge(&layout);
|
||||||
assert_eq!(got.len(), 1);
|
assert_eq!(got.len(), 1);
|
||||||
|
|
|
||||||
|
|
@ -450,7 +450,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_decision(dir: &Path, slug: &str, body: &str) {
|
fn write_decision(dir: &Path, slug: &str, body: &str) {
|
||||||
let path = dir.join(".insomnia/memory/decisions").join(format!("{slug}.md"));
|
let path = dir
|
||||||
|
.join(".insomnia/memory/decisions")
|
||||||
|
.join(format!("{slug}.md"));
|
||||||
let content = format!(
|
let content = format!(
|
||||||
"---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n{body}",
|
"---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n{body}",
|
||||||
n = now()
|
n = now()
|
||||||
|
|
@ -501,12 +503,14 @@ mod tests {
|
||||||
assert_eq!(records.len(), 1);
|
assert_eq!(records.len(), 1);
|
||||||
assert_eq!(records[0].slug, "alpha");
|
assert_eq!(records[0].slug, "alpha");
|
||||||
assert_eq!(records[0].kind, "decision");
|
assert_eq!(records[0].kind, "decision");
|
||||||
assert!(records[0]
|
assert!(
|
||||||
|
records[0]
|
||||||
.excerpt
|
.excerpt
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
.contains("ollama"));
|
.contains("ollama")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -634,12 +638,14 @@ mod tests {
|
||||||
assert_eq!(records[0].kind.as_deref(), Some("policy"));
|
assert_eq!(records[0].kind.as_deref(), Some("policy"));
|
||||||
assert_eq!(records[0].description.as_deref(), Some("the policy doc"));
|
assert_eq!(records[0].description.as_deref(), Some("the policy doc"));
|
||||||
assert_eq!(records[0].model_invokation, Some(false));
|
assert_eq!(records[0].model_invokation, Some(false));
|
||||||
assert!(records[0]
|
assert!(
|
||||||
|
records[0]
|
||||||
.excerpt
|
.excerpt
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
.contains("ollama"));
|
.contains("ollama")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
|
||||||
|
|
@ -150,12 +150,13 @@ pub fn lookup_session(session_id: SessionId) -> Result<Option<SessionLockInfo>,
|
||||||
let lock_path = default_registry_path()?;
|
let lock_path = default_registry_path()?;
|
||||||
let mut guard = LockFileGuard::open(&lock_path)?;
|
let mut guard = LockFileGuard::open(&lock_path)?;
|
||||||
crate::mutate::reclaim_stale(&mut guard);
|
crate::mutate::reclaim_stale(&mut guard);
|
||||||
Ok(guard.data().find_by_session(session_id).map(|a| {
|
Ok(guard
|
||||||
SessionLockInfo {
|
.data()
|
||||||
|
.find_by_session(session_id)
|
||||||
|
.map(|a| SessionLockInfo {
|
||||||
pod_name: a.pod_name.clone(),
|
pod_name: a.pod_name.clone(),
|
||||||
socket: a.socket.clone(),
|
socket: a.socket.clone(),
|
||||||
pid: a.pid,
|
pid: a.pid,
|
||||||
}
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -249,10 +249,7 @@ mod tests {
|
||||||
assert!(g.data().find_by_session(target_session).is_none());
|
assert!(g.data().find_by_session(target_session).is_none());
|
||||||
|
|
||||||
// After adopt-style rewrite, the same allocation is now found.
|
// After adopt-style rewrite, the same allocation is now found.
|
||||||
g.data_mut()
|
g.data_mut().find_mut("child").unwrap().session_id = Some(target_session);
|
||||||
.find_mut("child")
|
|
||||||
.unwrap()
|
|
||||||
.session_id = Some(target_session);
|
|
||||||
let found = g.data().find_by_session(target_session).unwrap();
|
let found = g.data().find_by_session(target_session).unwrap();
|
||||||
assert_eq!(found.pod_name, "child");
|
assert_eq!(found.pod_name, "child");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,22 +12,22 @@ use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use llm_worker::Item;
|
use llm_worker::Item;
|
||||||
|
use llm_worker::UsageRecord;
|
||||||
use llm_worker::interceptor::{
|
use llm_worker::interceptor::{
|
||||||
Interceptor, PostToolAction, PreRequestAction, PreToolAction, PromptAction, ToolCallInfo,
|
Interceptor, PostToolAction, PreRequestAction, PreToolAction, PromptAction, ToolCallInfo,
|
||||||
ToolResultInfo, TurnEndAction,
|
ToolResultInfo, TurnEndAction,
|
||||||
};
|
};
|
||||||
use llm_worker::UsageRecord;
|
|
||||||
use llm_worker::tool::ToolOutput;
|
use llm_worker::tool::ToolOutput;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::compact::state::CompactState;
|
use crate::compact::state::CompactState;
|
||||||
use llm_worker::token_counter::total_tokens;
|
|
||||||
use crate::hook::{
|
use crate::hook::{
|
||||||
AbortInfo, HookRegistry, PreRequestInfo, PromptSubmitInfo, ToolCallSummary, ToolResultSummary,
|
AbortInfo, HookRegistry, PreRequestInfo, PromptSubmitInfo, ToolCallSummary, ToolResultSummary,
|
||||||
TurnEndInfo,
|
TurnEndInfo,
|
||||||
};
|
};
|
||||||
use crate::ipc::notify_buffer::{NotifyBuffer, format_notify};
|
use crate::ipc::notify_buffer::{NotifyBuffer, format_notify};
|
||||||
use crate::prompt::catalog::PromptCatalog;
|
use crate::prompt::catalog::PromptCatalog;
|
||||||
|
use llm_worker::token_counter::total_tokens;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
/// Maximum number of bytes copied into `TurnEndInfo::final_text_preview`.
|
/// Maximum number of bytes copied into `TurnEndInfo::final_text_preview`.
|
||||||
|
|
|
||||||
|
|
@ -1207,10 +1207,7 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
|
||||||
// segments; only the user_messages surviving in retained_items
|
// segments; only the user_messages surviving in retained_items
|
||||||
// keep them. They are always the trailing K entries of
|
// keep them. They are always the trailing K entries of
|
||||||
// `self.user_segments` because submissions are appended in order.
|
// `self.user_segments` because submissions are appended in order.
|
||||||
let drop_n = self
|
let drop_n = self.user_segments.len().saturating_sub(retained_user_msgs);
|
||||||
.user_segments
|
|
||||||
.len()
|
|
||||||
.saturating_sub(retained_user_msgs);
|
|
||||||
if drop_n > 0 {
|
if drop_n > 0 {
|
||||||
self.user_segments.drain(..drop_n);
|
self.user_segments.drain(..drop_n);
|
||||||
}
|
}
|
||||||
|
|
@ -1371,7 +1368,12 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
|
||||||
return Ok(ExtractDecision::Skipped);
|
return Ok(ExtractDecision::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let current_history_len = self.worker.as_ref().expect("worker present").history().len();
|
let current_history_len = self
|
||||||
|
.worker
|
||||||
|
.as_ref()
|
||||||
|
.expect("worker present")
|
||||||
|
.history()
|
||||||
|
.len();
|
||||||
if current_history_len <= processed_history_len {
|
if current_history_len <= processed_history_len {
|
||||||
return Ok(ExtractDecision::Skipped);
|
return Ok(ExtractDecision::Skipped);
|
||||||
}
|
}
|
||||||
|
|
@ -1392,11 +1394,8 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
|
||||||
return Ok(ExtractDecision::Skipped);
|
return Ok(ExtractDecision::Skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
let items_to_extract = self
|
let items_to_extract = self.worker.as_ref().expect("worker present").history()
|
||||||
.worker
|
[processed_history_len..current_history_len]
|
||||||
.as_ref()
|
|
||||||
.expect("worker present")
|
|
||||||
.history()[processed_history_len..current_history_len]
|
|
||||||
.to_vec();
|
.to_vec();
|
||||||
|
|
||||||
let layout = memory::WorkspaceLayout::resolve(memory_cfg, &self.pwd);
|
let layout = memory::WorkspaceLayout::resolve(memory_cfg, &self.pwd);
|
||||||
|
|
@ -1428,7 +1427,10 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
|
||||||
extract_worker.register_tool(extract::write_extracted_tool(ctx.clone()));
|
extract_worker.register_tool(extract::write_extracted_tool(ctx.clone()));
|
||||||
|
|
||||||
let input_text = extract::build_extract_input(&items_to_extract);
|
let input_text = extract::build_extract_input(&items_to_extract);
|
||||||
extract_worker.run(input_text).await.map_err(PodError::Worker)?;
|
extract_worker
|
||||||
|
.run(input_text)
|
||||||
|
.await
|
||||||
|
.map_err(PodError::Worker)?;
|
||||||
|
|
||||||
let payload = ctx.take_payload().unwrap_or_else(|| {
|
let payload = ctx.take_payload().unwrap_or_else(|| {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
|
|
@ -1602,8 +1604,11 @@ impl<St: Store> Pod<Box<dyn LlmClient>, St> {
|
||||||
let common = prepare_pod_common(&manifest, &loader, /* parse_template */ true)?;
|
let common = prepare_pod_common(&manifest, &loader, /* parse_template */ true)?;
|
||||||
|
|
||||||
let session_id = session_store::new_session_id();
|
let session_id = session_store::new_session_id();
|
||||||
let scope_allocation =
|
let scope_allocation = pod_registry::adopt_allocation(
|
||||||
pod_registry::adopt_allocation(manifest.pod.name.clone(), std::process::id(), session_id)?;
|
manifest.pod.name.clone(),
|
||||||
|
std::process::id(),
|
||||||
|
session_id,
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut worker = Worker::new(common.client);
|
let mut worker = Worker::new(common.client);
|
||||||
apply_worker_manifest(&mut worker, &manifest.worker);
|
apply_worker_manifest(&mut worker, &manifest.worker);
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,8 @@ async fn restore_from_manifest_rejects_unknown_session() {
|
||||||
// NotFound, which `Pod::restore_from_manifest` surfaces verbatim
|
// NotFound, which `Pod::restore_from_manifest` surfaces verbatim
|
||||||
// as `PodError::Store`.
|
// as `PodError::Store`.
|
||||||
let unknown = session_store::new_session_id();
|
let unknown = session_store::new_session_id();
|
||||||
let result = Pod::restore_from_manifest(
|
let result =
|
||||||
unknown,
|
Pod::restore_from_manifest(unknown, manifest, store, pod::PromptLoader::builtins_only())
|
||||||
manifest,
|
|
||||||
store,
|
|
||||||
pod::PromptLoader::builtins_only(),
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
|
|
||||||
|
|
@ -35,14 +35,14 @@ pub mod store;
|
||||||
|
|
||||||
pub use event_trace::TraceEntry;
|
pub use event_trace::TraceEntry;
|
||||||
pub use fs_store::FsStore;
|
pub use fs_store::FsStore;
|
||||||
|
pub use llm_worker::UsageRecord;
|
||||||
|
pub use llm_worker::llm_client::types::{ContentPart, Item, Role};
|
||||||
pub use logged_item::{LoggedContentPart, LoggedItem, LoggedRole, from_logged, to_logged};
|
pub use logged_item::{LoggedContentPart, LoggedItem, LoggedRole, from_logged, to_logged};
|
||||||
pub use session::{
|
pub use session::{
|
||||||
SessionStartState, create_compacted_session, create_session, create_session_with_id,
|
SessionStartState, create_compacted_session, create_session, create_session_with_id,
|
||||||
ensure_head_or_fork, fork, fork_at, restore, save_config_changed, save_delta, save_extension,
|
ensure_head_or_fork, fork, fork_at, restore, save_config_changed, save_delta, save_extension,
|
||||||
save_run_completed, save_run_errored, save_turn_end, save_usage, save_user_input,
|
save_run_completed, save_run_errored, save_turn_end, save_usage, save_user_input,
|
||||||
};
|
};
|
||||||
pub use llm_worker::UsageRecord;
|
|
||||||
pub use llm_worker::llm_client::types::{ContentPart, Item, Role};
|
|
||||||
pub use session_log::{
|
pub use session_log::{
|
||||||
EntryHash, HashedEntry, LogEntry, RestoredState, SessionOrigin, build_chain, collect_state,
|
EntryHash, HashedEntry, LogEntry, RestoredState, SessionOrigin, build_chain, collect_state,
|
||||||
compute_hash,
|
compute_hash,
|
||||||
|
|
|
||||||
|
|
@ -257,19 +257,13 @@ pub fn collect_state(entries: &[HashedEntry]) -> RestoredState {
|
||||||
state.user_segments.push(segments.clone());
|
state.user_segments.push(segments.clone());
|
||||||
}
|
}
|
||||||
LogEntry::AssistantItems { items, .. } => {
|
LogEntry::AssistantItems { items, .. } => {
|
||||||
state
|
state.history.extend(items.iter().cloned().map(Item::from));
|
||||||
.history
|
|
||||||
.extend(items.iter().cloned().map(Item::from));
|
|
||||||
}
|
}
|
||||||
LogEntry::ToolResults { items, .. } => {
|
LogEntry::ToolResults { items, .. } => {
|
||||||
state
|
state.history.extend(items.iter().cloned().map(Item::from));
|
||||||
.history
|
|
||||||
.extend(items.iter().cloned().map(Item::from));
|
|
||||||
}
|
}
|
||||||
LogEntry::HookInjectedItems { items, .. } => {
|
LogEntry::HookInjectedItems { items, .. } => {
|
||||||
state
|
state.history.extend(items.iter().cloned().map(Item::from));
|
||||||
.history
|
|
||||||
.extend(items.iter().cloned().map(Item::from));
|
|
||||||
}
|
}
|
||||||
LogEntry::TurnEnd { turn_count, .. } => {
|
LogEntry::TurnEnd { turn_count, .. } => {
|
||||||
state.turn_count = *turn_count;
|
state.turn_count = *turn_count;
|
||||||
|
|
@ -419,9 +413,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
LogEntry::AssistantItems {
|
LogEntry::AssistantItems {
|
||||||
ts: 3000,
|
ts: 3000,
|
||||||
items: vec![
|
items: vec![Item::tool_call("call_1", "get_weather", r#"{"city":"Tokyo"}"#).into()],
|
||||||
Item::tool_call("call_1", "get_weather", r#"{"city":"Tokyo"}"#).into(),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
LogEntry::ToolResults {
|
LogEntry::ToolResults {
|
||||||
ts: 3500,
|
ts: 3500,
|
||||||
|
|
@ -721,10 +713,7 @@ mod tests {
|
||||||
assert_eq!(content.len(), 1);
|
assert_eq!(content.len(), 1);
|
||||||
match &content[0] {
|
match &content[0] {
|
||||||
llm_worker::ContentPart::Text { text } => {
|
llm_worker::ContentPart::Text { text } => {
|
||||||
assert_eq!(
|
assert_eq!(text, "see line1\nline2[unresolved file ref: src/main.rs]");
|
||||||
text,
|
|
||||||
"see line1\nline2[unresolved file ref: src/main.rs]"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
other => panic!("unexpected content: {other:?}"),
|
other => panic!("unexpected content: {other:?}"),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -460,7 +460,9 @@ impl App {
|
||||||
// single text segment.
|
// single text segment.
|
||||||
let segments = item
|
let segments = item
|
||||||
.get("segments")
|
.get("segments")
|
||||||
.and_then(|v| serde_json::from_value::<Vec<Segment>>(v.clone()).ok())
|
.and_then(|v| {
|
||||||
|
serde_json::from_value::<Vec<Segment>>(v.clone()).ok()
|
||||||
|
})
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
|
|
|
||||||
|
|
@ -71,9 +71,7 @@ fn char_class(c: char) -> AtomClass {
|
||||||
let cp = c as u32;
|
let cp = c as u32;
|
||||||
match cp {
|
match cp {
|
||||||
0x3040..=0x309F => AtomClass::Word(WordKind::Hiragana),
|
0x3040..=0x309F => AtomClass::Word(WordKind::Hiragana),
|
||||||
0x30A0..=0x30FF | 0x31F0..=0x31FF | 0xFF65..=0xFF9F => {
|
0x30A0..=0x30FF | 0x31F0..=0x31FF | 0xFF65..=0xFF9F => AtomClass::Word(WordKind::Katakana),
|
||||||
AtomClass::Word(WordKind::Katakana)
|
|
||||||
}
|
|
||||||
0x3400..=0x4DBF | 0x4E00..=0x9FFF | 0xF900..=0xFAFF | 0x20000..=0x2FFFF => {
|
0x3400..=0x4DBF | 0x4E00..=0x9FFF | 0xF900..=0xFAFF | 0x20000..=0x2FFFF => {
|
||||||
AtomClass::Word(WordKind::Han)
|
AtomClass::Word(WordKind::Han)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ use std::io;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crossterm::event::{self, Event as TermEvent, KeyCode, KeyEventKind, KeyModifiers};
|
use crossterm::event::{self, Event as TermEvent, KeyCode, KeyEventKind, KeyModifiers};
|
||||||
|
use pod_registry::lookup_session;
|
||||||
use ratatui::Terminal;
|
use ratatui::Terminal;
|
||||||
use ratatui::backend::CrosstermBackend;
|
use ratatui::backend::CrosstermBackend;
|
||||||
use ratatui::layout::{Constraint, Layout};
|
use ratatui::layout::{Constraint, Layout};
|
||||||
|
|
@ -19,7 +20,6 @@ use ratatui::style::{Color, Modifier, Style};
|
||||||
use ratatui::text::{Line, Span};
|
use ratatui::text::{Line, Span};
|
||||||
use ratatui::widgets::Paragraph;
|
use ratatui::widgets::Paragraph;
|
||||||
use ratatui::{Frame, TerminalOptions, Viewport};
|
use ratatui::{Frame, TerminalOptions, Viewport};
|
||||||
use pod_registry::lookup_session;
|
|
||||||
use session_store::{
|
use session_store::{
|
||||||
FsStore, HashedEntry, LogEntry, LoggedContentPart, LoggedItem, SessionId, Store,
|
FsStore, HashedEntry, LogEntry, LoggedContentPart, LoggedItem, SessionId, Store,
|
||||||
};
|
};
|
||||||
|
|
@ -138,9 +138,7 @@ pub async fn run() -> Result<PickerOutcome, PickerError> {
|
||||||
/// scrolls the terminal up exactly one row, so the next inline
|
/// scrolls the terminal up exactly one row, so the next inline
|
||||||
/// viewport opens immediately below the picker rather than on top of
|
/// viewport opens immediately below the picker rather than on top of
|
||||||
/// it.
|
/// it.
|
||||||
fn close_viewport(
|
fn close_viewport(terminal: &mut Terminal<CrosstermBackend<io::Stdout>>) -> io::Result<()> {
|
||||||
terminal: &mut Terminal<CrosstermBackend<io::Stdout>>,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
let area = terminal.get_frame().area();
|
let area = terminal.get_frame().area();
|
||||||
let last_row = area.bottom().saturating_sub(1);
|
let last_row = area.bottom().saturating_sub(1);
|
||||||
terminal.set_cursor_position((0, last_row))?;
|
terminal.set_cursor_position((0, last_row))?;
|
||||||
|
|
@ -253,8 +251,7 @@ fn poll_event() -> io::Result<Option<Action>> {
|
||||||
|
|
||||||
fn draw(f: &mut Frame<'_>, rows: &[Row], selected: usize) {
|
fn draw(f: &mut Frame<'_>, rows: &[Row], selected: usize) {
|
||||||
let area = f.area();
|
let area = f.area();
|
||||||
let mut constraints: Vec<Constraint> =
|
let mut constraints: Vec<Constraint> = Vec::with_capacity(rows.len() + 3);
|
||||||
Vec::with_capacity(rows.len() + 3);
|
|
||||||
constraints.push(Constraint::Length(1)); // title
|
constraints.push(Constraint::Length(1)); // title
|
||||||
for _ in rows {
|
for _ in rows {
|
||||||
constraints.push(Constraint::Length(1));
|
constraints.push(Constraint::Length(1));
|
||||||
|
|
@ -272,10 +269,7 @@ fn draw(f: &mut Frame<'_>, rows: &[Row], selected: usize) {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (i, row) in rows.iter().enumerate() {
|
for (i, row) in rows.iter().enumerate() {
|
||||||
f.render_widget(
|
f.render_widget(Paragraph::new(row_line(row, i == selected)), layout[i + 1]);
|
||||||
Paragraph::new(row_line(row, i == selected)),
|
|
||||||
layout[i + 1],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
|
|
@ -325,4 +319,3 @@ fn short_session(id: SessionId) -> String {
|
||||||
let s = id.to_string();
|
let s = id.to_string();
|
||||||
s.chars().take(8).collect()
|
s.chars().take(8).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,13 @@ use std::time::Duration;
|
||||||
use crossterm::event::{self, Event as TermEvent, KeyCode, KeyEventKind, KeyModifiers};
|
use crossterm::event::{self, Event as TermEvent, KeyCode, KeyEventKind, KeyModifiers};
|
||||||
use manifest::{PodManifestConfig, find_project_manifest_from, load_layer, user_manifest_path};
|
use manifest::{PodManifestConfig, find_project_manifest_from, load_layer, user_manifest_path};
|
||||||
use ratatui::Terminal;
|
use ratatui::Terminal;
|
||||||
use session_store::SessionId;
|
|
||||||
use ratatui::backend::CrosstermBackend;
|
use ratatui::backend::CrosstermBackend;
|
||||||
use ratatui::layout::{Constraint, Layout};
|
use ratatui::layout::{Constraint, Layout};
|
||||||
use ratatui::style::{Color, Modifier, Style};
|
use ratatui::style::{Color, Modifier, Style};
|
||||||
use ratatui::text::{Line, Span};
|
use ratatui::text::{Line, Span};
|
||||||
use ratatui::widgets::Paragraph;
|
use ratatui::widgets::Paragraph;
|
||||||
use ratatui::{Frame, TerminalOptions, Viewport};
|
use ratatui::{Frame, TerminalOptions, Viewport};
|
||||||
|
use session_store::SessionId;
|
||||||
use tokio::io::{AsyncBufReadExt, BufReader};
|
use tokio::io::{AsyncBufReadExt, BufReader};
|
||||||
use tokio::process::{Child, Command};
|
use tokio::process::{Child, Command};
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user