Repository navigation
feat: StartTask reads/writes per-site memory through SiteMemoryHost (contract 2.17) #100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ | |
| //! release workflow bumps, which tracks the shipped artifact. | ||
|
|
||
| /// The wire contract version this crate defines. | ||
| pub const CONTRACT_VERSION: (u32, u32) = (2, 16); | ||
| pub const CONTRACT_VERSION: (u32, u32) = (2, 17); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This bumps AGENTS.md reference: AGENTS.md:L182-L185 Useful? React with 👍 / 👎. |
||
|
|
||
| /// Returns whether a host holding [`CONTRACT_VERSION`] can bind to a module | ||
| /// reporting `module`. | ||
|
|
@@ -22,7 +22,7 @@ pub const CONTRACT_VERSION: (u32, u32) = (2, 16); | |
| /// ``` | ||
| /// # use tinycomputer_bus::{is_compatible, CONTRACT_VERSION}; | ||
| /// assert!(is_compatible(CONTRACT_VERSION)); | ||
| /// assert!(is_compatible((2, 16))); | ||
| /// assert!(is_compatible((2, 17))); | ||
| /// assert!(!is_compatible((2, 11))); | ||
| /// assert!(!is_compatible((1, 8))); | ||
| /// ``` | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,13 +5,16 @@ use std::sync::Arc; | |
|
|
||
| use tinybus::{Error as TinyBusError, Result as TinyBusResult}; | ||
| use tinycomputer_browser::{AgentBrowser, Browser}; | ||
| use tinycomputer_bus::agent::{SurfaceAvailability, SurfaceKind}; | ||
| use tinycomputer_bus::agent::{ | ||
| AgentResponse, StartTaskRequest, SurfaceAvailability, SurfaceKind, TaskView, | ||
| }; | ||
| use tinycomputer_bus::{DesktopResponse, JevConfig}; | ||
| use tinycomputer_engine as agentic; | ||
|
|
||
| use super::DesktopService; | ||
| use crate::tinybus_module::config::{BrowserDefaults, cursor_config}; | ||
| use crate::tinybus_module::runner::WorkspaceRunner; | ||
| use crate::tinybus_module::site_memory::{SiteLink, SiteMemoryPort, refused_flow}; | ||
| use crate::{Desktop, Result}; | ||
|
|
||
| impl DesktopService { | ||
|
|
@@ -87,6 +90,7 @@ impl DesktopService { | |
| browser, | ||
| browser_defaults, | ||
| accessibility: Arc::new(super::accessibility::Access::default()), | ||
| site_link: None, | ||
| }) | ||
| } | ||
|
|
||
|
|
@@ -200,3 +204,54 @@ impl DesktopService { | |
| self | ||
| } | ||
| } | ||
|
|
||
| impl DesktopService { | ||
| /// Keeps what browser tasks learn about a site through `port`, the host's | ||
| /// `SiteMemoryHost`. | ||
| pub(crate) fn with_site_memory(mut self, port: Box<dyn SiteMemoryPort>) -> Self { | ||
| self.site_link = Some(Arc::new(SiteLink::new(port))); | ||
| self | ||
| } | ||
|
|
||
| /// Starts a task with what earlier tasks on its `site` left, and follows | ||
| /// it for what it may teach. A saved plan the engine refuses is | ||
| /// forgotten and the task started again to be planned afresh. | ||
| pub(super) async fn start_remembering( | ||
| &self, | ||
| mut request: StartTaskRequest, | ||
| ) -> TinyBusResult<AgentResponse<TaskView>> { | ||
| let Some(link) = self.site_link.clone() else { | ||
| return self.on_tasks(move |tasks| tasks.start(&request)).await; | ||
| }; | ||
| let mut prepared = link.prepare(&mut request).await; | ||
| let mut reply = self.start_once(request.clone()).await?; | ||
| if refused_flow(&reply) | ||
| && let Some(reusing) = prepared.as_mut().filter(|reusing| reusing.reuses_plan()) | ||
| { | ||
| link.refused(reusing).await; | ||
| request.flow = None; | ||
| reply = self.start_once(request).await?; | ||
| } | ||
| if let (Some(prepared), Some(view)) = (prepared, reply.data.as_ref()) { | ||
| link.follow(&view.id, prepared); | ||
|
Comment on lines
+235
to
+236
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Useful? React with 👍 / 👎. |
||
| } | ||
| self.learn_from(&reply).await; | ||
| Ok(reply) | ||
| } | ||
|
|
||
| async fn start_once( | ||
| &self, | ||
| request: StartTaskRequest, | ||
| ) -> TinyBusResult<AgentResponse<TaskView>> { | ||
| self.on_tasks(move |tasks| tasks.start(&request)).await | ||
| } | ||
|
|
||
| /// Learns from `reply`'s task once it has ended. | ||
| pub(super) async fn learn_from(&self, reply: &AgentResponse<TaskView>) { | ||
| let (Some(link), Some(view)) = (&self.site_link, reply.data.as_ref()) else { | ||
| return; | ||
| }; | ||
| let tasks = self.tasks.clone(); | ||
| link.learn(view, |id| tasks.report(id)).await; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new public
sitefield is absent from bothtinycomputer_engine::task::describe::start_task_input()andcrates/tinycomputer-skills/schemas/start_task.schema.json. Consequently, callers that build tool inputs fromDescribe, and agents using the packaged skill schema, are never offered the only field that enables this feature and will continue sending requests that bypass site memory. Add the field to both advertised schemas and their schema-coverage tests.AGENTS.md reference: AGENTS.md:L414-L415
Useful? React with 👍 / 👎.