Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
34d09a3
refactor(composio): move catalogs into the bus crate
senamakel Aug 30, 2026
507c395
refactor(composio): update catalog module paths
senamakel Aug 30, 2026
f45a979
feat(composio): add catalogs module for composio bus
senamakel Aug 30, 2026
6c10908
feat(composio): extract curated catalogs into their own module
senamakel Aug 30, 2026
c54f9e2
test(composio): add catalog module tests
senamakel Aug 30, 2026
d9e3480
refactor(composio): centralize catalogs and scope lookup in API
senamakel Aug 30, 2026
43e7558
feat(composio): expose static capability matrix
senamakel Aug 30, 2026
6bdc8ef
refactor(composio): centralize capability and catalog lookups
senamakel Aug 30, 2026
9bdf9cd
docs(composio): document curated toolkit catalogs
senamakel Aug 30, 2026
47245b6
fix(composio): use regular comments for implementation notes
senamakel Aug 30, 2026
42e2d3c
fix(composio): support additional Google and OneDrive slugs
senamakel Aug 30, 2026
8cc4bce
feat(retrieval): add defaults for fast retrieval queries
senamakel Aug 30, 2026
133b7e0
test(retrieval): verify contract and engine defaults match
senamakel Aug 30, 2026
e762964
Merge remote-tracking branch 'origin/main' into tinymemory-bus-only
senamakel Aug 30, 2026
9b890cd
chore(composio): reformat long lines and reorder imports
senamakel Aug 30, 2026
85b24d1
fix(composio): handle missing Microsoft catalog gracefully
senamakel Aug 30, 2026
5d36fbf
fix(composio): handle missing productivity catalog gracefully
senamakel Aug 30, 2026
25f408f
chore(tinymemory-bus): remove unused test module
senamakel Aug 30, 2026
b3ead1c
chore(catalogs): backtick-quote tool names in doc comments
senamakel Aug 30, 2026
4ad7345
chore(composio): add catalogs compatibility module
senamakel Aug 30, 2026
8d5be90
chore(composio): remove unused providers module
senamakel Aug 30, 2026
7c181e1
fix(providers): correct module path for composio provider imports
senamakel Aug 30, 2026
ad555ae
chore(composio): remove commented-out tool entries from curated catalogs
senamakel Aug 30, 2026
3e08612
fix(composio): correct catalog description for memory-mapped I/O region
senamakel Aug 30, 2026
149ded8
fix(tinymemory-bus): correct test module path for composio catalogs
senamakel Aug 30, 2026
0e21f9c
chore(descriptions): flatten microsoft teams description
senamakel Aug 30, 2026
f015621
chore: files changed crates/tinymemory-core/src/sync/composio/provide…
senamakel Aug 30, 2026
4560a62
feat(sync): add deletion notice to catalogs compat module
senamakel Aug 30, 2026
e65ff58
docs(scopes): document that action-slug catalogs now live in super::c…
senamakel Aug 30, 2026
286a6cd
fix(composio): correct doc comment about catalog location
senamakel Aug 30, 2026
46b8735
chore(composio): move test module declaration to end of file
senamakel Aug 30, 2026
de82098
docs(composio/catalogs): add README for composio catalogs
senamakel Aug 30, 2026
d50a9b7
docs(catalogs): add `has_native_provider` to the list of moved functions
senamakel Aug 30, 2026
8cf0f3a
docs(README): clarify the historical path and compat module in public…
senamakel Aug 30, 2026
134b815
chore(composio): move compat tests to a separate file
senamakel Aug 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions crates/tinymemory-api/src/host/composio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,53 @@ pub struct ComposioTriggerHistoryResult {
pub entries: Vec<ComposioTriggerHistoryEntry>,
}

/// Static overview of the Composio integrations this build supports.
Comment thread
senamakel marked this conversation as resolved.
///
/// Deliberately does not consult the live Composio backend or a direct tenant:
/// it is an observability surface over what the code knows how to do, not over
/// what the signed-in user has authorized. Callers wanting the latter want
/// `composio.list_toolkits` / `composio.list_connections`.
///
/// # Why this lives here and not in the engine crate
///
/// It reads only [`ComposioCapability`] and the contract's curated catalogs
/// (OpenHuman#5560). The version it replaces sat in
/// `tinymemory_core::sync::composio::providers`, so a host rendering its own
/// capability matrix had to link the engine to spell a table of `&'static str`.
///
/// The two provider-shaped facts it needs — which toolkits have a native
/// provider, and how often each syncs — are
/// [`catalogs::NATIVE_PROVIDERS`][crate::composio::catalogs::NATIVE_PROVIDERS],
/// a const table that carries the same defaults the provider impls pass to
/// their own interval resolver.
#[must_use]
pub fn capability_matrix() -> Vec<ComposioCapability> {
use crate::composio::catalogs;
catalogs::CAPABILITY_TOOLKITS
.iter()
.map(|toolkit| {
let native_provider = catalogs::has_native_provider(toolkit);
let catalog = catalogs::catalog_for_toolkit(toolkit);
let sync_interval_secs = catalogs::native_provider_sync_interval_secs(toolkit);
ComposioCapability {
toolkit: (*toolkit).to_string(),
description: catalogs::toolkit_description(toolkit).to_string(),
native_provider,
curated_tools: catalog.is_some(),
curated_tool_count: catalog
.map_or(0, <[crate::composio::scopes::CuratedTool]>::len),
tool_execution: catalog.is_some(),
user_profile: native_provider,
initial_sync: native_provider,
periodic_sync: sync_interval_secs.is_some(),
sync_interval_secs,
trigger_webhooks: native_provider,
memory_ingest: native_provider,
}
})
.collect()
}

#[cfg(test)]
#[path = "composio_tests.rs"]
mod tests;
89 changes: 89 additions & 0 deletions crates/tinymemory-bus/src/composio/catalogs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# composio::catalogs

The curated Composio tool catalogs, and the lookups over them. Composio
publishes 60+ actions per toolkit; most are noise for an agent's planning
loop. Each toolkit that has one gets a hand-curated `&'static [CuratedTool]`
slice that pares the surface down to a useful subset and tags every action
with a [`ToolScope`](../scopes.rs), so a user's scope preference can gate
execution per action.

Moved here from the engine crate (`tinymemory-core`) by OpenHuman#5560: the
catalogs are `&'static str` action slugs with no dependency of any kind, and
the *host* is their heaviest reader (it filters the agent's visible tool
list, renders unlock hints, and decides which connected toolkits get the
"agent-ready" badge). While they lived in the engine crate, every one of
those host reads was a compile-time link to `tinymemory-core`; now a host can
read them by depending on `tinymemory-bus` (or `tinymemory-api`) alone.

## Responsibilities

- Hold one curated `&'static [CuratedTool]` table per catalogued toolkit,
grouped by category (see Key files).
- Resolve a toolkit slug — including its known aliases and casing — to its
catalog via [`catalog_for_toolkit`].
- Answer "should this action slug be visible to the agent, given a loaded
user scope preference?" via [`is_action_visible_with_pref`], falling back
to [`classify_unknown`] for toolkits with no curated catalog.
- Answer "what scope does this slug require?" via [`curated_scope_for`].
- Provide a short human-readable description of a toolkit for the UI via
[`toolkit_description`] (`descriptions.rs`).
- Track which catalogued toolkits have a native `ComposioProvider` in the
engine crate ([`NATIVE_PROVIDERS`]) and how often each one syncs
([`native_provider_sync_interval_secs`]), without depending on the engine
crate's provider trait or registry.

## Key files

| File | Role |
| --- | --- |
| `mod.rs` | Module docs, category re-exports, `CAPABILITY_TOOLKITS`, `catalog_for_toolkit`, `is_action_visible_with_pref`, `curated_scope_for`, `toolkit_has_scope`, `NATIVE_PROVIDERS`, sync-interval helpers. |
| `descriptions.rs` | `toolkit_description` — one short sentence per toolkit slug (including aliases), generic fallback for anything uncatalogued. |
| `business.rs`, `google.rs`, `messaging.rs`, `microsoft.rs`, `productivity.rs`, `social_media.rs` | The category-grouped `CuratedTool` tables (Shopify/Stripe/HubSpot/…, Google apps, Slack/Discord/…, OneDrive/Excel, Outlook/Linear/Jira/…, Twitter/Spotify/YouTube). |
| `github.rs`, `gmail.rs`, `notion.rs`, `linear.rs`, `clickup.rs` | Provider-colocated catalogs for the five toolkits with a native `ComposioProvider` in the engine crate. |
| `mod_tests.rs`, `microsoft_tests.rs`, `productivity_tests.rs` | Module-local unit tests, wired from the bottom of `mod.rs` / the relevant category file with `#[cfg(test)] #[path = "…_tests.rs"] mod tests;`. |

## Public surface

Re-exported from `mod.rs` (and re-exported again from `tinymemory-api::composio::catalogs`,
and from `tinymemory-core::sync::composio::providers::catalogs` for the historical flat
path — plus `tinymemory-core`'s `providers::catalogs_compat` module, which restores the
six per-category module names — `catalogs_business`, `catalogs_google`, … — that predate
this move):

- `catalog_for_toolkit`, `is_action_visible_with_pref`, `curated_scope_for`, `toolkit_has_scope`, `has_native_provider`
- `CAPABILITY_TOOLKITS`, `NATIVE_PROVIDERS`
- `toolkit_description`
- `sync_interval_env_var`, `parse_sync_interval_override`, `native_provider_sync_interval_secs`
- every category module (`business`, `google`, `messaging`, `microsoft`, `productivity`,
`social_media`) and every provider-colocated module (`gmail`, `notion`, `github`,
`linear`, `clickup`), each exporting its `&'static [CuratedTool]` constants.

## Dependencies

None beyond `serde`/`std` (via [`CuratedTool`]/[`ToolScope`] in `../scopes.rs`). This
module must stay dependency-light — see the guard command in
`tinymemory-bus/Cargo.toml`'s doc comment (`cargo tree -p tinymemory-bus -e normal,build
--prefix none | grep -Ei 'rusqlite|libsqlite|git2|reqwest|regex|tokio|tinybus'`, expect no
match) before adding anything here.

## Used by

- `tinymemory-api::host::composio::capability_matrix` — the static integrations-overview
RPC surface.
- `tinymemory-core::sync::composio::providers` — re-exports every symbol above at its
historical path so in-engine callers (trigger dispatch, periodic sync, the six native
`ComposioProvider` impls) keep resolving unchanged.
- The OpenHuman host — filters the agent's visible tool list and renders "agent-ready" /
unlock-hint UI without linking `tinymemory-core`.

## Notes / gotchas

- `get_provider(..).curated_tools()` (the engine's provider-registry hop) is deliberately
**not** consulted here. Every native provider's `curated_tools()` was verified to return
exactly the slice `catalog_for_toolkit` returns for the same toolkit, so the hop was pure
indirection — see the "`get_provider(..).curated_tools()` is not a separate source"
section in `mod.rs`'s module docs.
- `resolve_sync_interval_secs` (engine-side) logs via `tracing::warn!` on a malformed
interval override; `native_provider_sync_interval_secs` here applies the identical rule
(`parse_sync_interval_override`) silently, because an observability read should not emit
warnings. Do not add `tracing` to this crate to "fix" that — it is intentional.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! Curated catalogs — business toolkits: Shopify, Stripe, HubSpot,
//! Curated catalogs — business toolkits: Shopify, Stripe, `HubSpot`,
//! Salesforce, Airtable, Figma.

use super::tool_scope::{CuratedTool, ToolScope};
use crate::composio::scopes::{CuratedTool, ToolScope};

// ── shopify ─────────────────────────────────────────────────────────
/// The curated action catalog for the `shopify` toolkit.
pub const SHOPIFY_CURATED: &[CuratedTool] = &[
CuratedTool {
slug: "SHOPIFY_BULK_QUERY_OPERATION",
Expand Down Expand Up @@ -88,6 +89,7 @@ pub const SHOPIFY_CURATED: &[CuratedTool] = &[
];

// ── stripe ──────────────────────────────────────────────────────────
/// The curated action catalog for the `stripe` toolkit.
pub const STRIPE_CURATED: &[CuratedTool] = &[
CuratedTool {
slug: "STRIPE_GET_PAYMENT_INTENT",
Expand Down Expand Up @@ -168,6 +170,7 @@ pub const STRIPE_CURATED: &[CuratedTool] = &[
];

// ── hubspot ─────────────────────────────────────────────────────────
/// The curated action catalog for the `hubspot` toolkit.
pub const HUBSPOT_CURATED: &[CuratedTool] = &[
CuratedTool {
slug: "HUBSPOT_GET_CONTACTS",
Expand Down Expand Up @@ -272,6 +275,7 @@ pub const HUBSPOT_CURATED: &[CuratedTool] = &[
];

// ── salesforce ──────────────────────────────────────────────────────
/// The curated action catalog for the `salesforce` toolkit.
pub const SALESFORCE_CURATED: &[CuratedTool] = &[
CuratedTool {
slug: "SALESFORCE_RUN_SOQL_QUERY",
Expand Down Expand Up @@ -388,6 +392,7 @@ pub const SALESFORCE_CURATED: &[CuratedTool] = &[
];

// ── airtable ────────────────────────────────────────────────────────
/// The curated action catalog for the `airtable` toolkit.
pub const AIRTABLE_CURATED: &[CuratedTool] = &[
CuratedTool {
slug: "AIRTABLE_LIST_RECORDS",
Expand Down Expand Up @@ -464,6 +469,7 @@ pub const AIRTABLE_CURATED: &[CuratedTool] = &[
];

// ── figma ───────────────────────────────────────────────────────────
/// The curated action catalog for the `figma` toolkit.
pub const FIGMA_CURATED: &[CuratedTool] = &[
CuratedTool {
slug: "FIGMA_GET_FILE_JSON",
Expand Down
125 changes: 125 additions & 0 deletions crates/tinymemory-bus/src/composio/catalogs/clickup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//! Curated catalog of ClickUp Composio actions exposed to the agent.
//!
//! Slugs match Composio's naming convention (`<TOOLKIT>_<ACTION>`) for
//! the ClickUp REST surface. See <https://composio.dev/docs/toolkits/clickup>
//! for the canonical action list; the entries here are the read-oriented
//! subset the periodic Memory Tree sync relies on, plus the most common
//! task-write surface the agent already uses through generic tool-calling.

use crate::composio::scopes::{CuratedTool, ToolScope};

/// The curated action catalog for the `clickup` toolkit.
pub const CLICKUP_CURATED: &[CuratedTool] = &[
// ── Read: identity ─────────────────────────────────────────────
CuratedTool {
slug: "CLICKUP_GET_AUTHORIZED_USER",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES",
scope: ToolScope::Read,
},
// ── Read: structure (workspace → space → folder → list) ──────
CuratedTool {
slug: "CLICKUP_GET_SPACES",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_FOLDERS",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_LISTS",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_FOLDERLESS_LISTS",
scope: ToolScope::Read,
},
// ── Read: tasks (the main memory ingest surface) ──────────────
CuratedTool {
slug: "CLICKUP_GET_FILTERED_TEAM_TASKS",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_TASKS",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_TASK",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_TASK_COMMENTS",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_LIST_COMMENTS",
scope: ToolScope::Read,
},
// ── Read: docs / views / time tracking ────────────────────────
CuratedTool {
slug: "CLICKUP_SEARCH_DOCS",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_DOC_PAGES",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_VIEW_TASKS",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_TIME_ENTRIES_WITHIN_A_DATE_RANGE",
scope: ToolScope::Read,
},
// ── Read: members ─────────────────────────────────────────────
CuratedTool {
slug: "CLICKUP_GET_WORKSPACE_MEMBERS",
scope: ToolScope::Read,
},
CuratedTool {
slug: "CLICKUP_GET_TASK_MEMBERS",
scope: ToolScope::Read,
},
// ── Write: create / update tasks ──────────────────────────────
CuratedTool {
slug: "CLICKUP_CREATE_TASK",
scope: ToolScope::Write,
},
CuratedTool {
slug: "CLICKUP_UPDATE_TASK",
scope: ToolScope::Write,
},
CuratedTool {
slug: "CLICKUP_CREATE_TASK_COMMENT",
scope: ToolScope::Write,
},
CuratedTool {
slug: "CLICKUP_UPDATE_COMMENT",
scope: ToolScope::Write,
},
// ── Write: structure ──────────────────────────────────────────
CuratedTool {
slug: "CLICKUP_CREATE_LIST",
scope: ToolScope::Write,
},
CuratedTool {
slug: "CLICKUP_UPDATE_LIST",
scope: ToolScope::Write,
},
// ── Admin: destructive ────────────────────────────────────────
CuratedTool {
slug: "CLICKUP_DELETE_TASK",
scope: ToolScope::Admin,
},
CuratedTool {
slug: "CLICKUP_DELETE_COMMENT",
scope: ToolScope::Admin,
},
CuratedTool {
slug: "CLICKUP_DELETE_LIST",
scope: ToolScope::Admin,
},
];
65 changes: 65 additions & 0 deletions crates/tinymemory-bus/src/composio/catalogs/descriptions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//! Human-readable capability summaries for Composio toolkit slugs.

/// Human-readable capability summary for a Composio toolkit slug.
///
/// Used by the prompt renderer to tell the orchestrator what each connected
/// integration can do. Covers the most common toolkits; unknown slugs get
/// a generic fallback so newly connected services still appear.
pub fn toolkit_description(slug: &str) -> &'static str {
match slug {
"gmail" => {
"Send, read, draft, reply, forward, and search emails; manage labels and threads"
}
"notion" => "Create, read, update, and search notion pages and notion databases",
"github" => {
"Manage repositories, issues, and pull requests on GitHub; sync \
assigned issues into Memory Tree"
}
"slack" => "Send messages, read channels, manage threads, and post updates in Slack",
"discord" => "Send messages, manage channels, and interact with Discord servers",
"google_calendar" | "googlecalendar" => {
"Create, update, and query calendar events; check availability"
}
"google_drive" | "googledrive" => {
"Upload, download, search, and share files in Google Drive"
}
"google_docs" | "googledocs" => "Create, read, and edit Google Docs documents",
"google_sheets" | "googlesheets" => "Read, write, and manage Google Sheets spreadsheets",
"outlook" => "Send, read, and manage emails in Microsoft Outlook",
"microsoft" | "microsoft_teams" => "Send messages and manage channels in Microsoft Teams",
"larksuite" => {
"Connect Lark / Feishu workspace chat, docs, wiki, and meetings via Composio"
}
"linear" => {
"Create, read, and manage issues, projects, and cycles in Linear; sync \
assigned issues into Memory Tree"
}
"jira" => "Create and manage issues, projects, and sprints in Jira",
"trello" => "Create and manage cards, lists, and boards in Trello",
"asana" => "Create and manage tasks, projects, and sections in Asana",
"clickup" => {
"Create, read, and manage tasks, lists, and docs in ClickUp; sync \
assigned tasks into Memory Tree"
}
"dropbox" => "Upload, download, and share files in Dropbox",
"twitter" => "Post tweets, read timelines, and manage Twitter interactions",
"spotify" => "Control playback, search music, and manage playlists on Spotify",
"telegram" => "Send and receive messages via Telegram",
"whatsapp" => "Send and receive messages via WhatsApp",
"twilio" => "Send SMS, make calls, and manage communications via Twilio",
"shopify" => "Manage products, orders, and customers in Shopify",
"stripe" => "Manage payments, subscriptions, and customers in Stripe",
"hubspot" => "Manage contacts, deals, and marketing in HubSpot",
"salesforce" => "Manage contacts, leads, and opportunities in Salesforce",
"airtable" => "Read and write records in Airtable bases",
"figma" => "Access and manage Figma design files and components",
"youtube" => "Search videos, manage playlists, and interact with YouTube",
"calendar" => "Create, update, and query calendar events",
"one_drive" | "onedrive" | "one" => {
"Upload, download, search, and share files in Microsoft OneDrive"
}
"excel" => "Read, write, and manage workbooks, worksheets, and tables in Microsoft Excel",
"todoist" => "Create and manage tasks, projects, sections, and labels in Todoist",
_ => "Interact with this connected service via its available actions",
}
}
Loading