systemr-cli 1.1.3__tar.gz → 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/PKG-INFO +1 -1
  2. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/__init__.py +1 -1
  3. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/chat_commands.py +38 -30
  4. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/pyproject.toml +1 -1
  5. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/.gitignore +0 -0
  6. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/DESIGN.md +0 -0
  7. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/README.md +0 -0
  8. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/clawhub/systemr-trading/SKILL.md +0 -0
  9. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/clawhub/systemr-trading/scripts/mcp_stdio_proxy.py +0 -0
  10. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/__main__.py +0 -0
  11. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/auth.py +0 -0
  12. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/cli.py +0 -0
  13. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/client.py +0 -0
  14. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/__init__.py +0 -0
  15. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/auth_commands.py +0 -0
  16. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/cron_commands.py +0 -0
  17. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/doctor_command.py +0 -0
  18. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/eval_commands.py +0 -0
  19. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/journal_commands.py +0 -0
  20. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/plan_commands.py +0 -0
  21. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/risk_commands.py +0 -0
  22. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/scan_commands.py +0 -0
  23. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/commands/size_commands.py +0 -0
  24. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/config.py +0 -0
  25. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/confirmation.py +0 -0
  26. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/credits.py +0 -0
  27. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/cron.py +0 -0
  28. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/display/__init__.py +0 -0
  29. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/display/chat_renderer.py +0 -0
  30. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/display/formatters.py +0 -0
  31. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/display/tables.py +0 -0
  32. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/display/theme.py +0 -0
  33. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/hooks.py +0 -0
  34. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/logging.py +0 -0
  35. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/model_failover.py +0 -0
  36. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/orchestrator.py +0 -0
  37. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/profile.py +0 -0
  38. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/store.py +0 -0
  39. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/streaming.py +0 -0
  40. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/tool_router.py +0 -0
  41. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/neo/types.py +0 -0
  42. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/__init__.py +0 -0
  43. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_auth.py +0 -0
  44. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_chat_helpers.py +0 -0
  45. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_chat_renderer.py +0 -0
  46. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_cli.py +0 -0
  47. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_config.py +0 -0
  48. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_confirmation.py +0 -0
  49. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_credits.py +0 -0
  50. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_cron.py +0 -0
  51. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_doctor.py +0 -0
  52. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_formatters.py +0 -0
  53. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_hooks.py +0 -0
  54. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_logging.py +0 -0
  55. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_model_failover.py +0 -0
  56. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_orchestrator.py +0 -0
  57. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_profile.py +0 -0
  58. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_store.py +0 -0
  59. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_streaming.py +0 -0
  60. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_tool_router.py +0 -0
  61. {systemr_cli-1.1.3 → systemr_cli-1.2.0}/tests/test_types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: systemr-cli
3
- Version: 1.1.3
3
+ Version: 1.2.0
4
4
  Summary: System R AI — trading operating system for agents
5
5
  Author-email: System R AI <ashim@systemr.ai>
6
6
  License-Expression: MIT
@@ -1,3 +1,3 @@
1
1
  """System R CLI — trading operating system in your terminal."""
2
2
 
3
- __version__ = "1.1.3"
3
+ __version__ = "1.2.0"
@@ -17,9 +17,7 @@ import httpx
17
17
  import structlog
18
18
  from prompt_toolkit import PromptSession
19
19
  from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
20
- from prompt_toolkit.formatted_text import HTML
21
20
  from prompt_toolkit.history import FileHistory
22
- from prompt_toolkit.styles import Style as PTStyle
23
21
 
24
22
  from neo.auth import AuthManager
25
23
  from neo.config import SYSTEMR_HOME, SESSIONS_DIR, ensure_systemr_home
