AQIT 0.1.0
Loading...
Searching...
No Matches
sync_dispatch.py
Go to the documentation of this file.
1# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2# This file is part of the Aquin Engine. Unauthorized copying, modification,
3# distribution, or use of this file, via any medium, is strictly prohibited.
4# Proprietary and confidential. See LICENSE for terms.
5
6"""Run tools locally and track results in ~/.aquin/commands/."""
7from __future__ import annotations
8
9import time
10import uuid
11from typing import Any
12
13
14def _resolve_card(tool_name: str, result: Any, card: dict[str, Any] | None) -> dict[str, Any] | None:
15 if card is not None:
16 return card
17 if not isinstance(result, dict):
18 return None
19 existing = result.get("card")
20 if isinstance(existing, dict):
21 return existing
22 from aquin.compute import card_mapper
23
24 mapped = card_mapper.to_card(tool_name, result)
25 if mapped is not None:
26 return mapped
27 if result.get("type") and "data" in result:
28 return result
29 return None
30
31
32def _result_content(tool_name: str, result: Any, card: dict[str, Any] | None) -> Any:
33 raw = result.get("content", result) if isinstance(result, dict) else result
34 if isinstance(raw, dict):
35 from aquin.compute.sync_slim import slim_tool_result_for_sync
37 return slim_tool_result_for_sync(tool_name, raw, card)
38 return raw
39
40
41def _track(
42 *,
43 tool_name: str,
44 command: str | None,
45 args: dict[str, Any],
46 result: Any,
47 card: dict[str, Any] | None,
48 duration_ms: int,
49 exit_ok: bool,
50) -> str:
51 from aquin.command_log import append_record
52
53 slim = _result_content(tool_name, result, card) if isinstance(result, dict) else result
54 return append_record(
55 tool_name=tool_name,
56 command=command,
57 args=args,
58 result=slim,
59 card=card,
60 duration_ms=duration_ms,
61 exit_ok=exit_ok,
62 )
63
64
65def _emit_tracked(name: str, record_id: str) -> None:
66 print(f"[tracked] {name} -> {record_id[:8]}", flush=True)
67
68
70 tool_name: str,
71 args: dict[str, Any],
72 result: Any,
73 *,
74 card: dict[str, Any] | None = None,
75 command: str | None = None,
76 label: str | None = None,
77) -> None:
78 """Track a standalone CLI command result locally."""
79 _ = label
80 card = _resolve_card(tool_name, result, card)
81 exit_ok = not (isinstance(result, dict) and result.get("error"))
82 rid = _track(
83 tool_name=tool_name,
84 command=command,
85 args=args,
86 result=result,
87 card=card,
88 duration_ms=0,
89 exit_ok=exit_ok,
90 )
91 name = command or tool_name
92 _emit_tracked(name, rid)
93
94
96 name: str,
97 args: dict[str, Any],
98 ctx: dict[str, Any],
99 *,
100 command: str | None = None,
101) -> dict[str, Any]:
102 from aquin.engine.tools.registry import dispatch, _load_stubs
103
104 _load_stubs()
105 _ = ctx
106 t0 = time.perf_counter()
107 try:
108 result = dispatch(name, args, ctx)
109 exit_ok = True
110 except Exception as exc:
111 result = {"error": str(exc)}
112 exit_ok = False
113
114 card = _resolve_card(name, result, None)
115 duration_ms = int((time.perf_counter() - t0) * 1000)
116 rid = _track(
117 tool_name=name,
118 command=command,
119 args=args,
120 result=result,
121 card=card,
122 duration_ms=duration_ms,
123 exit_ok=exit_ok and not (isinstance(result, dict) and result.get("error")),
124 )
125 _emit_tracked(command or name, rid)
126 return result if isinstance(result, dict) else {"content": result}
127
128
130 name: str,
131 args: dict[str, Any],
132 ctx: dict[str, Any],
133 result: Any,
134 *,
135 command: str | None = None,
136) -> dict[str, Any]:
137 try:
138 card = _resolve_card(name, result, None)
139 exit_ok = not (isinstance(result, dict) and result.get("error"))
140 rid = _track(
141 tool_name=name,
142 command=command,
143 args=args,
144 result=result,
145 card=card,
146 duration_ms=0,
147 exit_ok=exit_ok,
148 )
149 _emit_tracked(command or name, rid)
150 except Exception:
151 pass
152 return result if isinstance(result, dict) else {"content": result}
153
154
156 name: str,
157 args: dict[str, Any],
158 ctx: dict[str, Any],
159 *,
160 command: str | None = None,
161) -> dict[str, Any]:
162 """Run catalog/session tools that never touch GPU weights."""
163 from aquin.session_mode import tool_requires_model
164
165 if tool_requires_model(name):
166 raise ValueError(f"dispatch_model_free called for GPU tool: {name}")
167
168 from aquin.engine.tools.registry import dispatch, _load_stubs
169
170 _load_stubs()
171 try:
172 result = dispatch(name, args, ctx)
173 except Exception as exc:
174 from aquin.user_errors import friendly_message
175
176 result = {"error": friendly_message(exc)}
177
178 return _finish_tracked_dispatch(name, args, ctx, result, command=command)
179
180
181def run_dispatch(
182 name: str,
183 args: dict[str, Any],
184 ctx: dict[str, Any],
185 *,
186 command: str | None = None,
187 ensure_model: str | None = None,
188 timeout: float = 1800,
189) -> dict[str, Any]:
190 """
191 Run a tool through the persistent model daemon when it is available, else load
192 in-process and run locally. Either way the result is tracked locally so the
193 user sees the [tracked] line with their own context.
194 """
195 from aquin.session_mode import tool_requires_model
196
197 if not tool_requires_model(name):
198 return dispatch_model_free(name, args, ctx, command=command)
199
200 result: Any = None
201 used_daemon = False
202
203 try:
204 from aquin.engine import model_daemon
205
206 if model_daemon.is_running():
207 data = model_daemon.dispatch(name, args, ctx, timeout=timeout)
208 if isinstance(data, dict):
209 if data.get("ok"):
210 result = data.get("result")
211 used_daemon = True
212 elif "error" in data:
213 err = str(data.get("error") or "")
214 low = err.lower()
215 if "not yet ported" in low or "unknown tool" in low:
216 used_daemon = False
217 result = None
218 else:
219 result = {"error": err}
220 used_daemon = True
221 except Exception:
222 used_daemon = False
223
224 if not used_daemon:
225 if ensure_model:
226 try:
227 from aquin.compute.model_loader import load_model, resolve_model_id
228 load_model(resolve_model_id(ensure_model))
229 except Exception as exc:
230 from aquin.user_errors import friendly_message
231
232 result = {"error": friendly_message(exc)}
233 if result is None:
234 from aquin.engine.tools.registry import dispatch, _load_stubs
235
236 _load_stubs()
237 try:
238 result = dispatch(name, args, ctx)
239 except Exception as exc:
240 from aquin.user_errors import friendly_message
241
242 result = {"error": friendly_message(exc)}
243
244 return _finish_tracked_dispatch(name, args, ctx, result, command=command)
245
246
247# Legacy names — same behavior, no cloud sync
248dispatch_with_sync = dispatch_with_tracking
249
250
252 ctx: dict[str, Any],
253 tool_name: str,
254 args: dict[str, Any],
255 result: Any,
256 *,
257 card: dict[str, Any] | None = None,
258 command: str | None = None,
259) -> None:
260 """Track a catalog/sync CLI result. ``ctx`` is accepted for API compat (session sync is optional)."""
261 _ = ctx
262 if command is None:
263 from aquin.command_log import _TOOL_TO_CLI
264
265 command = _TOOL_TO_CLI.get(tool_name, tool_name)
266 track_cli_result(tool_name, args, result, card=card, command=command)
267
268
269def session_ctx_from_state() -> dict[str, str]:
270 """Auth + base URL from engine state (optional session id if present)."""
271 import os
272
273 from aquin.engine.main import _load_state, resolve_api_key
274
275 state = _load_state()
276 sid = (state.get("active_session_id") or "").strip()
277 api_key = resolve_api_key(allow_missing=True)
278 base_url = (
279 state.get("base_url") or os.environ.get("AQUIN_BASE_URL", "https://api.aquin.app")
280 ).rstrip("/")
281 return {"session_id": sid, "api_key": api_key, "base_url": base_url}
282
283
284def require_session_ctx(*, label: str) -> dict[str, str]:
285 """Only required for aquin chat agent API — not for compute."""
286 from aquin.engine.main import resolve_api_key
287 import sys
290 api_key = (ctx.get("api_key") or resolve_api_key(allow_missing=True)).strip()
291 if not api_key:
292 print(f"[auth] {label} needs a cloud session token — not available in local framework mode.", file=sys.stderr)
293 sys.exit(1)
294 sid = (ctx.get("session_id") or "").strip()
295 if not sid:
296 print(
297 f"[chat] Session id required for {label}.\n"
298 " Open a session tab in the web app and run:\n"
299 " aquin config send-session <session-uuid>",
300 file=sys.stderr,
301 )
302 sys.exit(1)
303 return ctx
304
305
306def require_active_session(ctx: dict[str, Any], *, label: str = "this command") -> None:
307 """No-op for compute — kept so old imports don't break."""
308 _ = ctx, label
309
311def push_tool_pair(**kwargs: Any) -> bool:
312 """Legacy — track locally instead of pushing to cloud."""
313 tool_call_id = kwargs.get("tool_call_id") or str(uuid.uuid4())
314 _ = tool_call_id
316 kwargs.get("tool_name") or "tool",
317 kwargs.get("args") or {},
318 kwargs.get("result"),
319 card=kwargs.get("card"),
320 )
321 return True
None sync_cli_result(dict[str, Any] ctx, str tool_name, dict[str, Any] args, Any result, *, dict[str, Any]|None card=None, str|None command=None)
None _emit_tracked(str name, str record_id)
None require_active_session(dict[str, Any] ctx, *, str label="this command")
dict[str, Any] run_dispatch(str name, dict[str, Any] args, dict[str, Any] ctx, *, str|None command=None, str|None ensure_model=None, float timeout=1800)
Any _result_content(str tool_name, Any result, dict[str, Any]|None card)
dict[str, Any]|None _resolve_card(str tool_name, Any result, dict[str, Any]|None card)
dict[str, str] session_ctx_from_state()
None track_cli_result(str tool_name, dict[str, Any] args, Any result, *, dict[str, Any]|None card=None, str|None command=None, str|None label=None)
bool push_tool_pair(**Any kwargs)
dict[str, Any] dispatch_model_free(str name, dict[str, Any] args, dict[str, Any] ctx, *, str|None command=None)
dict[str, str] require_session_ctx(*, str label)
str _track(*, str tool_name, str|None command, dict[str, Any] args, Any result, dict[str, Any]|None card, int duration_ms, bool exit_ok)
dict[str, Any] _finish_tracked_dispatch(str name, dict[str, Any] args, dict[str, Any] ctx, Any result, *, str|None command=None)
dict[str, Any] dispatch_with_tracking(str name, dict[str, Any] args, dict[str, Any] ctx, *, str|None command=None)