|
1 | | -use std::fs; |
2 | 1 | use std::path::{Component, Path, PathBuf}; |
3 | 2 |
|
4 | 3 | use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; |
5 | | -use tree_ring_memory_core::{now_iso, ConsolidationRequest, MemoryEvent, SensitivityGuard}; |
| 4 | +use tree_ring_memory_core::{now_iso, ConsolidationRequest, MemoryEvent}; |
6 | 5 | use tree_ring_memory_sqlite::{MemoryRetriever, RecallResult, SQLiteMemoryStore}; |
7 | 6 |
|
8 | 7 | use crate::integrations::{scan_integrations, IntegrationScanReport}; |
| 8 | +use crate::actions::export_import::{export_jsonl, ExportActionRequest}; |
| 9 | +use crate::actions::remember::{remember, RememberRequest}; |
9 | 10 |
|
10 | 11 | use super::actions::{ActionKind, PendingAction}; |
11 | 12 | use super::input::{parse_slash_command, SlashCommand}; |
@@ -271,21 +272,18 @@ impl App { |
271 | 272 | self.status = "remember requires a summary".to_string(); |
272 | 273 | return Ok(()); |
273 | 274 | } |
274 | | - let mut event = |
275 | | - MemoryEvent::new(summary.trim(), "lesson").map_err(|err| err.to_string())?; |
276 | | - event.ring = "cambium".to_string(); |
277 | | - event.source.source_type = "manual".to_string(); |
278 | | - let guard = SensitivityGuard::default(); |
279 | | - let detected = guard |
280 | | - .detect_memory_event_sensitivity(&event) |
281 | | - .map_err(|err| err.to_string())?; |
282 | | - if detected != "normal" { |
283 | | - event.sensitivity = detected; |
284 | | - } |
285 | | - event.validate().map_err(|err| err.to_string())?; |
286 | | - let id = event.id.clone(); |
287 | | - self.store.put(&event).map_err(|err| err.to_string())?; |
288 | | - self.status = format!("remembered {id}"); |
| 275 | + let report = remember( |
| 276 | + &mut self.store, |
| 277 | + RememberRequest { |
| 278 | + summary: summary.trim().to_string(), |
| 279 | + event_type: "lesson".to_string(), |
| 280 | + ring: "cambium".to_string(), |
| 281 | + scope: "project".to_string(), |
| 282 | + project: None, |
| 283 | + tags: Vec::new(), |
| 284 | + }, |
| 285 | + )?; |
| 286 | + self.status = format!("remembered {}", report.memory.id); |
289 | 287 | self.refresh_store() |
290 | 288 | } |
291 | 289 |
|
@@ -371,19 +369,17 @@ impl App { |
371 | 369 | if output.exists() { |
372 | 370 | self.status = format!("export refused existing file {}", output.display()); |
373 | 371 | } else { |
374 | | - let (jsonl, report) = self |
375 | | - .store |
376 | | - .export_jsonl(include_sensitive, include_superseded) |
377 | | - .map_err(|err| err.to_string())?; |
378 | | - if let Some(parent) = output.parent() { |
379 | | - if !parent.as_os_str().is_empty() { |
380 | | - fs::create_dir_all(parent).map_err(|err| err.to_string())?; |
381 | | - } |
382 | | - } |
383 | | - fs::write(&output, jsonl).map_err(|err| err.to_string())?; |
| 372 | + let report = export_jsonl( |
| 373 | + &self.store, |
| 374 | + ExportActionRequest { |
| 375 | + output: Some(output.clone()), |
| 376 | + include_sensitive, |
| 377 | + include_superseded, |
| 378 | + }, |
| 379 | + )?; |
384 | 380 | self.status = format!( |
385 | 381 | "exported {} memories to {}", |
386 | | - report.memory_count, |
| 382 | + report.report.memory_count, |
387 | 383 | output.display() |
388 | 384 | ); |
389 | 385 | } |
@@ -574,6 +570,21 @@ mod tests { |
574 | 570 | assert_eq!(app.dashboard.ring("cambium").unwrap().total, 1); |
575 | 571 | } |
576 | 572 |
|
| 573 | + #[test] |
| 574 | + fn slash_remember_uses_shared_action_and_keeps_status_shape() { |
| 575 | + let dir = tempdir().unwrap(); |
| 576 | + let mut app = app(&dir); |
| 577 | + |
| 578 | + app.execute_slash_command("/remember Use shared TUI remember action") |
| 579 | + .unwrap(); |
| 580 | + |
| 581 | + assert!(app.status.starts_with("remembered mem_")); |
| 582 | + let memories = app.store.list_all(false).unwrap(); |
| 583 | + assert_eq!(memories.len(), 1); |
| 584 | + assert_eq!(memories[0].summary, "Use shared TUI remember action"); |
| 585 | + assert_eq!(memories[0].ring, "cambium"); |
| 586 | + } |
| 587 | + |
577 | 588 | #[test] |
578 | 589 | fn secret_like_remember_is_blocked() { |
579 | 590 | let dir = tempdir().unwrap(); |
@@ -670,6 +681,21 @@ mod tests { |
670 | 681 | assert_eq!(app.status, "action cancelled"); |
671 | 682 | } |
672 | 683 |
|
| 684 | + #[test] |
| 685 | + fn confirmed_export_uses_shared_action_and_keeps_default_filters() { |
| 686 | + let dir = tempdir().unwrap(); |
| 687 | + let mut app = app(&dir); |
| 688 | + app.execute_slash_command("/remember Export through shared TUI action") |
| 689 | + .unwrap(); |
| 690 | + app.execute_slash_command("/export shared.jsonl").unwrap(); |
| 691 | + confirm(&mut app); |
| 692 | + |
| 693 | + let output = dir.path().join(".tree-ring/exports/shared.jsonl"); |
| 694 | + let jsonl = fs::read_to_string(output).unwrap(); |
| 695 | + assert!(jsonl.contains("tree_ring_memory_export")); |
| 696 | + assert!(jsonl.contains("Export through shared TUI action")); |
| 697 | + } |
| 698 | + |
673 | 699 | #[test] |
674 | 700 | fn export_path_rejects_parent_dir_in_relative_and_absolute_targets() { |
675 | 701 | let dir = tempdir().unwrap(); |
|
0 commit comments