Skip to content

Commit 600dab4

Browse files
authored
refactor: migrate memory service to controller registry pattern (tinyhumansai#138)
Move all 23 memory RPC methods from legacy dispatch (src/rpc/dispatch.rs) to the controller registry pattern with typed schemas. - Create src/openhuman/memory/schemas.rs with 23 ControllerSchema definitions, RegisteredController entries, and handler functions - Wire memory controllers into src/core/all.rs registry builders - Remove all memory.* and ai.* branches from dispatch.rs (only security_policy_info remains) - Update frontend to use openhuman.memory_* method names directly in tauriCommands.ts (no legacy aliases needed) - Move ai.list_memory_files/read/write into memory namespace as openhuman.memory_list_files/read_file/write_file - Update jsonrpc.rs and tauriCommandsMemory test method strings Methods are now accessible via both JSON-RPC (openhuman.memory_*) and CLI (openhuman memory <function>).
1 parent e5e0922 commit 600dab4

7 files changed

Lines changed: 1112 additions & 278 deletions

File tree

‎app/src/utils/__tests__/tauriCommandsMemory.test.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe('memoryGraphQuery', () => {
4949
const result = await memoryGraphQuery('team', 'Alice', 'OWNS');
5050

5151
expect(mockCallCoreRpc).toHaveBeenCalledWith({
52-
method: 'memory.graph.query',
52+
method: 'openhuman.memory_graph_query',
5353
params: { namespace: 'team', subject: 'Alice', predicate: 'OWNS' },
5454
});
5555
expect(result).toEqual(mockRelations);
@@ -62,7 +62,7 @@ describe('memoryGraphQuery', () => {
6262
await memoryGraphQuery();
6363

6464
expect(mockCallCoreRpc).toHaveBeenCalledWith({
65-
method: 'memory.graph.query',
65+
method: 'openhuman.memory_graph_query',
6666
params: { namespace: undefined, subject: undefined, predicate: undefined },
6767
});
6868
});
@@ -100,7 +100,7 @@ describe('memoryDocIngest', () => {
100100

101101
const result = await memoryDocIngest(params);
102102

103-
expect(mockCallCoreRpc).toHaveBeenCalledWith({ method: 'memory.doc.ingest', params });
103+
expect(mockCallCoreRpc).toHaveBeenCalledWith({ method: 'openhuman.memory_doc_ingest', params });
104104
expect(result).toEqual(ingestResult);
105105
});
106106

@@ -111,6 +111,6 @@ describe('memoryDocIngest', () => {
111111
const params = { namespace: 'ns', key: 'k', title: 't', content: 'c' };
112112
await memoryDocIngest(params);
113113

114-
expect(mockCallCoreRpc).toHaveBeenCalledWith({ method: 'memory.doc.ingest', params });
114+
expect(mockCallCoreRpc).toHaveBeenCalledWith({ method: 'openhuman.memory_doc_ingest', params });
115115
});
116116
});

‎app/src/utils/tauriCommands.ts‎

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ export async function syncMemoryClientToken(token: string): Promise<void> {
199199
}
200200
try {
201201
console.debug('[memory] syncMemoryClientToken: payload → memory.init');
202-
await callCoreRpc<boolean>({ method: 'memory.init', params: { jwt_token: token } });
202+
await callCoreRpc<boolean>({ method: 'openhuman.memory_init', params: { jwt_token: token } });
203203
console.info('[memory] syncMemoryClientToken: exit — ok');
204204
} catch (err) {
205205
console.warn('[memory] syncMemoryClientToken: exit — error:', err);
@@ -217,14 +217,17 @@ export async function memoryListDocuments(namespace?: string): Promise<unknown>
217217
if (!isTauri()) {
218218
throw new Error('Not running in Tauri');
219219
}
220-
return await callCoreRpc<unknown>({ method: 'memory.list_documents', params: { namespace } });
220+
return await callCoreRpc<unknown>({
221+
method: 'openhuman.memory_list_documents',
222+
params: { namespace },
223+
});
221224
}
222225

223226
export async function memoryListNamespaces(): Promise<string[]> {
224227
if (!isTauri()) {
225228
throw new Error('Not running in Tauri');
226229
}
227-
return await callCoreRpc<string[]>({ method: 'memory.list_namespaces' });
230+
return await callCoreRpc<string[]>({ method: 'openhuman.memory_list_namespaces' });
228231
}
229232

230233
export async function memoryDeleteDocument(
@@ -235,7 +238,7 @@ export async function memoryDeleteDocument(
235238
throw new Error('Not running in Tauri');
236239
}
237240
return await callCoreRpc<unknown>({
238-
method: 'memory.delete_document',
241+
method: 'openhuman.memory_delete_document',
239242
params: { document_id: documentId, namespace },
240243
});
241244
}
@@ -249,7 +252,7 @@ export async function memoryQueryNamespace(
249252
throw new Error('Not running in Tauri');
250253
}
251254
return await callCoreRpc<string>({
252-
method: 'memory.query_namespace',
255+
method: 'openhuman.memory_query_namespace',
253256
params: { namespace, query, max_chunks: maxChunks },
254257
});
255258
}
@@ -262,7 +265,7 @@ export async function memoryRecallNamespace(
262265
throw new Error('Not running in Tauri');
263266
}
264267
return await callCoreRpc<string | null>({
265-
method: 'memory.recall_namespace',
268+
method: 'openhuman.memory_recall_context',
266269
params: { namespace, max_chunks: maxChunks },
267270
});
268271
}
@@ -289,7 +292,7 @@ export async function memoryGraphQuery(
289292
throw new Error('Not running in Tauri');
290293
}
291294
return await callCoreRpc<GraphRelation[]>({
292-
method: 'memory.graph.query',
295+
method: 'openhuman.memory_graph_query',
293296
params: { namespace, subject, predicate },
294297
});
295298
}
@@ -310,15 +313,15 @@ export async function memoryDocIngest(params: {
310313
if (!isTauri()) {
311314
throw new Error('Not running in Tauri');
312315
}
313-
return await callCoreRpc<unknown>({ method: 'memory.doc.ingest', params });
316+
return await callCoreRpc<unknown>({ method: 'openhuman.memory_doc_ingest', params });
314317
}
315318

316319
export async function aiListMemoryFiles(relativeDir = 'memory'): Promise<string[]> {
317320
if (!isTauri()) {
318321
throw new Error('Not running in Tauri');
319322
}
320323
return await callCoreRpc<string[]>({
321-
method: 'ai.list_memory_files',
324+
method: 'openhuman.memory_list_files',
322325
params: { relative_dir: relativeDir },
323326
});
324327
}
@@ -328,7 +331,7 @@ export async function aiReadMemoryFile(relativePath: string): Promise<string> {
328331
throw new Error('Not running in Tauri');
329332
}
330333
return await callCoreRpc<string>({
331-
method: 'ai.read_memory_file',
334+
method: 'openhuman.memory_read_file',
332335
params: { relative_path: relativePath },
333336
});
334337
}
@@ -338,7 +341,7 @@ export async function aiWriteMemoryFile(relativePath: string, content: string):
338341
throw new Error('Not running in Tauri');
339342
}
340343
await callCoreRpc<boolean>({
341-
method: 'ai.write_memory_file',
344+
method: 'openhuman.memory_write_file',
342345
params: { relative_path: relativePath, content },
343346
});
344347
}

