feat: adding peer config
This commit is contained in:
parent
a881313212
commit
f9e73a58bd
|
|
@ -27,6 +27,14 @@ honcho peer list
|
|||
honcho peer inspect <peer_id>
|
||||
honcho session messages <session_id> --last 20
|
||||
|
||||
# Peer management
|
||||
honcho peer create <peer_id>
|
||||
honcho peer create <peer_id> --observe-me --metadata '{"role": "user"}'
|
||||
honcho peer get-metadata <peer_id>
|
||||
honcho peer set-metadata <peer_id> --metadata '{"role": "user"}'
|
||||
honcho peer representation <peer_id>
|
||||
honcho peer representation <peer_id> --search-query "preferences" --max-conclusions 20
|
||||
|
||||
# Debug
|
||||
honcho peer card <peer_id>
|
||||
honcho conclusion search "topic" --observer <peer_id>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
"""Peer commands: list, inspect, card, chat, search."""
|
||||
"""Peer commands: list, inspect, card, chat, search, create, metadata, representation."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Optional
|
||||
|
||||
import typer
|
||||
|
|
@ -177,3 +178,130 @@ def search(
|
|||
print_result(items, columns=["id", "session_id", "content", "created_at"], title=f"Peer search: {query}")
|
||||
except Exception as e:
|
||||
_handle_error(e, "peer", pid)
|
||||
|
||||
|
||||
@app.command("create")
|
||||
def create_peer(
|
||||
peer_id: str = typer.Argument(help="Peer ID to create or get"),
|
||||
observe_me: Optional[bool] = typer.Option(None, "--observe-me/--no-observe-me", help="Whether Honcho will form a representation of this peer"),
|
||||
metadata: Optional[str] = typer.Option(None, "--metadata", help="JSON metadata to associate with the peer"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Create or get a peer."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
from honcho.api_types import PeerConfig
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace)
|
||||
pid = validate_resource_id(peer_id, "peer")
|
||||
client, config = get_client()
|
||||
|
||||
parsed_metadata = None
|
||||
if metadata:
|
||||
try:
|
||||
parsed_metadata = json.loads(metadata)
|
||||
except json.JSONDecodeError as e:
|
||||
from honcho_cli.output import print_error
|
||||
print_error("INVALID_JSON", f"--metadata must be valid JSON: {e}", {})
|
||||
raise typer.Exit(1)
|
||||
|
||||
peer_config = PeerConfig(observe_me=observe_me) if observe_me is not None else None
|
||||
|
||||
try:
|
||||
p = client.peer(pid, configuration=peer_config, metadata=parsed_metadata)
|
||||
result = {
|
||||
"peer_id": p.id,
|
||||
"metadata": parsed_metadata,
|
||||
"configuration": {"observe_me": observe_me} if observe_me is not None else None,
|
||||
}
|
||||
print_result(result)
|
||||
except Exception as e:
|
||||
_handle_error(e, "peer", pid)
|
||||
|
||||
|
||||
@app.command("get-metadata")
|
||||
def get_metadata(
|
||||
peer_id: Optional[str] = typer.Argument(None, help="Peer ID (uses default if omitted)"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
peer: Optional[str] = typer.Option(None, "--peer", "-p", help="Override peer ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Get metadata for a peer."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, peer=peer)
|
||||
pid = _get_peer_id(peer_id)
|
||||
client, config = get_client()
|
||||
p = client.peer(pid)
|
||||
|
||||
try:
|
||||
result = p.get_metadata()
|
||||
print_result({"peer_id": pid, "metadata": result})
|
||||
except Exception as e:
|
||||
_handle_error(e, "peer", pid)
|
||||
|
||||
|
||||
@app.command("set-metadata")
|
||||
def set_metadata(
|
||||
peer_id: Optional[str] = typer.Argument(None, help="Peer ID (uses default if omitted)"),
|
||||
metadata: str = typer.Option(..., "--metadata", "-m", help="JSON metadata to set (e.g. '{\"key\": \"value\"}')"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
peer: Optional[str] = typer.Option(None, "--peer", "-p", help="Override peer ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Set metadata for a peer."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, peer=peer)
|
||||
pid = _get_peer_id(peer_id)
|
||||
client, config = get_client()
|
||||
|
||||
try:
|
||||
parsed = json.loads(metadata)
|
||||
except json.JSONDecodeError as e:
|
||||
from honcho_cli.output import print_error
|
||||
print_error("INVALID_JSON", f"metadata must be valid JSON: {e}", {})
|
||||
raise typer.Exit(1)
|
||||
|
||||
p = client.peer(pid)
|
||||
|
||||
try:
|
||||
p.set_metadata(parsed)
|
||||
print_result({"peer_id": pid, "metadata": parsed})
|
||||
except Exception as e:
|
||||
_handle_error(e, "peer", pid)
|
||||
|
||||
|
||||
@app.command()
|
||||
def representation(
|
||||
peer_id: Optional[str] = typer.Argument(None, help="Peer ID (uses default if omitted)"),
|
||||
target: Optional[str] = typer.Option(None, help="Target peer to get representation about"),
|
||||
session: Optional[str] = typer.Option(None, help="Scope representation to a session"),
|
||||
search_query: Optional[str] = typer.Option(None, help="Semantic search query to filter conclusions"),
|
||||
max_conclusions: Optional[int] = typer.Option(None, help="Maximum number of conclusions to include"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
peer: Optional[str] = typer.Option(None, "--peer", "-p", help="Override peer ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Get the formatted representation for a peer."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, peer=peer)
|
||||
pid = _get_peer_id(peer_id)
|
||||
client, config = get_client()
|
||||
p = client.peer(pid)
|
||||
|
||||
try:
|
||||
result = p.representation(
|
||||
target=target,
|
||||
session=session,
|
||||
search_query=search_query,
|
||||
max_conclusions=max_conclusions,
|
||||
)
|
||||
print_result({"peer_id": pid, "target": target, "representation": result})
|
||||
except Exception as e:
|
||||
_handle_error(e, "peer", pid)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
"""Session commands: list, inspect, messages, context, summaries."""
|
||||
"""Session commands: list, inspect, messages, context, summaries, peers, search, representation, metadata."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
import json
|
||||
from typing import List, Optional
|
||||
|
||||
import typer
|
||||
|
||||
|
|
@ -197,3 +198,223 @@ def summaries(
|
|||
print_result(result)
|
||||
except Exception as e:
|
||||
_handle_error(e, "session", sid)
|
||||
|
||||
|
||||
@app.command()
|
||||
def delete(
|
||||
session_id: Optional[str] = typer.Argument(None, help="Session ID (uses default if omitted)"),
|
||||
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
session: Optional[str] = typer.Option(None, "--session", "-s", help="Override session ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Delete a session and all its data. Destructive — requires --yes or interactive confirm."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, session=session)
|
||||
sid = _get_session_id(session_id)
|
||||
client, config = get_client()
|
||||
|
||||
if not yes:
|
||||
typer.confirm(f"Delete session '{sid}' and all its messages, conclusions, and queue items?", abort=True)
|
||||
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
sess.delete()
|
||||
status(f"Session '{sid}' deleted")
|
||||
print_result({"deleted": sid})
|
||||
except Exception as e:
|
||||
_handle_error(e, "session", sid)
|
||||
|
||||
|
||||
@app.command("peers")
|
||||
def session_peers(
|
||||
session_id: Optional[str] = typer.Argument(None, help="Session ID (uses default if omitted)"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
session: Optional[str] = typer.Option(None, "--session", "-s", help="Override session ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""List peers in a session."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, session=session)
|
||||
sid = _get_session_id(session_id)
|
||||
client, config = get_client()
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
peers = sess.peers()
|
||||
items = [{"id": p.id} for p in peers]
|
||||
print_result(items, columns=["id"], title=f"Session peers ({sid})")
|
||||
except Exception as e:
|
||||
_handle_error(e, "session", sid)
|
||||
|
||||
|
||||
@app.command("add-peers")
|
||||
def add_peers(
|
||||
peer_ids: List[str] = typer.Argument(help="Peer IDs to add to the session"),
|
||||
session_id: Optional[str] = typer.Option(None, "--session", "-s", help="Session ID (uses default if omitted)"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Add peers to a session."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, session=session_id)
|
||||
sid = _get_session_id(session_id)
|
||||
client, config = get_client()
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
sess.add_peers(peer_ids)
|
||||
print_result({"session_id": sid, "added_peers": peer_ids})
|
||||
except Exception as e:
|
||||
_handle_error(e, "session", sid)
|
||||
|
||||
|
||||
@app.command("remove-peers")
|
||||
def remove_peers(
|
||||
peer_ids: List[str] = typer.Argument(help="Peer IDs to remove from the session"),
|
||||
session_id: Optional[str] = typer.Option(None, "--session", "-s", help="Session ID (uses default if omitted)"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Remove peers from a session."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, session=session_id)
|
||||
sid = _get_session_id(session_id)
|
||||
client, config = get_client()
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
sess.remove_peers(peer_ids)
|
||||
print_result({"session_id": sid, "removed_peers": peer_ids})
|
||||
except Exception as e:
|
||||
_handle_error(e, "session", sid)
|
||||
|
||||
|
||||
@app.command()
|
||||
def search(
|
||||
query: str = typer.Argument(help="Search query"),
|
||||
session_id: Optional[str] = typer.Option(None, help="Session ID (uses default if omitted)"),
|
||||
limit: int = typer.Option(10, help="Max results"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
session: Optional[str] = typer.Option(None, "--session", "-s", help="Override session ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Search messages in a session."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, session=session)
|
||||
sid = _get_session_id(session_id)
|
||||
client, config = get_client()
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
results = sess.search(query, limit=limit)
|
||||
items = [
|
||||
{
|
||||
"id": m.id,
|
||||
"peer_id": m.peer_id,
|
||||
"content": m.content[:200],
|
||||
"created_at": str(m.created_at),
|
||||
}
|
||||
for m in results
|
||||
]
|
||||
print_result(items, columns=["id", "peer_id", "content", "created_at"], title=f"Session search: {query}")
|
||||
except Exception as e:
|
||||
_handle_error(e, "session", sid)
|
||||
|
||||
|
||||
@app.command()
|
||||
def representation(
|
||||
peer_id: str = typer.Argument(help="Peer ID to get representation for"),
|
||||
session_id: Optional[str] = typer.Option(None, help="Session ID (uses default if omitted)"),
|
||||
target: Optional[str] = typer.Option(None, help="Target peer (what peer_id knows about target)"),
|
||||
search_query: Optional[str] = typer.Option(None, help="Semantic search query to filter conclusions"),
|
||||
max_conclusions: Optional[int] = typer.Option(None, help="Maximum number of conclusions to include"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
session: Optional[str] = typer.Option(None, "--session", "-s", help="Override session ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Get the representation of a peer within a session."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, session=session)
|
||||
sid = _get_session_id(session_id)
|
||||
client, config = get_client()
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
result = sess.representation(
|
||||
peer_id,
|
||||
target=target,
|
||||
search_query=search_query,
|
||||
max_conclusions=max_conclusions,
|
||||
)
|
||||
print_result({"session_id": sid, "peer_id": peer_id, "target": target, "representation": result})
|
||||
except Exception as e:
|
||||
_handle_error(e, "session", sid)
|
||||
|
||||
|
||||
@app.command("get-metadata")
|
||||
def get_metadata(
|
||||
session_id: Optional[str] = typer.Argument(None, help="Session ID (uses default if omitted)"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
session: Optional[str] = typer.Option(None, "--session", "-s", help="Override session ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Get metadata for a session."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, session=session)
|
||||
sid = _get_session_id(session_id)
|
||||
client, config = get_client()
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
result = sess.get_metadata()
|
||||
print_result({"session_id": sid, "metadata": result})
|
||||
except Exception as e:
|
||||
_handle_error(e, "session", sid)
|
||||
|
||||
|
||||
@app.command("set-metadata")
|
||||
def set_metadata(
|
||||
metadata: str = typer.Argument(help="JSON metadata to set (e.g. '{\"key\": \"value\"}')"),
|
||||
session_id: Optional[str] = typer.Option(None, help="Session ID (uses default if omitted)"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
session: Optional[str] = typer.Option(None, "--session", "-s", help="Override session ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Set metadata for a session."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace, session=session)
|
||||
sid = _get_session_id(session_id)
|
||||
client, config = get_client()
|
||||
|
||||
try:
|
||||
parsed = json.loads(metadata)
|
||||
except json.JSONDecodeError as e:
|
||||
from honcho_cli.output import print_error
|
||||
print_error("INVALID_JSON", f"metadata must be valid JSON: {e}", {})
|
||||
raise typer.Exit(1)
|
||||
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
sess.set_metadata(parsed)
|
||||
print_result({"session_id": sid, "metadata": parsed})
|
||||
except Exception as e:
|
||||
_handle_error(e, "session", sid)
|
||||
|
|
|
|||
|
|
@ -113,11 +113,16 @@ def inspect(
|
|||
@app.command()
|
||||
def delete(
|
||||
workspace_id: str = typer.Argument(help="Workspace ID to delete"),
|
||||
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation"),
|
||||
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt (for scripted/agent use)"),
|
||||
cascade: bool = typer.Option(False, "--cascade", help="Delete all sessions before deleting the workspace"),
|
||||
dry_run: bool = typer.Option(False, "--dry-run", help="Show what would be deleted without deleting"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Delete a workspace. Destructive — requires --yes or interactive confirm."""
|
||||
"""Delete a workspace. Use --dry-run first to see what will be deleted.
|
||||
|
||||
Requires --yes to skip confirmation, or will prompt interactively.
|
||||
If sessions exist, requires --cascade to delete them first.
|
||||
"""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
|
|
@ -125,26 +130,44 @@ def delete(
|
|||
|
||||
validate_resource_id(workspace_id, "workspace")
|
||||
client, config = get_client()
|
||||
client = _with_workspace(client, workspace_id)
|
||||
ws_client = _with_workspace(client, workspace_id)
|
||||
|
||||
# Always fetch sessions for dry-run or cascade
|
||||
raw_sessions = _raw_list(ws_client.sessions()) if (dry_run or cascade) else []
|
||||
|
||||
if dry_run:
|
||||
sessions = list(client.sessions())
|
||||
peers = list(client.peers())
|
||||
print_result({
|
||||
"dry_run": True,
|
||||
"workspace_id": workspace_id,
|
||||
"sessions_to_delete": len(sessions),
|
||||
"peers_to_delete": len(peers),
|
||||
"sessions_to_delete": len(raw_sessions),
|
||||
"session_ids": [s.id for s in raw_sessions],
|
||||
"warning": "This action cannot be undone.",
|
||||
})
|
||||
return
|
||||
|
||||
if not yes:
|
||||
typer.confirm(f"Delete workspace '{workspace_id}' and all its data?", abort=True)
|
||||
if cascade and raw_sessions:
|
||||
typer.confirm(
|
||||
f"Delete workspace '{workspace_id}' and {len(raw_sessions)} session(s)? This cannot be undone.",
|
||||
abort=True,
|
||||
)
|
||||
else:
|
||||
typer.confirm(f"Delete workspace '{workspace_id}'? This cannot be undone.", abort=True)
|
||||
|
||||
try:
|
||||
client.delete_workspace(workspace_id)
|
||||
status(f"Workspace '{workspace_id}' deleted")
|
||||
print_result({"deleted": workspace_id})
|
||||
deleted_sessions = []
|
||||
if cascade and raw_sessions:
|
||||
for s in raw_sessions:
|
||||
ws_client.session(s.id).delete()
|
||||
deleted_sessions.append(s.id)
|
||||
status(f"Deleted session '{s.id}'")
|
||||
|
||||
ws_client.delete_workspace(workspace_id)
|
||||
status(f"Workspace '{workspace_id}' deletion accepted (processing in background)")
|
||||
result = {"deleted_workspace": workspace_id, "status": "accepted"}
|
||||
if cascade:
|
||||
result["deleted_sessions"] = deleted_sessions
|
||||
print_result(result)
|
||||
except Exception as e:
|
||||
_handle_error(e, "workspace", workspace_id)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue