-
Notifications
You must be signed in to change notification settings - Fork 0
Phase 4 complete: IToolRegistry AIDL + wire into RagService #1
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package android.rag; | ||
|
|
||
| /** | ||
| * Public Binder interface for the JarvisOS Tool Registry. | ||
| * | ||
| * Published as service name "jarvis_tools" from RagService. | ||
| * Apps use this to inspect what tools are registered on the device. | ||
| * | ||
| * Return value contract: | ||
| * - listTools() / searchTools() return "[]" when store is not ready or no results. | ||
| * - getTool(id) returns null when not found or store is not ready. | ||
| * - All other failures return "[]" (list methods) or null (single-item methods). | ||
| * | ||
| * Note: listTools() returns the full registry in one Binder call. This is fine | ||
| * for small registries but risks TransactionTooLargeException at scale. | ||
| * Pagination (offset/limit) will be added in a future phase. | ||
| */ | ||
| interface IToolRegistry { | ||
|
|
||
| /** | ||
| * Returns a JSON array of all registered tools, or "[]" if none / not ready. | ||
| * Each element is a tool object: | ||
| * {id, toolName, description, paramsJson, rawDefinition, receiverClass, | ||
| * cactusIndexId, app:{id, packageName, appLabel, sourceType}} | ||
| * | ||
| * Note: paramsJson is itself a JSON-encoded string, not an embedded JSON object. | ||
| */ | ||
| String listTools(); | ||
|
|
||
| /** | ||
| * Returns the JSON object for a single tool by its ObjectBox id. | ||
| * Returns null if not found. | ||
| */ | ||
| String getTool(long id); | ||
|
|
||
| /** | ||
| * Semantic + metadata search over registered tools. | ||
| * Returns a JSON array of matching tools (up to TOP_K), ordered by relevance. | ||
| * Uses Cactus HNSW if available, falls back to keyword match. | ||
| */ | ||
| String searchTools(String query); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |||||
| import android.os.Binder; | ||||||
| import android.os.Environment; | ||||||
| import android.app.rag.IRagService; | ||||||
| import android.rag.IToolRegistry; | ||||||
| import android.util.Log; | ||||||
|
|
||||||
| import com.android.server.SystemService; | ||||||
|
|
@@ -14,6 +15,7 @@ | |||||
| import com.android.server.rag.indexing.RagIndexWorker; | ||||||
| import com.android.server.rag.model.SourceFile; | ||||||
| import com.android.server.rag.tools.ToolDispatcher; | ||||||
| import com.android.server.rag.tools.ToolRecord; | ||||||
| import com.android.server.rag.tools.ToolScannerService; | ||||||
|
|
||||||
| /** | ||||||
|
|
@@ -59,6 +61,7 @@ public RagService(Context context) { | |||||
| @Override | ||||||
| public void onStart() { | ||||||
| publishBinderService("rag", mBinder); | ||||||
| publishBinderService("jarvis_tools", mToolRegistryBinder); | ||||||
|
||||||
| publishBinderService("jarvis_tools", mToolRegistryBinder); | |
| Log.w(TAG, "Not publishing jarvis_tools Binder service: caller permission enforcement is not implemented"); |
Copilot
AI
Apr 5, 2026
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.
Binder transactions have a hard size limit (~1MB). Returning all tools as one JSON string (and including potentially large fields like rawDefinition/paramsJson) risks TransactionTooLargeException as the registry grows. Consider adding paging (offset/limit), a lightweight summary listing, and/or omitting large fields from listTools() results.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -343,6 +343,68 @@ protected void onReceiveResult(int resultCode, Bundle resultData) { | |
| return result; | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| // Public search API (used by IToolRegistry) | ||
| // ------------------------------------------------------------------------- | ||
|
|
||
| /** | ||
| * Search for tools matching the query without dispatching. | ||
| * Returns a JSON array string (never null; returns "[]" on empty/failure). | ||
| */ | ||
| public String searchTools(String query) { | ||
| if (query == null || query.trim().isEmpty()) return "[]"; | ||
| List<ToolRecord> results = semanticSearch(query); | ||
| return serializeTools(results); | ||
| } | ||
|
Comment on lines
+350
to
+358
|
||
|
|
||
| /** | ||
| * Serialize a single ToolRecord to a JSONObject. | ||
| * Returns null if tool is null or serialization fails. | ||
| */ | ||
| public static JSONObject serializeToolObject(ToolRecord tool) { | ||
| if (tool == null) return null; | ||
| try { | ||
| JSONObject obj = new JSONObject(); | ||
| obj.put("id", tool.id); | ||
| obj.put("toolName", tool.toolName != null ? tool.toolName : ""); | ||
| obj.put("description", tool.description != null ? tool.description : ""); | ||
| obj.put("paramsJson", tool.paramsJson != null ? tool.paramsJson : ""); | ||
| obj.put("rawDefinition", tool.rawDefinition != null ? tool.rawDefinition : ""); | ||
| obj.put("receiverClass", tool.receiverClass != null ? tool.receiverClass : ""); | ||
| obj.put("cactusIndexId", tool.cactusIndexId); | ||
|
|
||
| AppRecord app = tool.app.getTarget(); | ||
| if (app != null) { | ||
| JSONObject appObj = new JSONObject(); | ||
| appObj.put("id", app.id); | ||
| appObj.put("packageName", app.packageName != null ? app.packageName : ""); | ||
| appObj.put("appLabel", app.appLabel != null ? app.appLabel : ""); | ||
| appObj.put("sourceType", app.sourceType != null ? app.sourceType : ""); | ||
| obj.put("app", appObj); | ||
| } | ||
| return obj; | ||
| } catch (JSONException e) { | ||
| Log.e(TAG, "serializeToolObject failed for: " + tool.toolName, e); | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| /** Serialize a single ToolRecord to a JSON string, or null on failure. */ | ||
| public static String serializeTool(ToolRecord tool) { | ||
| JSONObject obj = serializeToolObject(tool); | ||
| return obj != null ? obj.toString() : null; | ||
| } | ||
|
|
||
| /** Serialize a list of ToolRecords to a JSON array string. */ | ||
| public static String serializeTools(List<ToolRecord> tools) { | ||
| JSONArray arr = new JSONArray(); | ||
| for (ToolRecord t : tools) { | ||
| JSONObject obj = serializeToolObject(t); | ||
| if (obj != null) arr.put(obj); | ||
| } | ||
|
Comment on lines
+398
to
+404
|
||
| return arr.toString(); | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| // Internal data class | ||
| // ------------------------------------------------------------------------- | ||
|
|
||
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 AIDL docs say "All return values are JSON strings. Null = not found / store not ready", but
listTools()/searchTools()are implemented to return "[]" when the store isn't ready or the query is empty. Please align the documentation with the actual contract (or change the implementation to match the docs).