feat: adding more support for command-level flags, also including workarounds for getting raw SDK info
This commit is contained in:
parent
d3342ab466
commit
a881313212
|
|
@ -21,10 +21,15 @@ add_common_options(app)
|
|||
def list_conclusions(
|
||||
observer: Optional[str] = typer.Option(None, "--observer", help="Observer peer ID"),
|
||||
observed: Optional[str] = typer.Option(None, "--observed", help="Observed peer ID"),
|
||||
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:
|
||||
"""List conclusions."""
|
||||
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)
|
||||
client, config = get_client()
|
||||
|
||||
if not observer:
|
||||
|
|
@ -33,13 +38,13 @@ def list_conclusions(
|
|||
print_error("NO_PEER", "Observer peer ID required. Use --observer or set default peer.")
|
||||
raise typer.Exit(1)
|
||||
|
||||
peer = client.peer(observer)
|
||||
p = client.peer(observer)
|
||||
|
||||
try:
|
||||
if observed:
|
||||
scope = peer.conclusions_of(observed)
|
||||
scope = p.conclusions_of(observed)
|
||||
else:
|
||||
scope = peer.conclusions
|
||||
scope = p.conclusions
|
||||
|
||||
conclusions = list(scope.list())
|
||||
items = [
|
||||
|
|
@ -63,10 +68,15 @@ def search(
|
|||
observer: Optional[str] = typer.Option(None, "--observer", help="Observer peer ID"),
|
||||
observed: Optional[str] = typer.Option(None, "--observed", help="Observed peer ID"),
|
||||
top_k: int = typer.Option(10, help="Max results"),
|
||||
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:
|
||||
"""Semantic search over conclusions."""
|
||||
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)
|
||||
client, config = get_client()
|
||||
|
||||
if not observer:
|
||||
|
|
@ -75,13 +85,13 @@ def search(
|
|||
print_error("NO_PEER", "Observer peer ID required. Use --observer or set default peer.")
|
||||
raise typer.Exit(1)
|
||||
|
||||
peer = client.peer(observer)
|
||||
p = client.peer(observer)
|
||||
|
||||
try:
|
||||
if observed:
|
||||
scope = peer.conclusions_of(observed)
|
||||
scope = p.conclusions_of(observed)
|
||||
else:
|
||||
scope = peer.conclusions
|
||||
scope = p.conclusions
|
||||
|
||||
results = scope.query(query, top_k=top_k)
|
||||
items = [
|
||||
|
|
@ -104,11 +114,16 @@ def create(
|
|||
content: str = typer.Argument(help="Conclusion content or JSON payload"),
|
||||
observer: Optional[str] = typer.Option(None, "--observer", help="Observer peer ID"),
|
||||
observed: Optional[str] = typer.Option(None, "--observed", help="Observed peer ID"),
|
||||
session_id: Optional[str] = typer.Option(None, "--session", help="Session context"),
|
||||
session_id: Optional[str] = typer.Option(None, "--session", "-s", help="Session context"),
|
||||
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:
|
||||
"""Create a conclusion."""
|
||||
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)
|
||||
client, config = get_client()
|
||||
|
||||
if not observer:
|
||||
|
|
@ -124,13 +139,13 @@ def create(
|
|||
except (json.JSONDecodeError, AttributeError):
|
||||
pass
|
||||
|
||||
peer = client.peer(observer)
|
||||
p = client.peer(observer)
|
||||
|
||||
try:
|
||||
if observed:
|
||||
scope = peer.conclusions_of(observed)
|
||||
scope = p.conclusions_of(observed)
|
||||
else:
|
||||
scope = peer.conclusions
|
||||
scope = p.conclusions
|
||||
|
||||
result = scope.create(content, session_id=session_id)
|
||||
print_result({
|
||||
|
|
@ -150,10 +165,15 @@ def delete(
|
|||
observer: Optional[str] = typer.Option(None, "--observer", help="Observer peer ID"),
|
||||
observed: Optional[str] = typer.Option(None, "--observed", help="Observed peer ID"),
|
||||
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation"),
|
||||
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:
|
||||
"""Delete a conclusion."""
|
||||
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)
|
||||
validate_resource_id(conclusion_id, "conclusion")
|
||||
client, config = get_client()
|
||||
|
||||
|
|
@ -166,13 +186,13 @@ def delete(
|
|||
if not yes:
|
||||
typer.confirm(f"Delete conclusion '{conclusion_id}'?", abort=True)
|
||||
|
||||
peer = client.peer(observer)
|
||||
p = client.peer(observer)
|
||||
|
||||
try:
|
||||
if observed:
|
||||
scope = peer.conclusions_of(observed)
|
||||
scope = p.conclusions_of(observed)
|
||||
else:
|
||||
scope = peer.conclusions
|
||||
scope = p.conclusions
|
||||
|
||||
scope.delete(conclusion_id)
|
||||
status(f"Conclusion '{conclusion_id}' deleted")
|
||||
|
|
|
|||
|
|
@ -47,13 +47,17 @@ def generate(
|
|||
admin: bool = typer.Option(False, "--admin", help="Generate admin key"),
|
||||
expires: str = typer.Option("90d", "--expires", help="Expiry duration (e.g., 30d, 24h)"),
|
||||
no_expire: bool = typer.Option(False, "--no-expire", help="No expiration (use with caution)"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Generate a scoped JWT key.
|
||||
|
||||
Requires an admin JWT in config. Generated keys are scoped down from admin.
|
||||
"""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_resolved_config
|
||||
|
||||
handle_cmd_flags(json_output=json_output)
|
||||
|
||||
config = get_resolved_config()
|
||||
|
||||
if not config.api_key:
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from typing import Optional
|
||||
|
||||
import typer
|
||||
|
||||
from honcho_cli.commands.workspace import _handle_error
|
||||
from honcho_cli.output import print_result
|
||||
from honcho_cli.output import print_result, status
|
||||
from honcho_cli.validation import validate_resource_id
|
||||
|
||||
from honcho_cli.common import add_common_options
|
||||
|
|
@ -21,34 +22,62 @@ def list_messages(
|
|||
session_id: Optional[str] = typer.Argument(None, help="Session ID (uses default if omitted)"),
|
||||
last: int = typer.Option(20, "--last", help="Number of recent messages"),
|
||||
reverse: bool = typer.Option(False, "--reverse", help="Reverse order"),
|
||||
brief: bool = typer.Option(False, "--brief", help="Show only IDs, peer, token count, and created_at (no content)"),
|
||||
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 messages in a session."""
|
||||
from honcho_cli.commands.session import _get_session_id
|
||||
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()
|
||||
session = client.session(sid)
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
msgs = list(session.messages())
|
||||
msgs = list(sess.messages())
|
||||
if not reverse:
|
||||
msgs = msgs[-last:]
|
||||
else:
|
||||
msgs = msgs[:last]
|
||||
|
||||
items = [
|
||||
{
|
||||
"id": m.id,
|
||||
"peer_id": m.peer_id,
|
||||
"content": m.content,
|
||||
"token_count": m.token_count,
|
||||
"metadata": m.metadata,
|
||||
"created_at": str(m.created_at),
|
||||
}
|
||||
for m in msgs
|
||||
]
|
||||
print_result(items, columns=["id", "peer_id", "content", "created_at"], title="Messages")
|
||||
# Detect duplicate content
|
||||
content_hashes: dict[str, list[str]] = {}
|
||||
for m in msgs:
|
||||
h = hashlib.md5(m.content.encode()).hexdigest()
|
||||
content_hashes.setdefault(h, []).append(m.id)
|
||||
dupes = {h: ids for h, ids in content_hashes.items() if len(ids) > 1}
|
||||
if dupes:
|
||||
dupe_count = sum(len(ids) - 1 for ids in dupes.values())
|
||||
status(f"Warning: {dupe_count} duplicate message(s) detected (identical content, different IDs)")
|
||||
|
||||
if brief:
|
||||
items = [
|
||||
{
|
||||
"id": m.id,
|
||||
"peer_id": m.peer_id,
|
||||
"token_count": m.token_count,
|
||||
"created_at": str(m.created_at),
|
||||
}
|
||||
for m in msgs
|
||||
]
|
||||
print_result(items, columns=["id", "peer_id", "token_count", "created_at"], title="Messages")
|
||||
else:
|
||||
items = [
|
||||
{
|
||||
"id": m.id,
|
||||
"peer_id": m.peer_id,
|
||||
"content": m.content,
|
||||
"token_count": m.token_count,
|
||||
"metadata": m.metadata,
|
||||
"created_at": str(m.created_at),
|
||||
}
|
||||
for m in msgs
|
||||
]
|
||||
print_result(items, columns=["id", "peer_id", "content", "created_at"], title="Messages")
|
||||
except Exception as e:
|
||||
_handle_error(e, "message", "list")
|
||||
|
||||
|
|
@ -56,20 +85,24 @@ def list_messages(
|
|||
@app.command("get")
|
||||
def get_message(
|
||||
message_id: str = typer.Argument(help="Message ID"),
|
||||
session_id: Optional[str] = typer.Option(None, "--session", help="Session ID"),
|
||||
session_id: Optional[str] = typer.Option(None, "--session", "-s", help="Session ID"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Get a single message by ID."""
|
||||
from honcho_cli.commands.session import _get_session_id
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace)
|
||||
validate_resource_id(message_id, "message")
|
||||
sid = _get_session_id(session_id)
|
||||
client, config = get_client()
|
||||
|
||||
try:
|
||||
# Use raw HTTP to get a single message
|
||||
session = client.session(sid)
|
||||
msgs = list(session.messages())
|
||||
sess = client.session(sid)
|
||||
msgs = list(sess.messages())
|
||||
msg = next((m for m in msgs if m.id == message_id), None)
|
||||
|
||||
if msg is None:
|
||||
|
|
|
|||
|
|
@ -30,22 +30,28 @@ def _get_peer_id(peer_id: str | None) -> str:
|
|||
|
||||
|
||||
@app.command("list")
|
||||
def list_peers() -> None:
|
||||
def list_peers(
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""List all peers in the workspace."""
|
||||
from honcho_cli.commands.workspace import _compact_config, _raw_list
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace)
|
||||
client, config = get_client()
|
||||
|
||||
try:
|
||||
peers = list(client.peers())
|
||||
raw_peers = _raw_list(client.peers())
|
||||
items = [
|
||||
{
|
||||
"id": p.id,
|
||||
"metadata": getattr(p, "metadata", {}),
|
||||
"configuration": _config_to_dict(p.configuration) if getattr(p, "configuration", None) else None,
|
||||
"created_at": str(getattr(p, "created_at", "")),
|
||||
"metadata": p.metadata,
|
||||
"configuration": _compact_config(_config_to_dict(p.configuration)) if p.configuration else None,
|
||||
"created_at": str(p.created_at),
|
||||
}
|
||||
for p in peers
|
||||
for p in raw_peers
|
||||
]
|
||||
print_result(items, columns=["id", "metadata", "created_at"], title="Peers")
|
||||
except Exception as e:
|
||||
|
|
@ -55,18 +61,23 @@ def list_peers() -> None:
|
|||
@app.command()
|
||||
def inspect(
|
||||
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:
|
||||
"""Inspect a peer: card, session count, recent conclusions."""
|
||||
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()
|
||||
peer = client.peer(pid)
|
||||
p = client.peer(pid)
|
||||
|
||||
try:
|
||||
card = peer.get_card()
|
||||
sessions = list(peer.sessions())
|
||||
conclusions = list(peer.conclusions.list())
|
||||
card = p.get_card()
|
||||
sessions = list(p.sessions())
|
||||
conclusions = list(p.conclusions.list())
|
||||
|
||||
result = {
|
||||
"id": pid,
|
||||
|
|
@ -88,16 +99,21 @@ def inspect(
|
|||
def card(
|
||||
peer_id: Optional[str] = typer.Argument(None, help="Peer ID (uses default if omitted)"),
|
||||
target: Optional[str] = typer.Option(None, help="Target peer for relationship card"),
|
||||
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 raw peer card content."""
|
||||
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()
|
||||
peer = client.peer(pid)
|
||||
p = client.peer(pid)
|
||||
|
||||
try:
|
||||
result = peer.get_card(target=target)
|
||||
result = p.get_card(target=target)
|
||||
print_result({"peer_id": pid, "target": target, "card": result})
|
||||
except Exception as e:
|
||||
_handle_error(e, "peer", pid)
|
||||
|
|
@ -109,16 +125,21 @@ def chat(
|
|||
peer_id: Optional[str] = typer.Option(None, help="Peer ID (uses default if omitted)"),
|
||||
target: Optional[str] = typer.Option(None, help="Target peer for perspective"),
|
||||
session: Optional[str] = typer.Option(None, help="Session context"),
|
||||
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:
|
||||
"""Query the dialectic about 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()
|
||||
peer = client.peer(pid)
|
||||
p = client.peer(pid)
|
||||
|
||||
try:
|
||||
response = peer.chat(query, target=target, session=session)
|
||||
response = p.chat(query, target=target, session=session)
|
||||
print_result({"peer_id": pid, "query": query, "response": response})
|
||||
except Exception as e:
|
||||
_handle_error(e, "peer", pid)
|
||||
|
|
@ -129,16 +150,21 @@ def search(
|
|||
query: str = typer.Argument(help="Search query"),
|
||||
peer_id: Optional[str] = typer.Option(None, help="Peer 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"),
|
||||
peer: Optional[str] = typer.Option(None, "--peer", "-p", help="Override peer ID"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Search a peer's messages."""
|
||||
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()
|
||||
peer = client.peer(pid)
|
||||
p = client.peer(pid)
|
||||
|
||||
try:
|
||||
results = peer.search(query, limit=limit)
|
||||
results = p.search(query, limit=limit)
|
||||
items = [
|
||||
{
|
||||
"id": m.id,
|
||||
|
|
|
|||
|
|
@ -31,28 +31,34 @@ def _get_session_id(session_id: str | None) -> str:
|
|||
|
||||
@app.command("list")
|
||||
def list_sessions(
|
||||
peer_id: Optional[str] = typer.Option(None, "--peer", help="Filter by peer"),
|
||||
peer_id: Optional[str] = typer.Option(None, "--peer", "-p", help="Filter by peer"),
|
||||
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 sessions in the workspace."""
|
||||
from honcho_cli.commands.workspace import _raw_list
|
||||
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)
|
||||
client, config = get_client()
|
||||
|
||||
try:
|
||||
if peer_id:
|
||||
peer = client.peer(peer_id)
|
||||
sessions = list(peer.sessions())
|
||||
raw_sessions = _raw_list(peer.sessions())
|
||||
else:
|
||||
sessions = list(client.sessions())
|
||||
raw_sessions = _raw_list(client.sessions())
|
||||
|
||||
items = [
|
||||
{
|
||||
"id": s.id,
|
||||
"is_active": getattr(s, "is_active", None),
|
||||
"metadata": getattr(s, "metadata", {}),
|
||||
"created_at": str(getattr(s, "created_at", "")),
|
||||
"is_active": s.is_active,
|
||||
"metadata": s.metadata,
|
||||
"created_at": str(s.created_at),
|
||||
}
|
||||
for s in sessions
|
||||
for s in raw_sessions
|
||||
]
|
||||
print_result(items, columns=["id", "is_active", "metadata", "created_at"], title="Sessions")
|
||||
except Exception as e:
|
||||
|
|
@ -62,20 +68,28 @@ def list_sessions(
|
|||
@app.command()
|
||||
def inspect(
|
||||
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:
|
||||
"""Inspect a session: peers, message count, summaries, config."""
|
||||
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()
|
||||
session = client.session(sid)
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
peers = session.peers()
|
||||
messages = list(session.messages())
|
||||
summaries = session.summaries()
|
||||
sess_config = session.get_configuration()
|
||||
peers = sess.peers()
|
||||
messages = list(sess.messages())
|
||||
summaries = sess.summaries()
|
||||
sess_config = sess.get_configuration()
|
||||
|
||||
from honcho_cli.commands.workspace import _compact_config
|
||||
|
||||
raw_config = _config_to_dict(sess_config) if sess_config else None
|
||||
result = {
|
||||
"id": sid,
|
||||
"peers": [{"id": p.id} for p in peers],
|
||||
|
|
@ -84,7 +98,7 @@ def inspect(
|
|||
"short": summaries.short_summary if hasattr(summaries, "short_summary") else None,
|
||||
"long": summaries.long_summary if hasattr(summaries, "long_summary") else None,
|
||||
},
|
||||
"configuration": _config_to_dict(sess_config) if sess_config else None,
|
||||
"configuration": _compact_config(raw_config) if isinstance(raw_config, dict) else raw_config,
|
||||
}
|
||||
print_result(result)
|
||||
except Exception as e:
|
||||
|
|
@ -96,16 +110,21 @@ def messages(
|
|||
session_id: Optional[str] = typer.Argument(None, help="Session ID (uses default if omitted)"),
|
||||
last: int = typer.Option(20, "--last", help="Number of recent messages"),
|
||||
reverse: bool = typer.Option(False, "--reverse", help="Reverse order (oldest first)"),
|
||||
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 recent 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()
|
||||
session = client.session(sid)
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
msgs = list(session.messages())
|
||||
msgs = list(sess.messages())
|
||||
if not reverse:
|
||||
msgs = msgs[-last:]
|
||||
else:
|
||||
|
|
@ -131,16 +150,21 @@ def context(
|
|||
session_id: Optional[str] = typer.Argument(None, help="Session ID (uses default if omitted)"),
|
||||
tokens: Optional[int] = typer.Option(None, help="Token budget"),
|
||||
summary: bool = typer.Option(True, help="Include summary"),
|
||||
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 session context (what an agent would see)."""
|
||||
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()
|
||||
session = client.session(sid)
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
ctx = session.context(tokens=tokens, summary=summary)
|
||||
ctx = sess.context(tokens=tokens, summary=summary)
|
||||
result = ctx.__dict__ if hasattr(ctx, "__dict__") else ctx
|
||||
print_result(result)
|
||||
except Exception as e:
|
||||
|
|
@ -150,16 +174,21 @@ def context(
|
|||
@app.command()
|
||||
def summaries(
|
||||
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 session summaries (short + long)."""
|
||||
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()
|
||||
session = client.session(sid)
|
||||
sess = client.session(sid)
|
||||
|
||||
try:
|
||||
s = session.summaries()
|
||||
s = sess.summaries()
|
||||
result = {
|
||||
"session_id": sid,
|
||||
"short_summary": s.short_summary if hasattr(s, "short_summary") else None,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
"""Workspace commands: inspect, delete, search, queue-status."""
|
||||
"""Workspace commands: list, inspect, delete, search, queue-status."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
@ -26,13 +26,55 @@ def _get_workspace_id(workspace_id: str | None) -> str:
|
|||
return validate_resource_id(wid, "workspace")
|
||||
|
||||
|
||||
def _raw_list(page) -> list:
|
||||
"""Collect all raw API response items across all pages of a SyncPage."""
|
||||
items = list(page._raw_items)
|
||||
while page.has_next_page():
|
||||
page = page.get_next_page()
|
||||
if page is None:
|
||||
break
|
||||
items.extend(page._raw_items)
|
||||
return items
|
||||
|
||||
|
||||
def _compact_config(config_dict: dict) -> dict | str:
|
||||
"""Return '(defaults)' if all config values are None, else the dict."""
|
||||
if all(v is None for v in config_dict.values()):
|
||||
return "(defaults)"
|
||||
return config_dict
|
||||
|
||||
|
||||
@app.command("list")
|
||||
def list_workspaces(
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""List all accessible workspaces."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output)
|
||||
client, config = get_client()
|
||||
|
||||
try:
|
||||
workspaces = list(client.workspaces())
|
||||
items = [{"id": w} for w in workspaces]
|
||||
print_result(items, columns=["id"], title="Workspaces")
|
||||
except Exception as e:
|
||||
_handle_error(e, "workspace", "list")
|
||||
|
||||
|
||||
@app.command()
|
||||
def inspect(
|
||||
workspace_id: Optional[str] = typer.Argument(None, help="Workspace 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:
|
||||
"""Inspect a workspace: peers, sessions, config."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace)
|
||||
|
||||
wid = _get_workspace_id(workspace_id)
|
||||
client, config = get_client()
|
||||
|
||||
|
|
@ -44,17 +86,24 @@ def inspect(
|
|||
ws_config = client.get_configuration()
|
||||
ws_metadata = client.get_metadata()
|
||||
|
||||
peers = list(client.peers())
|
||||
sessions = list(client.sessions())
|
||||
# Use raw API response objects to get all fields (created_at, is_active)
|
||||
raw_peers = _raw_list(client.peers())
|
||||
raw_sessions = _raw_list(client.sessions())
|
||||
|
||||
result = {
|
||||
"workspace_id": wid,
|
||||
"metadata": ws_metadata,
|
||||
"configuration": _config_to_dict(ws_config),
|
||||
"peer_count": len(peers),
|
||||
"session_count": len(sessions),
|
||||
"peers": [{"id": p.id, "metadata": getattr(p, "metadata", {})} for p in peers[:20]],
|
||||
"sessions": [{"id": s.id, "is_active": getattr(s, "is_active", None), "metadata": getattr(s, "metadata", {})} for s in sessions[:20]],
|
||||
"configuration": _compact_config(_config_to_dict(ws_config)),
|
||||
"peer_count": len(raw_peers),
|
||||
"session_count": len(raw_sessions),
|
||||
"peers": [
|
||||
{"id": p.id, "metadata": p.metadata, "created_at": str(p.created_at)}
|
||||
for p in raw_peers[:20]
|
||||
],
|
||||
"sessions": [
|
||||
{"id": s.id, "is_active": s.is_active, "metadata": s.metadata, "created_at": str(s.created_at)}
|
||||
for s in raw_sessions[:20]
|
||||
],
|
||||
}
|
||||
print_result(result)
|
||||
except Exception as e:
|
||||
|
|
@ -66,10 +115,14 @@ def delete(
|
|||
workspace_id: str = typer.Argument(help="Workspace ID to delete"),
|
||||
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation"),
|
||||
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."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output)
|
||||
|
||||
validate_resource_id(workspace_id, "workspace")
|
||||
client, config = get_client()
|
||||
client = _with_workspace(client, workspace_id)
|
||||
|
|
@ -100,11 +153,16 @@ def delete(
|
|||
def search(
|
||||
query: str = typer.Argument(help="Search query"),
|
||||
workspace_id: Optional[str] = typer.Option(None, help="Workspace ID"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
limit: int = typer.Option(10, help="Max results"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Search messages across workspace."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace)
|
||||
|
||||
wid = _get_workspace_id(workspace_id)
|
||||
client, config = get_client()
|
||||
|
||||
|
|
@ -128,13 +186,18 @@ def search(
|
|||
@app.command("queue-status")
|
||||
def queue_status(
|
||||
workspace_id: Optional[str] = typer.Option(None, help="Workspace ID"),
|
||||
workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Override workspace ID"),
|
||||
observer: Optional[str] = typer.Option(None, help="Filter by observer peer"),
|
||||
sender: Optional[str] = typer.Option(None, help="Filter by sender peer"),
|
||||
session: Optional[str] = typer.Option(None, help="Filter by session"),
|
||||
json_output: bool = typer.Option(False, "--json", help="Force JSON output"),
|
||||
) -> None:
|
||||
"""Get queue processing status."""
|
||||
from honcho_cli.common import handle_cmd_flags
|
||||
from honcho_cli.main import get_client
|
||||
|
||||
handle_cmd_flags(json_output=json_output, workspace=workspace)
|
||||
|
||||
_get_workspace_id(workspace_id)
|
||||
client, config = get_client()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
"""Shared callback for subcommand groups to accept global-style flags."""
|
||||
"""Shared callback and command-level flag helpers.
|
||||
|
||||
Flags like --json, -w, -p, -s work in TWO positions:
|
||||
1. Group-level (before subcommand): honcho workspace --json list
|
||||
2. Command-level (after subcommand): honcho workspace list --json -w granola
|
||||
|
||||
Both positions are idempotent — if set at group level, the command-level is a no-op.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
@ -9,10 +16,28 @@ import typer
|
|||
from honcho_cli.output import set_json_mode, set_quiet_mode
|
||||
|
||||
|
||||
def handle_cmd_flags(
|
||||
json_output: bool = False,
|
||||
workspace: str | None = None,
|
||||
peer: str | None = None,
|
||||
session: str | None = None,
|
||||
) -> None:
|
||||
"""Apply command-level flags. Idempotent if already set by group callback."""
|
||||
if json_output:
|
||||
set_json_mode(True)
|
||||
|
||||
from honcho_cli.main import _global_overrides
|
||||
|
||||
if workspace:
|
||||
_global_overrides["workspace"] = workspace
|
||||
if peer:
|
||||
_global_overrides["peer"] = peer
|
||||
if session:
|
||||
_global_overrides["session"] = session
|
||||
|
||||
|
||||
def add_common_options(app: typer.Typer) -> None:
|
||||
"""Add a callback to a sub-app that accepts --json, --quiet, -w, -p, -s."""
|
||||
# Allow flags like --json after subcommands (e.g., `honcho workspace inspect granola --json`)
|
||||
app.info.context_settings = {"allow_interspersed_args": True}
|
||||
|
||||
@app.callback(invoke_without_command=True)
|
||||
def _callback(
|
||||
|
|
@ -28,7 +53,6 @@ def add_common_options(app: typer.Typer) -> None:
|
|||
if quiet:
|
||||
set_quiet_mode(True)
|
||||
|
||||
# Import here to avoid circular imports
|
||||
from honcho_cli.main import _global_overrides
|
||||
|
||||
if workspace:
|
||||
|
|
|
|||
Loading…
Reference in New Issue