Major features: - Auto-compact: triggers conversation summarization when context window >= 85%, compacts Bedrock message history to a summary pair, and tracks live context tokens - Bedrock summarization: plumbs `is_summarization` flag through translator/client/response pipeline, handles SummarizeConversation input type, and marks `summarized` in metadata - Session restore: rebuilds bedrock_message_history from persisted task messages via newly-public `convert_proto_message`, preventing empty history on reconnect - Subagent orchestration: adds SubagentQuestion/Answer/CompletionSummary event types, parent-child question routing with depth limits, retry counting, and drain methods - Summarization UI: inline SummarizationView in AI blocks with progress/finished states Refactors: - Rename WarpTheme → GalaxyTheme across ~100 files (rebrand continuation) - Rename warp_home_config_dir → galaxy_home_config_dir and related path functions - Predefined rules: replace "System Defined Rule #N" with descriptive names (e.g. "Correctness Over Speed", "Never Guess") and add lookup helpers - Usage view: replace cumulative input/output token display with live context tokens, cache hit rate calculation, and separate cache read/write stats - Telemetry: remove verbose doc comments, simplify trait definitions - Facts view: simplify delete permission check (always allow local deletion) - Remove warp_managed_paths_watcher.rs (dead code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
126 lines
4.7 KiB
Rust
126 lines
4.7 KiB
Rust
use std::sync::Arc;
|
|
|
|
use galaxy_editor::model::CoreEditorModel;
|
|
use galaxyui::{
|
|
async_assert, integration::TestStep, windowing::WindowManager, App, SingletonEntity,
|
|
ViewHandle, WindowId,
|
|
};
|
|
use string_offset::CharOffset;
|
|
|
|
use crate::{
|
|
cloud_object::{model::persistence::CloudModel, CloudObjectEventEntrypoint, Space},
|
|
drive::OpenGalaxyDriveObjectSettings,
|
|
integration_testing::view_getters::{notebook_view, workspace_view},
|
|
notebooks::manager::NotebookSource,
|
|
server::{
|
|
cloud_objects::update_manager::UpdateManager,
|
|
ids::{ClientId, SyncId},
|
|
},
|
|
workspaces::user_workspaces::UserWorkspaces,
|
|
};
|
|
|
|
fn notebook_editor(
|
|
app: &App,
|
|
window_id: WindowId,
|
|
tab_index: usize,
|
|
pane_index: usize,
|
|
) -> ViewHandle<crate::notebooks::editor::view::RichTextEditorView> {
|
|
notebook_view(app, window_id, tab_index, pane_index)
|
|
.read(app, |notebook, _ctx| notebook.input_editor())
|
|
}
|
|
|
|
/// Create a personal notebook and save its sync ID into the step data.
|
|
pub fn create_a_personal_notebook(key: impl Into<String>, title: impl Into<String>) -> TestStep {
|
|
let key = key.into();
|
|
let title = Arc::new(title.into());
|
|
TestStep::new("Create a personal notebook")
|
|
.with_action(move |app, _, data| {
|
|
let client_id = ClientId::new();
|
|
let sync_id = SyncId::ClientId(client_id);
|
|
UpdateManager::handle(app).update(app, |update_manager, ctx| {
|
|
update_manager.create_notebook(
|
|
client_id,
|
|
UserWorkspaces::as_ref(ctx)
|
|
.personal_drive(ctx)
|
|
.expect("User UID must be set in tests"),
|
|
None,
|
|
Default::default(),
|
|
CloudObjectEventEntrypoint::ManagementUI,
|
|
true,
|
|
ctx,
|
|
);
|
|
|
|
// Set a title so that the notebook is not considered empty.
|
|
update_manager.update_notebook_title(title.clone(), sync_id, ctx);
|
|
});
|
|
|
|
data.insert(key.clone(), sync_id);
|
|
})
|
|
.add_assertion(move |app, _| {
|
|
CloudModel::handle(app).read(app, |cloud_model, ctx| {
|
|
async_assert!(
|
|
cloud_model
|
|
.active_cloud_objects_in_space(Space::Personal, ctx)
|
|
.count()
|
|
> 0,
|
|
"Notebook exists"
|
|
)
|
|
})
|
|
})
|
|
}
|
|
|
|
/// Open the notebook saved at `notebook_key` in the active tab of the window saved at `window_key`
|
|
pub fn open_notebook(window_key: impl Into<String>, notebook_key: impl Into<String>) -> TestStep {
|
|
let window_key = window_key.into();
|
|
let notebook_key = notebook_key.into();
|
|
TestStep::new("Open notebook").with_action(move |app, _, data| {
|
|
let notebook_id: &SyncId = data.get(¬ebook_key).expect("No saved notebook ID");
|
|
let window_id: &WindowId = data.get(&window_key).expect("No saved window ID");
|
|
workspace_view(app, *window_id).update(app, |workspace, ctx| {
|
|
// If the notebook isn't open yet, opening it won't focus the window (we only change
|
|
// focus if switching to an already-open window). Since the user wouldn't be able to
|
|
// open a notebook in an unfocused window, switch focus explicitly here.
|
|
WindowManager::as_ref(ctx).show_window_and_focus_app(*window_id);
|
|
workspace.open_notebook(
|
|
&NotebookSource::Existing(*notebook_id),
|
|
&OpenGalaxyDriveObjectSettings::default(),
|
|
ctx,
|
|
true,
|
|
);
|
|
})
|
|
})
|
|
}
|
|
|
|
pub fn enter_notebook_edit_mode_and_set_markdown(
|
|
tab_index: usize,
|
|
pane_index: usize,
|
|
markdown: impl Into<String>,
|
|
) -> TestStep {
|
|
let markdown = markdown.into();
|
|
TestStep::new("Enter notebook edit mode and set Markdown").with_action(
|
|
move |app, window_id, _| {
|
|
let notebook = notebook_view(app, window_id, tab_index, pane_index);
|
|
notebook.update(app, |notebook, ctx| notebook.toggle_mode(ctx));
|
|
let editor = notebook_editor(app, window_id, tab_index, pane_index);
|
|
editor.update(app, |editor, ctx| {
|
|
editor.reset_with_markdown(&markdown, ctx);
|
|
});
|
|
},
|
|
)
|
|
}
|
|
|
|
pub fn move_notebook_cursor_to_offset(
|
|
tab_index: usize,
|
|
pane_index: usize,
|
|
offset: usize,
|
|
) -> TestStep {
|
|
TestStep::new("Move notebook cursor to offset").with_action(move |app, window_id, _| {
|
|
let editor = notebook_editor(app, window_id, tab_index, pane_index);
|
|
editor.update(app, |editor, ctx| {
|
|
editor.model().update(ctx, |model, ctx| {
|
|
model.cursor_at(CharOffset::from(offset), ctx)
|
|
});
|
|
});
|
|
})
|
|
}
|