‎src/core/all.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ fn build_registered_controllers() -> Vec<RegisteredController> {
6262
controllers.extend(crate::openhuman::skills::all_skills_registered_controllers());
6363
controllers.extend(crate::openhuman::workspace::all_workspace_registered_controllers());
6464
controllers.extend(crate::openhuman::tools::all_tools_registered_controllers());
65+
controllers.extend(crate::openhuman::memory::all_memory_registered_controllers());
6566
controllers
6667
}
6768

@@ -89,6 +90,7 @@ fn build_declared_controller_schemas() -> Vec<ControllerSchema> {
8990
schemas.extend(crate::openhuman::skills::all_skills_controller_schemas());
9091
schemas.extend(crate::openhuman::workspace::all_workspace_controller_schemas());
9192
schemas.extend(crate::openhuman::tools::all_tools_controller_schemas());
93+
schemas.extend(crate::openhuman::memory::all_memory_controller_schemas());
9294
schemas
9395
}
9496

@@ -122,6 +124,7 @@ pub fn namespace_description(namespace: &str) -> Option<&'static str> {
122124
"service" => Some("Desktop service lifecycle management."),
123125
"skills" => Some("Skill registry, runtime lifecycle, setup, tools, and sync."),
124126
"socket" => Some("Skills runtime socket bridge controls."),
127+
"memory" => Some("Document storage, vector search, key-value store, and knowledge graph."),
125128
_ => None,
126129
}
127130
}

