mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-30 23:14:37 +00:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openhuman",
|
||||
"version": "0.49.11",
|
||||
"version": "0.49.12",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -5,11 +5,3 @@
|
||||
# Generated by Tauri
|
||||
# will have schema files for capabilities auto-completion
|
||||
/gen/schemas
|
||||
|
||||
# TDLib and dependencies copied by build.rs for macOS bundling
|
||||
/libraries/
|
||||
|
||||
# TDLib built from source (see scripts/build-tdlib-from-source.sh)
|
||||
/tdlib-local/
|
||||
/tdlib-build/
|
||||
/tdlib-cache/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "OpenHuman"
|
||||
version = "0.49.11"
|
||||
version = "0.49.12"
|
||||
description = "OpenHuman - AI-powered Super Assistant"
|
||||
authors = ["OpenHuman"]
|
||||
edition = "2021"
|
||||
|
||||
+1
-17
@@ -1,5 +1,4 @@
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
maybe_override_tauri_config_for_local_builds();
|
||||
@@ -9,13 +8,8 @@ fn main() {
|
||||
fn maybe_override_tauri_config_for_local_builds() {
|
||||
let profile = env::var("PROFILE").unwrap_or_default();
|
||||
let skip_resources = env::var("TAURI_SKIP_RESOURCES").is_ok() || profile == "test";
|
||||
let is_release = profile == "release";
|
||||
let manifest_dir =
|
||||
PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"));
|
||||
let tdlib_framework_path = manifest_dir.join("libraries/libtdjson.1.8.29.dylib");
|
||||
let skip_missing_frameworks = !is_release && !tdlib_framework_path.exists();
|
||||
|
||||
if !skip_resources && !skip_missing_frameworks {
|
||||
if !skip_resources {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,9 +17,6 @@ fn maybe_override_tauri_config_for_local_builds() {
|
||||
if skip_resources {
|
||||
merge_config["bundle"]["resources"] = serde_json::json!([]);
|
||||
}
|
||||
if skip_missing_frameworks {
|
||||
merge_config["bundle"]["macOS"]["frameworks"] = serde_json::json!([]);
|
||||
}
|
||||
|
||||
match serde_json::to_string(&merge_config) {
|
||||
Ok(json) => {
|
||||
@@ -33,16 +24,9 @@ fn maybe_override_tauri_config_for_local_builds() {
|
||||
if skip_resources {
|
||||
println!("cargo:warning=TAURI resources disabled for local build");
|
||||
}
|
||||
if skip_missing_frameworks {
|
||||
println!(
|
||||
"cargo:warning=TAURI macOS frameworks disabled because {} is missing",
|
||||
tdlib_framework_path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("cargo:warning=Failed to serialize TAURI_CONFIG override: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1242,8 +1242,7 @@ pub fn run() {
|
||||
}
|
||||
}
|
||||
|
||||
// Gracefully shut down TDLib before process exit to prevent
|
||||
// use-after-free crash in the blocking receive loop.
|
||||
// Gracefully shut down background services before process exit.
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
RunEvent::Exit => {
|
||||
log::info!("[app] Exit event received, shutting down");
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::runtime::skill_registry::SkillRegistry;
|
||||
use crate::runtime::socket_manager::SocketManager;
|
||||
use crate::runtime::types::{events, SkillMessage, SkillSnapshot, SkillStatus, ToolResult};
|
||||
use crate::runtime::qjs_skill_instance::{BridgeDeps, QjsSkillInstance};
|
||||
// IdbStorage removed with TDLib cleanup
|
||||
// IdbStorage removed during runtime cleanup
|
||||
|
||||
/// The central runtime engine using QuickJS.
|
||||
pub struct RuntimeEngine {
|
||||
@@ -463,20 +463,20 @@ impl RuntimeEngine {
|
||||
}
|
||||
|
||||
/// Read a KV value from a skill's database.
|
||||
/// TODO: Removed with TDLib cleanup - reimplement if needed
|
||||
/// TODO: Removed during runtime cleanup - reimplement if needed
|
||||
pub fn kv_get(&self, _skill_id: &str, _key: &str) -> Result<serde_json::Value, String> {
|
||||
Err("KV storage removed with TDLib cleanup".to_string())
|
||||
Err("KV storage removed during runtime cleanup".to_string())
|
||||
}
|
||||
|
||||
/// Write a KV value into a skill's database.
|
||||
/// TODO: Removed with TDLib cleanup - reimplement if needed
|
||||
/// TODO: Removed during runtime cleanup - reimplement if needed
|
||||
pub fn kv_set(
|
||||
&self,
|
||||
_skill_id: &str,
|
||||
_key: &str,
|
||||
_value: &serde_json::Value,
|
||||
) -> Result<(), String> {
|
||||
Err("KV storage removed with TDLib cleanup".to_string())
|
||||
Err("KV storage removed during runtime cleanup".to_string())
|
||||
}
|
||||
|
||||
/// Route a JSON-RPC method call.
|
||||
|
||||
+2
-70
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Bootstrap JavaScript for QuickJS Runtime
|
||||
*
|
||||
* Provides browser-like API shims that tdweb expects.
|
||||
* Provides browser-like API shims for skill execution.
|
||||
* These shims call Rust "ops" for actual I/O.
|
||||
*/
|
||||
|
||||
@@ -343,7 +343,7 @@ WebSocket._instances = new Map();
|
||||
globalThis.WebSocket = WebSocket;
|
||||
|
||||
// ============================================================================
|
||||
// IndexedDB API (for tdweb persistence)
|
||||
// IndexedDB API (persistent local storage)
|
||||
// ============================================================================
|
||||
class IDBFactory {
|
||||
open(name, version = 1) {
|
||||
@@ -940,74 +940,6 @@ globalThis.skills = {
|
||||
},
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// TDLib Bridge API (telegram skill only)
|
||||
// ============================================================================
|
||||
// Provides native TDLib access for the telegram skill.
|
||||
// This is only available on desktop - Android uses Tauri invoke() instead.
|
||||
|
||||
globalThis.tdlib = {
|
||||
/**
|
||||
* Check if TDLib ops are available.
|
||||
* @returns {boolean} True on desktop, false on mobile/web.
|
||||
*/
|
||||
isAvailable: function () {
|
||||
try {
|
||||
return typeof __ops?.tdlib_is_available === 'function'
|
||||
? __ops.tdlib_is_available()
|
||||
: false;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create client and set TDLib parameters in a single atomic call.
|
||||
* API credentials are stored on the Rust side only.
|
||||
* @param {string} dataDir - Path to store TDLib data files.
|
||||
* @returns {Promise<number>} Client ID.
|
||||
*/
|
||||
ensureInitialized: async function (dataDir) {
|
||||
return await __ops.tdlib_ensure_initialized(dataDir);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a TDLib client with the given data directory.
|
||||
* @param {string} dataDir - Path to store TDLib data files.
|
||||
* @returns {Promise<number>} Client ID (always 1 for singleton).
|
||||
*/
|
||||
createClient: function (dataDir) {
|
||||
return __ops.tdlib_create_client(dataDir);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a TDLib request and wait for the response.
|
||||
* @param {string} requestJson - JSON-serialized TDLib API request with @type field.
|
||||
* @returns {Promise<string>} JSON-serialized TDLib response.
|
||||
*/
|
||||
send: async function (requestJson) {
|
||||
return await __ops.tdlib_send(requestJson);
|
||||
},
|
||||
|
||||
/**
|
||||
* Receive the next TDLib update (with timeout).
|
||||
* @param {number} [timeoutMs=1000] - Timeout in milliseconds.
|
||||
* @returns {Promise<object|null>} Update object or null if timeout.
|
||||
*/
|
||||
receive: async function (timeoutMs = 1000) {
|
||||
const resultJson = await __ops.tdlib_receive(timeoutMs);
|
||||
return resultJson ? JSON.parse(resultJson) : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the TDLib client and clean up resources.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
destroy: async function () {
|
||||
return await __ops.tdlib_destroy();
|
||||
},
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Model Bridge API (routes to cloud backend)
|
||||
// ============================================================================
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
//! TDLib Runtime Module
|
||||
//! QuickJS Runtime Support Module
|
||||
//!
|
||||
//! Provides a QuickJS JavaScript runtime (via rquickjs) for running
|
||||
//! skill JavaScript code and TDLib integration. Provides a browser-like
|
||||
//! skill JavaScript code and supporting browser-like shims.
|
||||
//! environment for skill execution.
|
||||
|
||||
pub mod qjs_ops;
|
||||
pub mod service;
|
||||
pub mod storage;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub use service::{TdClientAdapter, TdClientConfig, TdUpdate, TdlibV8Service};
|
||||
pub use storage::IdbStorage;
|
||||
|
||||
@@ -1,457 +0,0 @@
|
||||
//! TdlibV8Service — High-level TDLib service using V8 runtime.
|
||||
//!
|
||||
//! Manages TDLib client instances running in V8 with tdweb.
|
||||
//! Provides async send/receive interface and update broadcasting.
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::{broadcast, mpsc, oneshot};
|
||||
|
||||
use super::storage::IdbStorage;
|
||||
|
||||
/// Configuration for a TDLib client.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
pub struct TdClientConfig {
|
||||
/// API ID from my.telegram.org
|
||||
pub api_id: i32,
|
||||
/// API hash from my.telegram.org
|
||||
pub api_hash: String,
|
||||
/// Database directory name
|
||||
pub database_directory: String,
|
||||
/// Files directory name
|
||||
pub files_directory: String,
|
||||
/// Use test DC
|
||||
#[serde(default)]
|
||||
pub use_test_dc: bool,
|
||||
/// Use file database
|
||||
#[serde(default = "default_true")]
|
||||
pub use_file_database: bool,
|
||||
/// Use chat info database
|
||||
#[serde(default = "default_true")]
|
||||
pub use_chat_info_database: bool,
|
||||
/// Use message database
|
||||
#[serde(default = "default_true")]
|
||||
pub use_message_database: bool,
|
||||
/// System language code
|
||||
#[serde(default = "default_lang")]
|
||||
pub system_language_code: String,
|
||||
/// Device model
|
||||
#[serde(default = "default_device")]
|
||||
pub device_model: String,
|
||||
/// Application version
|
||||
#[serde(default = "default_version")]
|
||||
pub application_version: String,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn default_true() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn default_lang() -> String {
|
||||
"en".to_string()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn default_device() -> String {
|
||||
"Desktop".to_string()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn default_version() -> String {
|
||||
"1.0.0".to_string()
|
||||
}
|
||||
|
||||
impl Default for TdClientConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
api_id: 0,
|
||||
api_hash: String::new(),
|
||||
database_directory: "tdlib".to_string(),
|
||||
files_directory: "tdlib_files".to_string(),
|
||||
use_test_dc: false,
|
||||
use_file_database: true,
|
||||
use_chat_info_database: true,
|
||||
use_message_database: true,
|
||||
system_language_code: "en".to_string(),
|
||||
device_model: "Desktop".to_string(),
|
||||
application_version: "1.0.0".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A TDLib update received from the server.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
pub struct TdUpdate {
|
||||
/// The update type (e.g., "updateNewMessage")
|
||||
#[serde(rename = "@type")]
|
||||
pub update_type: String,
|
||||
/// The full update data
|
||||
#[serde(flatten)]
|
||||
pub data: serde_json::Value,
|
||||
}
|
||||
|
||||
/// Messages sent to the TDLib service.
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum TdServiceMessage {
|
||||
/// Send a TDLib query
|
||||
Send {
|
||||
user_id: String,
|
||||
query: serde_json::Value,
|
||||
reply: oneshot::Sender<Result<serde_json::Value, String>>,
|
||||
},
|
||||
/// Get current auth state
|
||||
GetAuthState {
|
||||
user_id: String,
|
||||
reply: oneshot::Sender<Result<serde_json::Value, String>>,
|
||||
},
|
||||
/// Create a new client
|
||||
CreateClient {
|
||||
user_id: String,
|
||||
config: TdClientConfig,
|
||||
reply: oneshot::Sender<Result<(), String>>,
|
||||
},
|
||||
/// Destroy a client
|
||||
DestroyClient {
|
||||
user_id: String,
|
||||
reply: oneshot::Sender<Result<(), String>>,
|
||||
},
|
||||
/// Stop the service
|
||||
Stop,
|
||||
}
|
||||
|
||||
/// State for a single TDLib client.
|
||||
#[allow(dead_code)]
|
||||
struct TdClientState {
|
||||
/// Current authorization state
|
||||
auth_state: serde_json::Value,
|
||||
/// Whether the client is ready
|
||||
is_ready: bool,
|
||||
}
|
||||
|
||||
/// TDLib V8 Service that manages TDLib clients.
|
||||
#[allow(dead_code)]
|
||||
pub struct TdlibV8Service {
|
||||
/// Data directory for TDLib databases
|
||||
data_dir: PathBuf,
|
||||
/// Storage layer for IndexedDB emulation
|
||||
storage: IdbStorage,
|
||||
/// Message sender for the service
|
||||
tx: mpsc::Sender<TdServiceMessage>,
|
||||
/// Update broadcaster
|
||||
update_tx: broadcast::Sender<(String, TdUpdate)>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl TdlibV8Service {
|
||||
/// Create a new TDLib V8 service.
|
||||
pub async fn new(data_dir: PathBuf) -> Result<Self, String> {
|
||||
let storage = IdbStorage::new(&data_dir)?;
|
||||
let (tx, _rx) = mpsc::channel(64);
|
||||
let (update_tx, _) = broadcast::channel(256);
|
||||
|
||||
let service = Self {
|
||||
data_dir,
|
||||
storage,
|
||||
tx,
|
||||
update_tx,
|
||||
};
|
||||
|
||||
Ok(service)
|
||||
}
|
||||
|
||||
/// Get a sender for the service.
|
||||
pub fn sender(&self) -> mpsc::Sender<TdServiceMessage> {
|
||||
self.tx.clone()
|
||||
}
|
||||
|
||||
/// Subscribe to TDLib updates.
|
||||
/// Returns a receiver that will receive (user_id, update) tuples.
|
||||
pub fn subscribe(&self) -> broadcast::Receiver<(String, TdUpdate)> {
|
||||
self.update_tx.subscribe()
|
||||
}
|
||||
|
||||
/// Send a query to TDLib.
|
||||
pub async fn send(
|
||||
&self,
|
||||
user_id: &str,
|
||||
query: serde_json::Value,
|
||||
) -> Result<serde_json::Value, String> {
|
||||
let (reply_tx, reply_rx) = oneshot::channel();
|
||||
|
||||
self.tx
|
||||
.send(TdServiceMessage::Send {
|
||||
user_id: user_id.to_string(),
|
||||
query,
|
||||
reply: reply_tx,
|
||||
})
|
||||
.await
|
||||
.map_err(|e| format!("Failed to send query: {e}"))?;
|
||||
|
||||
reply_rx
|
||||
.await
|
||||
.map_err(|_| "Service did not respond".to_string())?
|
||||
}
|
||||
|
||||
/// Get the current authorization state.
|
||||
pub async fn get_auth_state(&self, user_id: &str) -> Result<serde_json::Value, String> {
|
||||
let (reply_tx, reply_rx) = oneshot::channel();
|
||||
|
||||
self.tx
|
||||
.send(TdServiceMessage::GetAuthState {
|
||||
user_id: user_id.to_string(),
|
||||
reply: reply_tx,
|
||||
})
|
||||
.await
|
||||
.map_err(|e| format!("Failed to get auth state: {e}"))?;
|
||||
|
||||
reply_rx
|
||||
.await
|
||||
.map_err(|_| "Service did not respond".to_string())?
|
||||
}
|
||||
|
||||
/// Create a new TDLib client for a user.
|
||||
pub async fn create_client(
|
||||
&self,
|
||||
user_id: &str,
|
||||
config: TdClientConfig,
|
||||
) -> Result<(), String> {
|
||||
let (reply_tx, reply_rx) = oneshot::channel();
|
||||
|
||||
self.tx
|
||||
.send(TdServiceMessage::CreateClient {
|
||||
user_id: user_id.to_string(),
|
||||
config,
|
||||
reply: reply_tx,
|
||||
})
|
||||
.await
|
||||
.map_err(|e| format!("Failed to create client: {e}"))?;
|
||||
|
||||
reply_rx
|
||||
.await
|
||||
.map_err(|_| "Service did not respond".to_string())?
|
||||
}
|
||||
|
||||
/// Destroy a TDLib client.
|
||||
pub async fn destroy_client(&self, user_id: &str) -> Result<(), String> {
|
||||
let (reply_tx, reply_rx) = oneshot::channel();
|
||||
|
||||
self.tx
|
||||
.send(TdServiceMessage::DestroyClient {
|
||||
user_id: user_id.to_string(),
|
||||
reply: reply_tx,
|
||||
})
|
||||
.await
|
||||
.map_err(|e| format!("Failed to destroy client: {e}"))?;
|
||||
|
||||
reply_rx
|
||||
.await
|
||||
.map_err(|_| "Service did not respond".to_string())?
|
||||
}
|
||||
}
|
||||
|
||||
/// TDLib client adapter that wraps a V8 runtime.
|
||||
///
|
||||
/// This is a placeholder for the full tdweb integration.
|
||||
/// In the full implementation, this would:
|
||||
/// 1. Load the tdweb JavaScript bundle
|
||||
/// 2. Initialize TdClient with the WASM module
|
||||
/// 3. Handle send/receive through the V8 runtime
|
||||
#[allow(dead_code)]
|
||||
pub struct TdClientAdapter {
|
||||
user_id: String,
|
||||
config: TdClientConfig,
|
||||
data_dir: PathBuf,
|
||||
storage: IdbStorage,
|
||||
auth_state: serde_json::Value,
|
||||
query_id: u64,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl TdClientAdapter {
|
||||
/// Create a new TDLib client adapter.
|
||||
pub fn new(
|
||||
user_id: String,
|
||||
config: TdClientConfig,
|
||||
data_dir: PathBuf,
|
||||
storage: IdbStorage,
|
||||
) -> Self {
|
||||
Self {
|
||||
user_id,
|
||||
config,
|
||||
data_dir,
|
||||
storage,
|
||||
auth_state: serde_json::json!({
|
||||
"@type": "authorizationStateWaitTdlibParameters"
|
||||
}),
|
||||
query_id: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize the TDLib client.
|
||||
///
|
||||
/// This would load the tdweb bundle and initialize the WASM module.
|
||||
pub async fn init(&mut self) -> Result<(), String> {
|
||||
log::info!("[tdlib:{}] Initializing TDLib client", self.user_id);
|
||||
|
||||
// TODO: Load tdweb.js and libtdjson.wasm
|
||||
// TODO: Create TdClient instance in V8
|
||||
// TODO: Set up update handlers
|
||||
|
||||
// For now, simulate initialization
|
||||
self.auth_state = serde_json::json!({
|
||||
"@type": "authorizationStateWaitTdlibParameters"
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Send a query to TDLib.
|
||||
pub async fn send(&mut self, query: serde_json::Value) -> Result<serde_json::Value, String> {
|
||||
self.query_id += 1;
|
||||
let query_id = self.query_id;
|
||||
|
||||
log::debug!(
|
||||
"[tdlib:{}] Sending query {}: {:?}",
|
||||
self.user_id,
|
||||
query_id,
|
||||
query.get("@type")
|
||||
);
|
||||
|
||||
// TODO: Execute query through V8/tdweb
|
||||
// For now, return a placeholder response
|
||||
|
||||
let query_type = query
|
||||
.get("@type")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("unknown");
|
||||
|
||||
match query_type {
|
||||
"getAuthorizationState" => Ok(self.auth_state.clone()),
|
||||
"setTdlibParameters" => {
|
||||
self.auth_state = serde_json::json!({
|
||||
"@type": "authorizationStateWaitPhoneNumber"
|
||||
});
|
||||
Ok(serde_json::json!({ "@type": "ok" }))
|
||||
}
|
||||
_ => Ok(serde_json::json!({
|
||||
"@type": "error",
|
||||
"code": 400,
|
||||
"message": "TDLib not fully initialized - tdweb integration pending"
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current authorization state.
|
||||
pub fn get_auth_state(&self) -> serde_json::Value {
|
||||
self.auth_state.clone()
|
||||
}
|
||||
|
||||
/// Destroy the client.
|
||||
pub async fn destroy(&mut self) -> Result<(), String> {
|
||||
log::info!("[tdlib:{}] Destroying TDLib client", self.user_id);
|
||||
|
||||
// TODO: Properly close TDLib client
|
||||
// TODO: Cleanup V8 runtime
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// JavaScript code to initialize the TDLib bridge in V8.
|
||||
///
|
||||
/// This provides the `__tdlib_send` and `__tdlib_get_auth_state` functions
|
||||
/// that the bootstrap.js exposes to skills.
|
||||
#[allow(dead_code)]
|
||||
pub const TDLIB_BRIDGE_JS: &str = r#"
|
||||
// TDLib Bridge for V8 Runtime
|
||||
// This will be replaced with actual tdweb integration
|
||||
|
||||
(function() {
|
||||
// Client state
|
||||
const clients = new Map();
|
||||
let defaultClient = null;
|
||||
|
||||
// Create a mock client for now
|
||||
class MockTdClient {
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
this.authState = { '@type': 'authorizationStateWaitTdlibParameters' };
|
||||
this.queryId = 0;
|
||||
this.callbacks = new Map();
|
||||
}
|
||||
|
||||
async send(query) {
|
||||
this.queryId++;
|
||||
const queryType = query['@type'];
|
||||
|
||||
console.log('[TDLib] Send:', queryType);
|
||||
|
||||
// Handle known query types
|
||||
switch (queryType) {
|
||||
case 'getAuthorizationState':
|
||||
return this.authState;
|
||||
|
||||
case 'setTdlibParameters':
|
||||
this.authState = { '@type': 'authorizationStateWaitPhoneNumber' };
|
||||
return { '@type': 'ok' };
|
||||
|
||||
case 'setAuthenticationPhoneNumber':
|
||||
this.authState = { '@type': 'authorizationStateWaitCode' };
|
||||
return { '@type': 'ok' };
|
||||
|
||||
default:
|
||||
return {
|
||||
'@type': 'error',
|
||||
'code': 400,
|
||||
'message': 'TDLib not fully initialized - waiting for tdweb integration'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getAuthState() {
|
||||
return this.authState;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize default client
|
||||
function initClient(userId, options) {
|
||||
const client = new MockTdClient(options);
|
||||
clients.set(userId, client);
|
||||
if (!defaultClient) {
|
||||
defaultClient = client;
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
// Get or create client
|
||||
function getClient(userId) {
|
||||
if (!clients.has(userId)) {
|
||||
initClient(userId, {});
|
||||
}
|
||||
return clients.get(userId);
|
||||
}
|
||||
|
||||
// Export to global scope
|
||||
globalThis.__tdlib_send = async function(userId, query) {
|
||||
const client = getClient(userId);
|
||||
return await client.send(query);
|
||||
};
|
||||
|
||||
globalThis.__tdlib_get_auth_state = function(userId) {
|
||||
const client = getClient(userId);
|
||||
return client.getAuthState();
|
||||
};
|
||||
|
||||
globalThis.__tdlib_init = function(userId, options) {
|
||||
return initClient(userId, options);
|
||||
};
|
||||
|
||||
console.log('[TDLib] Bridge initialized (mock mode)');
|
||||
})();
|
||||
"#;
|
||||
@@ -1,7 +1,7 @@
|
||||
//! IndexedDB Storage Layer (SQLite-backed)
|
||||
//!
|
||||
//! Provides persistent storage for:
|
||||
//! - IndexedDB API (for tdweb)
|
||||
//! - IndexedDB API
|
||||
//! - Skill databases (db bridge)
|
||||
//! - Skill key-value store (store bridge)
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Result of opening an IndexedDB database.
|
||||
/// Used by the IndexedDB emulation layer for tdweb.
|
||||
/// Used by the IndexedDB emulation layer.
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
pub struct IdbOpenResult {
|
||||
/// Whether a version upgrade is needed.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "OpenHuman",
|
||||
"version": "0.49.11",
|
||||
"version": "0.49.12",
|
||||
"identifier": "com.tinyhumansai.openhuman",
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ const AppRoutes = () => {
|
||||
path="/conversations/:threadId"
|
||||
element={
|
||||
<ProtectedRoute requireAuth={true}>
|
||||
<Conversations />
|
||||
<Navigate to="/conversations" replace />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
|
||||
+438
-784
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,9 @@ export interface ChatCompletionRequest {
|
||||
messages: ChatMessage[];
|
||||
tools?: Tool[];
|
||||
tool_choice?: 'auto' | 'none' | { type: 'function'; function: { name: string } };
|
||||
openhuman?: {
|
||||
trace_tools?: boolean;
|
||||
};
|
||||
stream?: boolean;
|
||||
temperature?: number;
|
||||
max_tokens?: number;
|
||||
|
||||
Reference in New Issue
Block a user