mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-03 09:17:09 +08:00
feat: add workspace foundation and search tooling
This commit is contained in:
111
tools/workspace_tool.py
Normal file
111
tools/workspace_tool.py
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Workspace tool — inspect and search the Hermes workspace."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from agent.workspace import build_workspace_manifest, workspace_list, workspace_search, workspace_status
|
||||
from hermes_cli.config import load_config
|
||||
from tools.registry import registry
|
||||
|
||||
|
||||
WORKSPACE_SCHEMA = {
|
||||
"name": "workspace",
|
||||
"description": "Manage the Hermes workspace under HERMES_HOME. Use this to inspect workspace status, rebuild the workspace manifest, list files, or search within workspace documents without relying on the terminal environment.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["status", "index", "list", "search"],
|
||||
"description": "What to do: status shows roots and counts, index rebuilds the manifest, list enumerates files, search searches text content.",
|
||||
},
|
||||
"query": {
|
||||
"type": "string",
|
||||
"description": "Regex query to search for when action='search'.",
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Optional subpath within the workspace to scope list/search operations.",
|
||||
},
|
||||
"file_glob": {
|
||||
"type": "string",
|
||||
"description": "Optional filename glob filter for search, e.g. '*.md'.",
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Maximum number of entries or matches to return.",
|
||||
"default": 20,
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"description": "Skip the first N entries or matches.",
|
||||
"default": 0,
|
||||
},
|
||||
"recursive": {
|
||||
"type": "boolean",
|
||||
"description": "When action='list', recurse through subdirectories (default true).",
|
||||
"default": True,
|
||||
},
|
||||
},
|
||||
"required": ["action"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def workspace_tool(
|
||||
action: str,
|
||||
query: str = "",
|
||||
path: str = "",
|
||||
file_glob: str | None = None,
|
||||
limit: int = 20,
|
||||
offset: int = 0,
|
||||
recursive: bool = True,
|
||||
) -> str:
|
||||
try:
|
||||
config = load_config()
|
||||
if action == "status":
|
||||
result: dict[str, Any] = workspace_status(config)
|
||||
elif action == "index":
|
||||
result = build_workspace_manifest(config)
|
||||
elif action == "list":
|
||||
result = workspace_list(
|
||||
config=config,
|
||||
relative_path=path,
|
||||
recursive=recursive,
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
)
|
||||
elif action == "search":
|
||||
result = workspace_search(
|
||||
query=query,
|
||||
config=config,
|
||||
relative_path=path,
|
||||
file_glob=file_glob,
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
)
|
||||
else:
|
||||
result = {"success": False, "error": f"Unknown action: {action}"}
|
||||
return json.dumps(result, ensure_ascii=False)
|
||||
except Exception as e: # pragma: no cover - defensive wrapper
|
||||
return json.dumps({"success": False, "error": str(e)}, ensure_ascii=False)
|
||||
|
||||
|
||||
registry.register(
|
||||
name="workspace",
|
||||
toolset="workspace",
|
||||
schema=WORKSPACE_SCHEMA,
|
||||
handler=lambda args, **kw: workspace_tool(
|
||||
action=args.get("action", ""),
|
||||
query=args.get("query", ""),
|
||||
path=args.get("path", ""),
|
||||
file_glob=args.get("file_glob"),
|
||||
limit=args.get("limit", 20),
|
||||
offset=args.get("offset", 0),
|
||||
recursive=args.get("recursive", True),
|
||||
),
|
||||
check_fn=lambda: True,
|
||||
)
|
||||
Reference in New Issue
Block a user