‎src/core/jsonrpc.rs‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -478,46 +478,46 @@ mod tests {
478478

479479
#[tokio::test]
480480
async fn invoke_memory_init_missing_required_param_fails() {
481-
let err = invoke_method(default_state(), "memory.init", json!({}))
481+
let err = invoke_method(default_state(), "openhuman.memory_init", json!({}))
482482
.await
483483
.expect_err("missing jwt_token should fail");
484-
assert!(err.contains("missing field `jwt_token`") || err.contains("jwt_token"));
484+
assert!(err.contains("jwt_token"));
485485
}
486486

487487
#[tokio::test]
488488
async fn invoke_memory_list_namespaces_rejects_unknown_param() {
489489
let err = invoke_method(
490490
default_state(),
491-
"memory.list_namespaces",
491+
"openhuman.memory_list_namespaces",
492492
json!({ "extra": true }),
493493
)
494494
.await
495495
.expect_err("unknown param should fail");
496-
assert!(err.contains("unknown field `extra`") || err.contains("extra"));
496+
assert!(err.contains("extra"));
497497
}
498498

499499
#[tokio::test]
500500
async fn invoke_memory_query_namespace_missing_namespace_fails() {
501501
let err = invoke_method(
502502
default_state(),
503-
"memory.query_namespace",
503+
"openhuman.memory_query_namespace",
504504
json!({ "query": "who owns atlas" }),
505505
)
506506
.await
507507
.expect_err("missing namespace should fail");
508-
assert!(err.contains("missing field `namespace`") || err.contains("namespace"));
508+
assert!(err.contains("namespace"));
509509
}
510510

511511
#[tokio::test]
512512
async fn invoke_memory_recall_memories_rejects_unknown_param() {
513513
let err = invoke_method(
514514
default_state(),
515-
"memory.recall_memories",
515+
"openhuman.memory_recall_memories",
516516
json!({ "namespace": "team", "extra": true }),
517517
)
518518
.await
519519
.expect_err("unknown param should fail");
520-
assert!(err.contains("unknown field `extra`") || err.contains("extra"));
520+
assert!(err.contains("extra"));
521521
}
522522

523523
#[tokio::test]

‎src/openhuman/memory/mod.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod ingestion;
44
pub mod ops;
55
pub(crate) mod relex;
66
pub mod rpc_models;
7+
pub mod schemas;
78
pub mod store;
89
pub mod traits;
910

@@ -14,6 +15,10 @@ pub use ingestion::{
1415
pub use ops as rpc;
1516
pub use ops::*;
1617
pub use rpc_models::*;
18+
pub use schemas::{
19+
all_controller_schemas as all_memory_controller_schemas,
20+
all_registered_controllers as all_memory_registered_controllers,
21+
};
1722
pub use store::{
1823
create_memory, create_memory_for_migration, create_memory_with_storage,
1924
create_memory_with_storage_and_routes, effective_memory_backend_name, MemoryClient,

0 commit comments

Comments
 (0)