Incrementally ingests the Cursor transcript referenced by `event_json` into the resolved project session DB, bounded by `max_new_bytes` (the hot-path cap) and an overall `budget`. Always fails open: a timeout, missing transcript, or any error is swallowed so the calling hook never blocks the agent.
(
event_json: &str,
max_new_bytes: Option<u64>,
budget: Duration,
)
| 662 | /// and an overall `budget`. Always fails open: a timeout, missing transcript, or |
| 663 | /// any error is swallowed so the calling hook never blocks the agent. |
| 664 | pub(super) async fn ingest_cursor_transcript_for_event( |
| 665 | event_json: &str, |
| 666 | max_new_bytes: Option<u64>, |
| 667 | budget: Duration, |
| 668 | ) -> bool { |
| 669 | let work = async { |
| 670 | let Ok(parsed) = serde_json::from_str::<Value>(event_json) else { |
| 671 | return false; |
| 672 | }; |
| 673 | let Some(project_root) = cursor_project_root_from_parsed_event(&parsed) else { |
| 674 | return false; |
| 675 | }; |
| 676 | if let Some(cwd_root) = cursor_event_cwd(&parsed) |
| 677 | .as_deref() |
| 678 | .and_then(crate::config::discover_project_root) |
| 679 | { |
| 680 | if !paths_same(&cwd_root, &project_root) { |
| 681 | return false; |
| 682 | } |
| 683 | } |
| 684 | let Some(db) = crate::sessions::cursor::open_project_session_db(&project_root).await else { |
| 685 | return false; |
| 686 | }; |
| 687 | let _ = crate::sessions::cursor::ingest_cursor_transcript_event_capped( |
| 688 | event_json, |
| 689 | &db, |
| 690 | max_new_bytes, |
| 691 | ) |
| 692 | .await; |
| 693 | true |
| 694 | }; |
| 695 | // Short-lived CLI hook processes exit immediately, so the ingest must run |
| 696 | // inline (not on a detached task); the timeout keeps it inside budget. |
| 697 | tokio::time::timeout(budget, work).await.unwrap_or(false) |
| 698 | } |
| 699 | |
| 700 | fn cursor_tool_hint_input(parsed: &Value) -> ToolHintInput { |
| 701 | let tool_input = parsed |
no test coverage detected