@@ -223,16 +221,9 @@ def chat(ctx: click.Context, model_name: str | None, research: bool, resume: boo
223
221
  history_file = SYSTEMR_HOME / "chat_history"
224
222
  loop = asyncio.new_event_loop()
225
223
 
226
- # Dark theme for prompt_toolkit — matches terminal background
227
- pt_style = PTStyle.from_dict({
228
- "bottom-toolbar": "bg:#111114 #52525B",
229
- "prompt": "bold #F5F5F5",
230
- })
231
-
232
224
  prompt_session: PromptSession[str] = PromptSession(
233
225
  history=FileHistory(str(history_file)),
234
226
  auto_suggest=AutoSuggestFromHistory(),
235
- style=pt_style,
236
227
  )
237
228
 
238
229
  # Broker state (will be dynamic when broker connection is implemented)
@@ -245,29 +236,18 @@ def chat(ctx: click.Context, model_name: str | None, research: bool, resume: boo
245
236
 
246
237
  try:
247
238
  while True:
248
- # Status bar as prompt_toolkit bottom_toolbar (visible while typing)
249
- def _toolbar():
250
- if connected_broker:
251
- broker_html = f'<style fg="#3ECF8E">●</style> {connected_broker}'
252
- else:
253
- broker_html = '<style fg="#EF4444">○</style> broker not connected'
254
- return HTML(
255
- f' <style fg="#3ECF8E">●</style> {display_model}'
256
- f' <style fg="#3F3F46">│</style> {broker_html}'
257
- f' <style fg="#3F3F46">│</style> /help commands'
258
- )
259
-
260
239
  print_separator()
261
240
  try:
262
- user_input = prompt_session.prompt(
263
- " ❯ ",
264
- bottom_toolbar=_toolbar,
265
- ).strip()
241
+ user_input = prompt_session.prompt(" ❯ ").strip()
266
242
  except (EOFError, KeyboardInterrupt):
267
243
  console.print()
268
244
  console.print(f" [{DIM}]Session closed.[/]")
269
245
  break
270
246
 
247
+ # Bottom separator + status bar
248
+ print_separator()
249
+ print_prompt_bar(model=display_model, broker=connected_broker)
250
+
271
251
  if not user_input:
272
252
  continue
273
253
 
@@ -429,22 +409,33 @@ async def _do_chat(
429
409
  Returns:
430
410
  The collected assistant response text.
431
411
  """
412
+ import time as _time
413
+ import sys
414
+
432
415
  collected_text = ""
433
416
  tool_count = 0
434
417
  has_trade = False
418
+ streaming_started = False
419
+ start_time = _time.time()
435
420
 
436
421
  try:
437
422
  async for event in stream_chat(request, access_token):
438
423
  if event.event == "thinking":
439
- text = event.parsed.get("text", event.parsed.get("content", ""))
424
+ text = event.parsed.get("text", event.parsed.get("status", event.parsed.get("content", "")))
440
425
  if text:
441
- render_thinking(text[:80])
426
+ # Clear line and show thinking status
427
+ sys.stdout.write(f"\r \033[2m◐ {text[:70]}\033[0m\033[K")
428
+ sys.stdout.flush()
442
429
 
443
430
  elif event.event == "action":
444
431
  tool = event.parsed.get("action", event.parsed.get("tool", event.parsed.get("name", "")))
445
432
  params = event.parsed.get("parameters", event.parsed.get("args", {}))
446
433
  tool_count += 1
447
434
 
435
+ # Clear thinking line before showing tool
436
+ sys.stdout.write("\r\033[K")
437
+ sys.stdout.flush()
438
+
448
439
  # Fire BEFORE_TOOL_CALL hook — can inspect/log tool calls
449
440
  if tool:
450
441
  fire_hook(HookEvent.BEFORE_TOOL_CALL, context={
@@ -515,12 +506,29 @@ async def _do_chat(
515
506
  elif event.event == "text_delta":
516
507
  text = event.parsed.get("text", event.parsed.get("delta", event.data))
517
508
  if text and text != "null":
509
+ # Start green border on first chunk
510
+ if not streaming_started:
511
+ sys.stdout.write("\r\033[K") # Clear thinking line
512
+ sys.stdout.write(f"\n \033[38;2;62;207;142m┃\033[0m ")
513
+ streaming_started = True
514
+ # Stream text in real-time, handle newlines with border
515
+ for ch in text:
516
+ if ch == "\n":
517
+ sys.stdout.write(f"\n \033[38;2;62;207;142m┃\033[0m ")
518
+ else:
519
+ sys.stdout.write(ch)
520
+ sys.stdout.flush()
518
521
  collected_text += text
519
522
 
520
523
  elif event.event == "done":
521
- if collected_text.strip():
522
- render_assistant_message(collected_text.strip())
523
- else:
524
+ # Close the streaming block
525
+ if streaming_started:
526
+ elapsed = _time.time() - start_time
527
+ sys.stdout.write(f"\n \033[38;2;62;207;142m┃\033[0m")
528
+ sys.stdout.write(f"\n\n \033[2m✦ {elapsed:.1f}s\033[0m")
529
+ sys.stdout.write("\n")
530
+ sys.stdout.flush()
531
+ elif not collected_text.strip():
524
532
  full = event.parsed.get(
525
533
  "response", event.parsed.get("content", ""),
526
534
  )
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "systemr-cli"
7
- version = "1.1.3"
7
+ version = "1.2.0"
8
8
  description = "System R AI — trading operating system for agents"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes