* chore: update AlphaHuman version to 0.49.3 and configure updater plugin in tauri.conf.json - Bumped the AlphaHuman package version in Cargo.lock to 0.49.3. - Added updater configuration in tauri.conf.json to enable automatic updates with specified endpoints. * refactor: rename AlphaHuman to OpenHuman across the codebase - Updated all instances of "AlphaHuman" to "OpenHuman" in comments, tooltips, and constants to reflect the new branding. - Adjusted relevant documentation and prompts to ensure consistency with the new name. * refactor: update documentation and configurations to reflect OpenHuman branding - Replaced all instances of "AlphaHuman" with "OpenHuman" in documentation, comments, and configuration files to ensure consistency with the new branding. - Updated deep link URLs and related authentication flows to use the new "openhuman://" scheme. - Adjusted paths and references in the skills system and other related files to align with the new project name.te * refactor: standardize OpenHuman references and update configurations - Replaced all instances of "AlphaHuman" with "OpenHuman" across documentation, comments, and configuration files to maintain branding consistency. - Updated URLs and paths to reflect the new "openhuman://" scheme. - Adjusted environment variable names and related settings to align with the new project identity. - Enhanced documentation for clarity and accuracy regarding the OpenHuman framework.r * chore: update subproject commit reference in skills directory * refactor: update backend URL to reflect new service domain - Changed default backend URL from "https://api.openhuman.xyz" to "https://api.tinyhumans.ai" in both JavaScript and Rust configuration files. - Ensured consistency across the codebase regarding the new backend service endpoint. * feat: introduce identity and migration modules for OpenHuman - Added a new identity module to support AIEOS v1.1 JSON format, including structures for identity, psychology, linguistics, motivations, capabilities, physicality, history, and interests. - Implemented a migration module to facilitate data migration from OpenClaw memory, including SQLite and Markdown sources, with detailed reporting on migration statistics and warnings. - Established utility functions for handling multimodal content and image processing within the OpenHuman framework. - Enhanced the agent system with new dispatcher and classifier functionalities to improve tool management and message classification. * chore: remove Android project files and configurations - Deleted various Android project files including .editorconfig, .gitignore, build.gradle.kts, gradle.properties, and others to clean up the project structure. - Removed all related resources, layouts, and source files from the Android app directory to streamline the codebase. - This cleanup is part of a larger effort to refactor and simplify the project structure. * refactor: update login flow and remove Telegram integration - Removed the TelegramLoginButton component and its references from the OAuthLoginSection, streamlining the login options. - Updated the AppRoutes to remove the login route, reflecting changes in the authentication flow. - Enhanced the RotatingTetrahedronCanvas component with improved geometry and lighting effects for better visual presentation. - Adjusted the TypewriterGreeting component's styling for consistency. - Cleaned up the Welcome page to integrate the OAuthLoginSection directly, improving user experience. * chore: update subproject commit reference in skills directory * chore: update test configurations and improve test assertions - Modified test scripts in package.json to use a specific Vitest configuration file for consistency. - Updated assertions in loader tests to ensure loading durations are non-negative. - Enhanced tool loading tests to clarify expected behavior regarding localStorage and cache management. - Adjusted agent tool registry tests to improve error handling and ensure accurate statistics. - Refined device detection tests to reflect updated fallback URLs. * fix: enhance parameter formatting and remove unused components - Updated the `formatParameters` function to handle cases where schema properties are empty, returning a more informative response. - Deleted the `DownloadScreen` component and associated device detection utilities to streamline the codebase and remove unused functionality. - Adjusted tests to reflect changes in the tool loading and agent tool registry, ensuring accuracy in assertions. * chore: simplify Vitest configuration by removing unused include patterns - Updated the Vitest configuration to remove unnecessary test file patterns, streamlining the test setup for better clarity and maintainability. * refactor: update paths and comments for AI configuration and file watching - Modified Vite configuration to ignore only the `src-tauri` directory. - Updated logging messages to reflect the correct path for writing AI configuration files. - Adjusted fetch calls in the file watcher to use the new path for `TOOLS.md`. - Revised comments and logic in Rust code to clarify the handling of AI configuration file paths, including legacy fallback options. * chore: remove unused updater secrets from GitHub Actions workflow - Deleted UPDATER_GIST_URL and UPDATER_GIST_ID environment variables from the package-and-publish workflow, streamlining the configuration. * chore: comment out Vitest thresholds for clarity - Commented out the thresholds section in the Vitest configuration to improve clarity and maintainability, as it is currently not in use. * ran formatter * chore: update updater public key in tauri configuration - Replaced the existing public key in the updater plugin configuration with a new value to ensure proper functionality and security. * chore: update ESLint configuration and refactor components - Added `localStorage` and `sessionStorage` as readonly globals in ESLint configuration for better linting support. - Removed unused imports from `SkillsPanel.tsx` to clean up the code. - Changed the type of `watcherInterval` in `file-watcher.ts` for improved type safety. - Refactored toast management logic in `Intelligence.tsx` to enhance clarity and maintainability. - Simplified import statements in `IntelligenceProvider.tsx` for consistency. - Streamlined object property shorthand in `agentToolRegistry.ts` for cleaner code. * refactor: improve error handling and type safety in Intelligence component - Enhanced toast notification logic to defer state updates, preventing potential issues with setState in effects. - Updated the source filter dispatch to use a more specific type for improved type safety. * refactor: enhance type safety across various components and services - Updated type definitions from `any` to `unknown` in multiple files to improve type safety and prevent potential runtime errors. - Refactored state management in `TauriCommandsPanel` to use more specific types. - Adjusted context and parameters in several interfaces to ensure consistent typing. - Added ESLint directive to `polyfills.ts` for intentional global assignments. - Streamlined type handling in utility functions and API responses for better clarity and maintainability. * refactor: streamline import statements and improve code clarity - Consolidated import statements in `agentToolRegistry.ts` and `intelligenceSlice.ts` for better readability. - Simplified the `createTestStore` function in `test-utils.tsx` to enhance code conciseness. - Cleaned up the `isExecutionStepProgressEvent` function in `intelligence-chat-api.ts` for improved clarity and maintainability.
11 KiB
Skills → Memory Layer → Agent Inference: Full Flow
Overview
This document traces the complete data flow from skill discovery and OAuth/sync events, through the TinyHumans Neocortex memory layer (tinyhumansai SDK), and into the Rust-side agentic inference loop — showing exactly how skill data is written to and read from memory and how it reaches the LLM context at inference time.
1. Skill Discovery & Lifecycle (SkillProvider.tsx)
File: src/providers/SkillProvider.tsx
On app mount (when a JWT token is present) SkillProvider calls
invoke('runtime_discover_skills') → the Rust runtime scans
skills/skills/{skill-id}/manifest.json from the git submodule and returns a manifest list.
Token present
→ discoverSkills()
→ invoke('runtime_discover_skills') // Rust: qjs_engine.rs:184
→ reads skills/skills/*/manifest.json
→ filters: is_javascript() && supports_current_platform()
→ returns manifests[]
→ skillManager.registerSkill(manifest) // in-memory registry
→ for each manifest with setupComplete:
skillManager.startSkill(manifest) // starts V8/QuickJS instance
Two Tauri event listeners run continuously:
| Event | What it does |
|---|---|
skill-state-changed |
Dispatches setSkillState into Redux skillsSlice.skillStates[skillId] |
runtime:skill-status-changed |
Updates skillsSlice.skills[skillId].status; surfaces errors |
2. Memory Client Initialisation
File: src-tauri/src/memory/mod.rs
Tauri command: init_memory_client (called by frontend after auth)
The MemoryClient wraps the TinyHumansMemoryClient from the tinyhumansai Rust crate.
It is constructed with the user's JWT (authSlice.token) and stored as Arc<MemoryClient>
in MemoryState (a Mutex<Option<MemoryClientRef>>).
Base URL resolution (in priority order):
OPENHUMAN_BASE_URLenv varTINYHUMANS_BASE_URLenv var- SDK default
3. Skill → Memory Sync: Two Write Paths
Both trigger inside src-tauri/src/runtime/qjs_skill_instance.rs.
3a. OAuth Completion (skill/oauth-complete)
When a user connects a skill via OAuth, the JS runtime calls back with skill/oauth-complete.
After the OAuth flow completes the skill's ops state (data published via state.set()) is
snapshotted and stored to memory:
skill/oauth-complete handler
→ handle_js_call(rt, ctx, "onOAuthComplete", params) // runs skill JS
→ ops_state.read().data.clone() // snapshot skill state
→ tokio::spawn (fire-and-forget):
MemoryClient::store_skill_sync(
skill_id = e.g. "gmail"
integration_id = params["integrationId"] // e.g. user email
title = "{skill} OAuth sync — {integrationId}"
content = JSON snapshot of ops state
namespace = "skill:{skill_id}:{integration_id}"
)
→ tinyhumansai::TinyHumansMemoryClient::insert_memory(InsertMemoryParams { ... })
→ HTTP POST to TinyHumans Neocortex API
3b. Periodic Sync (skill/sync)
The runtime fires skill/sync events on a cron schedule. The flow is identical to OAuth
completion but uses integration_id = "default" and title "{skill} periodic sync":
skill/sync handler
→ handle_js_call(rt, ctx, "onSync", "{}")
→ ops_state.read().data.clone()
→ tokio::spawn:
MemoryClient::store_skill_sync(
skill_id = e.g. "notion"
integration_id = "default"
namespace = "skill:notion:default"
content = JSON snapshot
)
Namespace Pattern
All skill memories are stored under skill:{skill_id}:{integration_id}.
Examples: skill:gmail:user@example.com, skill:notion:default.
4. Memory Operations Reference
File: src-tauri/src/memory/mod.rs
| Method | SDK call | When used |
|---|---|---|
store_skill_sync(...) |
insert_memory |
OAuth complete, periodic sync |
query_skill_context(...) |
query_memory |
RAG query — fetch relevant chunks for a user question |
recall_skill_context(...) |
recall_memory |
Recall synthesised summary from Master node |
clear_skill_memory(...) |
delete_memory |
OAuth revoke / disconnect |
5. Conversation → Inference: Two Code Paths
File: src/pages/Conversations.tsx
useRustChat() returns true when running in Tauri (desktop). This selects between two paths:
handleSendMessage(text)
├─ rustChat == true → Rust path (invoke chat_send)
└─ rustChat == false → Web path (handleSendMessageWeb — TypeScript loop)
5a. Rust Path (Desktop)
chatSend({ threadId, message, model, authToken, backendUrl, messages, notionContext })
→ invoke('chat_send') // src-tauri/src/commands/chat.rs:359
→ spawns background task
→ chat_send_inner(...)
Completion events flow back over Tauri events:
| Event | Frontend handler |
|---|---|
chat:tool_call |
shows active tool indicator |
chat:tool_result |
clears tool indicator |
chat:done |
dispatch(addInferenceResponse(...)) |
chat:error |
shows error, clears loading state |
5b. Web/Fallback Path
Used when not running in Tauri (browser). Runs the agentic loop entirely in TypeScript:
- Calls
inferenceApi.createChatCompletion(request)directly - Executes tools via
skillManager.callTool(skillId, toolName, args) - Both paths share the same 5-round
MAX_TOOL_ROUNDSlimit and{skillId}__{toolName}naming convention
6. Rust Agentic Loop in Detail
File: src-tauri/src/commands/chat.rs — chat_send_inner()
Step 1: Load OpenClaw context
→ load_openclaw_context(app)
→ reads ai/SOUL.md, IDENTITY.md, AGENTS.md, USER.md, BOOTSTRAP.md, MEMORY.md, TOOLS.md
→ cached in static AI_CONFIG_CACHE (cleared on restart)
→ truncated to MAX_CONTEXT_CHARS (20,000 chars)
Step 2: Recall memory context
→ MemoryClient::recall_skill_context("conversations", thread_id, 10)
→ tinyhumansai recall_memory(namespace="skill:conversations:{thread_id}")
→ returns synthesised summary string or None
Step 3: Build processed user message
processed = user_message
if openclaw_context → prepend as "## Project Context\n...\n\nUser message: {processed}"
if memory_context → prepend as "[MEMORY_CONTEXT]\n{mem}\n[/MEMORY_CONTEXT]\n\n{processed}"
if notion_context → prepend as "{notionContext}\n\n{processed}"
Step 4: Build messages array
→ history (ChatMessagePayload[]) + processed user message
Step 5: Discover tools
→ engine.all_tools()
→ returns all tools from running skills
→ namespaced: "{skill_id}__{tool_name}"
→ formatted as OpenAI function-calling schema
Step 6: Agentic loop (max 5 rounds)
for round in 0..MAX_TOOL_ROUNDS:
POST {backend_url}/openai/v1/chat/completions
body: { model, messages, tools, tool_choice: "auto" }
timeout: 120s
auth: Bearer {auth_token}
if finish_reason == "tool_calls":
emit chat:tool_call
engine.call_tool(skill_id, tool_name, args) // 60s timeout
→ QuickJS/V8 runtime executes skill JS tool handler
emit chat:tool_result
append tool result to messages
continue loop
else (finish_reason == "stop"):
emit chat:done { full_response, rounds_used, token_counts }
return Ok(())
7. Tool Execution: Rust → Skill JS
File: src-tauri/src/runtime/qjs_engine.rs — call_tool(skill_id, tool_name, args)
The Rust runtime routes call_tool into the running QuickJS/V8 skill instance:
- Serialises
argsas JSON - Calls the JS tool handler registered by the skill
- Returns
ToolCallResult { content: Vec<ToolContent>, is_error: bool } - Text content is extracted and appended as the
toolrole message in the loop
8. End-to-End Flow Summary
User types message (Conversations.tsx)
│
├─ [Web path only] invoke('recall_memory') → TinyHumans API (recall)
│ returns synthesised context
├─ buildNotionContext() → from Redux skillStates.notion
│
▼
invoke('chat_send') [Rust/desktop path]
│
▼
Rust: chat_send_inner()
├─ load_openclaw_context() → ai/*.md files (cached)
├─ recall_skill_context("conversations", tid) → TinyHumans API (recall)
├─ Build prompt: [OpenClaw] + [MEMORY] + [Notion] + user_message
├─ discover_tools() → all running skill tools
│
└─ Agentic loop (≤5 rounds):
POST /openai/v1/chat/completions → Backend LLM (neocortex-mk1)
│
├─ tool_calls → engine.call_tool() → QuickJS/V8 skill instance
│ └─ JS tool handler
│ └─ returns result string
│ └─ appended as tool message
│
└─ stop → emit chat:done
└─ Frontend: dispatch(addInferenceResponse(...))
Separately (async, fire-and-forget):
Skill onSync() / onOAuthComplete()
→ MemoryClient::store_skill_sync()
→ TinyHumans insert_memory (namespace: skill:{id}:{integrationId})
Key Files Reference
| File | Role |
|---|---|
src/providers/SkillProvider.tsx |
Discovery, lifecycle, Redux state sync |
src/pages/Conversations.tsx |
Message send, both code paths, Notion context |
src/services/chatService.ts |
chatSend(), chatCancel(), useRustChat() |
src-tauri/src/commands/chat.rs |
Rust agentic loop, context assembly, tool dispatch |
src-tauri/src/commands/memory.rs |
recall_memory Tauri command |
src-tauri/src/memory/mod.rs |
MemoryClient wrapping tinyhumansai SDK |
src-tauri/src/runtime/qjs_skill_instance.rs |
Skill sync → memory write triggers |
src-tauri/src/runtime/qjs_engine.rs |
discover_skills(), call_tool(), all_tools() |
skills/skills/*/manifest.json |
Skill metadata (git submodule) |