cli-memory-os 0.1.8__tar.gz → 0.1.10__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 (69) hide show
  1. {cli_memory_os-0.1.8/cli_memory_os.egg-info → cli_memory_os-0.1.10}/PKG-INFO +1 -1
  2. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/tui/app.py +97 -60
  3. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10/cli_memory_os.egg-info}/PKG-INFO +1 -1
  4. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/pyproject.toml +1 -1
  5. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/tests/test_tui.py +19 -19
  6. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/LICENSE +0 -0
  7. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/MANIFEST.in +0 -0
  8. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/README.md +0 -0
  9. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/__init__.py +0 -0
  10. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/__init__.py +0 -0
  11. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/ask.py +0 -0
  12. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/benchmark.py +0 -0
  13. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/config_cmd.py +0 -0
  14. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/doctor.py +0 -0
  15. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/export.py +0 -0
  16. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/import_cmd.py +0 -0
  17. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/init.py +0 -0
  18. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/logs.py +0 -0
  19. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/monitor.py +0 -0
  20. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/plugins.py +0 -0
  21. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/restart.py +0 -0
  22. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/start.py +0 -0
  23. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/status.py +0 -0
  24. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/stop.py +0 -0
  25. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/sync.py +0 -0
  26. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/version.py +0 -0
  27. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/commands/workspace.py +0 -0
  28. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/main.py +0 -0
  29. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/parser.py +0 -0
  30. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli/tui/__init__.py +0 -0
  31. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli_memory_os.egg-info/SOURCES.txt +0 -0
  32. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli_memory_os.egg-info/dependency_links.txt +0 -0
  33. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli_memory_os.egg-info/entry_points.txt +0 -0
  34. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli_memory_os.egg-info/requires.txt +0 -0
  35. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/cli_memory_os.egg-info/top_level.txt +0 -0
  36. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/connectors/__init__.py +0 -0
  37. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/connectors/base.py +0 -0
  38. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/connectors/github.py +0 -0
  39. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/connectors/gmail.py +0 -0
  40. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/connectors/notion.py +0 -0
  41. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/connectors/registry.py +0 -0
  42. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/core/__init__.py +0 -0
  43. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/core/chunker.py +0 -0
  44. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/core/context_builder.py +0 -0
  45. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/core/embedder.py +0 -0
  46. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/core/llm.py +0 -0
  47. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/core/vector_store.py +0 -0
  48. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/infrastructure/__init__.py +0 -0
  49. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/infrastructure/compose.py +0 -0
  50. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/infrastructure/config.py +0 -0
  51. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/infrastructure/docker.py +0 -0
  52. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/infrastructure/health.py +0 -0
  53. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/infrastructure/observability.py +0 -0
  54. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/infrastructure/workspace.py +0 -0
  55. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/models/__init__.py +0 -0
  56. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/models/memory.py +0 -0
  57. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/setup.cfg +0 -0
  58. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/storage/__init__.py +0 -0
  59. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/storage/db.py +0 -0
  60. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/storage/graph.py +0 -0
  61. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/storage/schema.sql +0 -0
  62. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/storage/tech_detector.py +0 -0
  63. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/tests/test_cli_integration.py +0 -0
  64. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/tests/test_commands_phase2.py +0 -0
  65. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/tests/test_compose_manager.py +0 -0
  66. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/tests/test_first_time_user_experience.py +0 -0
  67. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/tests/test_infrastructure_stabilization.py +0 -0
  68. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/tests/test_sync_ask_cli.py +0 -0
  69. {cli_memory_os-0.1.8 → cli_memory_os-0.1.10}/tests/test_v1_features.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cli-memory-os
3
- Version: 0.1.8
3
+ Version: 0.1.10
4
4
  Summary: CLI-based Personal Knowledge Operating System
5
5
  Author-email: Anirudh T <anirudh200584@gmail.com>
6
6
  License-Expression: MIT
@@ -159,31 +159,44 @@ class Sidebar(Static):
159
159
  f"Gmail: {self.gmail_status}\n"
160
160
  f"Notion: {self.notion_status}\n\n"
161
161
  f"[bold cyan]⌨️ Shortcuts[/bold cyan]\n"
162
- f"[cyan]C[/cyan]: Chat\n"
163
- f"[cyan]S[/cyan]: Sync\n"
164
- f"[cyan]D[/cyan]: Doctor\n"
165
- f"[cyan]G[/cyan]: Graph\n"
166
- f"[cyan]F[/cyan]: Find / Search\n"
167
- f"[cyan]M[/cyan]: Monitor\n"
168
- f"[cyan]E[/cyan]: Settings\n"
169
- f"[cyan]Q[/cyan]: Quit"
162
+ f"[cyan]ctrl+1[/cyan]: Chat\n"
163
+ f"[cyan]ctrl+2[/cyan]: Sync\n"
164
+ f"[cyan]ctrl+3[/cyan]: Doctor\n"
165
+ f"[cyan]ctrl+4[/cyan]: Graph\n"
166
+ f"[cyan]ctrl+5[/cyan]: Search\n"
167
+ f"[cyan]ctrl+6[/cyan]: Monitor\n"
168
+ f"[cyan]ctrl+7[/cyan]: Settings\n"
169
+ f"[cyan]ctrl+q[/cyan]: Quit"
170
170
  )
171
- self.update(Panel(content, title="Memory-OS", border_style="cyan"))
171
+ self.update(Panel(content, title="Memory-OS", border_style="#1F2937"))
172
172
 
173
173
 
174
- class ChatPanel(Static):
174
+ class ChatPanel(Container):
175
175
  """Main Chat Interface supporting streaming responses and input field."""
176
176
 
177
177
  def compose(self) -> ComposeResult:
178
178
  with Vertical(id="chat_container"):
179
179
  with VerticalScroll(id="chat_history_scroll"):
180
+ welcome_md = (
181
+ "```\n"
182
+ " __ __ ____ ____\n"
183
+ "| \\/ | ___ _ __ ___ ___ _ __ _ _ / ___| / ___|\n"
184
+ "| |\\/| |/ _ \\ '_ ` _ \\ / _ \\| '__| | | | \\___ \\| |\n"
185
+ "| | | | __/ | | | | | (_) | | | |_| | ___) | |___\n"
186
+ "|_| |_|\\___|_| |_| |_|\\___/|_| \\__, | |____/ \\____|\n"
187
+ " |___/\n"
188
+ "```\n"
189
+ "**Grounded Personal Knowledge Operating System**\n\n"
190
+ "Ask questions grounded against your connected workspace: repositories, documentation files, and synced emails.\n\n"
191
+ "💡 *Tip: Try asking: 'tell me about my projects' or 'what repositories use Python?'*"
192
+ )
180
193
  yield Static(
181
- RichMarkdown("# Memory-OS RAG Assistant\nAsk any question grounded against your indexed sources! Try asking about your repositories, emails, or technologies used."),
194
+ RichMarkdown(welcome_md),
182
195
  id="welcome_message"
183
196
  )
184
197
  with Horizontal(id="input_bar"):
198
+ yield Label("❯", id="prompt_symbol")
185
199
  yield Input(placeholder="Ask a question...", id="chat_input")
186
- yield Button("Send", id="chat_send_btn", variant="primary")
187
200
 
188
201
  def on_mount(self) -> None:
189
202
  self.query_one("#chat_input").focus()
@@ -194,10 +207,6 @@ class ChatPanel(Static):
194
207
  async def on_input_submitted(self, event: Input.Submitted) -> None:
195
208
  await self.process_message()
196
209
 
197
- async def on_button_pressed(self, event: Button.Pressed) -> None:
198
- if event.button.id == "chat_send_btn":
199
- await self.process_message()
200
-
201
210
  async def process_message(self) -> None:
202
211
  chat_input = self.query_one("#chat_input", Input)
203
212
  user_text = chat_input.value.strip()
@@ -212,20 +221,20 @@ class ChatPanel(Static):
212
221
  except Exception:
213
222
  pass
214
223
 
215
- # Append User Message Bubble
224
+ # Append User Message
216
225
  history_scroll = self.query_one("#chat_history_scroll")
226
+ user_markup = f"[bold green]● You[/bold green]\n\n{user_text}"
217
227
  history_scroll.mount(
218
- Static(Panel(user_text, title="[bold green]You[/bold green]", border_style="green"), classes="chat_msg_user")
228
+ Static(user_markup, classes="chat_msg_user")
219
229
  )
220
230
 
221
- # Append Assistant Loading/Streaming Message Bubble
222
- agent_msg = Static(Panel("Thinking...", title="[bold cyan]Memory-OS[/bold cyan]", border_style="cyan"), classes="chat_msg_agent")
231
+ # Append Assistant Loading/Streaming Message
232
+ agent_msg = Static("[bold cyan]● Memory-OS[/bold cyan]\n\n[italic dim]Thinking...[/italic dim]", classes="chat_msg_agent")
223
233
  history_scroll.mount(agent_msg)
224
234
  self.scroll_to_bottom()
225
235
 
226
236
  # Disable input while processing
227
237
  chat_input.disabled = True
228
- self.query_one("#chat_send_btn").disabled = True
229
238
 
230
239
  # Run generator task in a background worker
231
240
  self.run_worker(self.stream_response(user_text, agent_msg))
@@ -240,7 +249,7 @@ class ChatPanel(Static):
240
249
  try:
241
250
  gen = await loop.run_in_executor(executor, get_generator)
242
251
  except Exception as e:
243
- response_widget.update(Panel(f"Error: {e}", title="[bold red]Error[/bold red]", border_style="red"))
252
+ response_widget.update(f"[bold red]● Error[/bold red]\n\n{e}")
244
253
  self.enable_input()
245
254
  return
246
255
 
@@ -255,14 +264,14 @@ class ChatPanel(Static):
255
264
  except StopIteration:
256
265
  break
257
266
  except Exception as e:
258
- response_widget.update(Panel(f"Error: {e}", title="[bold red]Error[/bold red]", border_style="red"))
267
+ response_widget.update(f"[bold red]● Error[/bold red]\n\n{e}")
259
268
  break
260
269
 
261
270
  if item["type"] == "diagnostics":
262
271
  query_class = item["data"].get("query_class", "Unknown")
263
272
  elif item["type"] == "token":
264
273
  answer_text += item["content"]
265
- response_widget.update(Panel(answer_text, title=f"[bold cyan]Memory-OS ({query_class})[/bold cyan]", border_style="cyan"))
274
+ response_widget.update(f"[bold cyan]● Memory-OS ({query_class})[/bold cyan]\n\n{answer_text}")
266
275
  self.scroll_to_bottom()
267
276
  elif item["type"] == "done":
268
277
  sources = item["sources"]
@@ -280,7 +289,7 @@ class ChatPanel(Static):
280
289
  metadata.append(f"**Confidence**: {confidence:.1f}")
281
290
  final_md += "\n\n---\n" + "\n".join(metadata)
282
291
 
283
- response_widget.update(Panel(RichMarkdown(final_md), title=f"[bold cyan]Memory-OS ({query_class})[/bold cyan]", border_style="cyan"))
292
+ response_widget.update(RichMarkdown(f"### ● Memory-OS ({query_class})\n\n{final_md}"))
284
293
  self.scroll_to_bottom()
285
294
 
286
295
  self.enable_input()
@@ -288,12 +297,11 @@ class ChatPanel(Static):
288
297
  def enable_input(self) -> None:
289
298
  chat_input = self.query_one("#chat_input", Input)
290
299
  chat_input.disabled = False
291
- self.query_one("#chat_send_btn").disabled = False
292
300
  chat_input.focus()
293
301
  self.scroll_to_bottom()
294
302
 
295
303
 
296
- class DoctorPanel(Static):
304
+ class DoctorPanel(Container):
297
305
  """System diagnostic view execution wizard."""
298
306
 
299
307
  def compose(self) -> ComposeResult:
@@ -354,11 +362,11 @@ class DoctorPanel(Static):
354
362
  report.append("=" * 45)
355
363
  report.append(f"Summary: [bold]{healthy_count}/{len(results)}[/bold] services are functional.")
356
364
 
357
- results_static.update(Panel("\n".join(report), border_style="cyan"))
365
+ results_static.update(Panel("\n".join(report), border_style="#1F2937"))
358
366
  btn.disabled = False
359
367
 
360
368
 
361
- class SyncPanel(Static):
369
+ class SyncPanel(Container):
362
370
  """Workspace synchronization action board."""
363
371
 
364
372
  def compose(self) -> ComposeResult:
@@ -453,13 +461,13 @@ class SyncPanel(Static):
453
461
  return mystdout.getvalue()
454
462
 
455
463
  output = await loop.run_in_executor(executor, run_sync_redirected)
456
- log_widget.update(Panel(output, title="Sync Log Output", border_style="cyan"))
464
+ log_widget.update(Panel(output, title="Sync Log Output", border_style="#1F2937"))
457
465
 
458
466
  btn_all.disabled = False
459
467
  btn_rebuild.disabled = False
460
468
 
461
469
 
462
- class GraphPanel(Static):
470
+ class GraphPanel(Container):
463
471
  """View graph metrics and technological detections."""
464
472
 
465
473
  def compose(self) -> ComposeResult:
@@ -530,10 +538,10 @@ class GraphPanel(Static):
530
538
  for r_name, lang in repos:
531
539
  stats_text += f" - [white]{r_name}[/white] : {lang or 'Unknown'}\n"
532
540
 
533
- self.query_one("#graph_stats", Static).update(Panel(stats_text, border_style="cyan"))
541
+ self.query_one("#graph_stats", Static).update(Panel(stats_text, border_style="#1F2937"))
534
542
 
535
543
 
536
- class SearchPanel(Static):
544
+ class SearchPanel(Container):
537
545
  """Semantic Finder View."""
538
546
 
539
547
  def compose(self) -> ComposeResult:
@@ -598,7 +606,7 @@ class SearchPanel(Static):
598
606
  results_static.update("\n".join(report))
599
607
 
600
608
 
601
- class MonitorPanel(Static):
609
+ class MonitorPanel(Container):
602
610
  """Latency dashboard displaying performance parser metrics."""
603
611
 
604
612
  def compose(self) -> ComposeResult:
@@ -633,17 +641,17 @@ class MonitorPanel(Static):
633
641
  f" - [bold cyan]Average LLM generation[/bold cyan]: {avg(l_times):.2f}s ({len(l_times)} calls)\n"
634
642
  f" - [bold cyan]Average Embedding Gen[/bold cyan] : {avg([x[0] for x in e_times]):.2f}s ({len(e_times)} runs)\n"
635
643
  f" - [bold cyan]Average Qdrant Upload[/bold cyan] : {avg([x[0] for x in v_uploads]):.2f}s ({len(v_uploads)} runs)\n\n"
636
- f"[bold cyan]📊 Recent Log Details[/bold cyan]\n"
644
+ f"[bold cyan] Recent Log Details[/bold cyan]\n"
637
645
  )
638
646
  if r_times:
639
647
  stats_text += f" - Last RAG execution: {r_times[-1]:.2f}s\n"
640
648
  if l_times:
641
649
  stats_text += f" - Last Groq response: {l_times[-1]:.2f}s\n"
642
650
 
643
- self.query_one("#monitor_stats", Static).update(Panel(stats_text, border_style="cyan"))
651
+ self.query_one("#monitor_stats", Static).update(Panel(stats_text, border_style="#1F2937"))
644
652
 
645
653
 
646
- class SettingsPanel(Static):
654
+ class SettingsPanel(Container):
647
655
  """View active configs and workspaces."""
648
656
 
649
657
  def compose(self) -> ComposeResult:
@@ -668,7 +676,7 @@ class SettingsPanel(Static):
668
676
  f"Groq Model: {cfg.get('groq', {}).get('model', 'llama-3.3-70b-versatile')}\n"
669
677
  f"Embedding Model: {cfg.get('embeddings', {}).get('model', 'all-MiniLM-L6-v2')}\n"
670
678
  )
671
- self.query_one("#settings_details", Static).update(Panel(details, border_style="cyan"))
679
+ self.query_one("#settings_details", Static).update(Panel(details, border_style="#1F2937"))
672
680
 
673
681
 
674
682
  class MemoryOSTUIApp(App):
@@ -677,7 +685,7 @@ class MemoryOSTUIApp(App):
677
685
  TITLE = "Memory-OS Terminal UI"
678
686
  CSS = """
679
687
  Screen {
680
- background: #0f1419;
688
+ background: #0B0F19;
681
689
  }
682
690
 
683
691
  #main_layout {
@@ -687,8 +695,8 @@ class MemoryOSTUIApp(App):
687
695
  Sidebar {
688
696
  width: 35;
689
697
  height: 100%;
690
- background: #141923;
691
- border-right: solid cyan;
698
+ background: #111622;
699
+ border-right: solid #1F2937;
692
700
  }
693
701
 
694
702
  ContentSwitcher {
@@ -703,19 +711,24 @@ class MemoryOSTUIApp(App):
703
711
 
704
712
  #chat_history_scroll {
705
713
  height: 1fr;
706
- border: solid cyan;
714
+ border: solid #1F2937;
707
715
  margin-bottom: 1;
708
716
  padding: 1 2;
717
+ background: #0B0F19;
709
718
  }
710
719
 
711
720
  .chat_msg_user {
712
721
  margin: 1 0;
713
- align: right middle;
722
+ background: #161B22;
723
+ border-left: solid #10B981;
724
+ padding: 1 2;
714
725
  }
715
726
 
716
727
  .chat_msg_agent {
717
728
  margin: 1 0;
718
- align: left middle;
729
+ background: #111622;
730
+ border-left: solid #3B82F6;
731
+ padding: 1 2;
719
732
  }
720
733
 
721
734
  #input_bar {
@@ -725,14 +738,21 @@ class MemoryOSTUIApp(App):
725
738
 
726
739
  #chat_input {
727
740
  width: 1fr;
728
- background: #1c2333;
729
- border: solid cyan;
741
+ background: #161B22;
742
+ border: solid #1F2937;
730
743
  color: white;
731
744
  }
732
745
 
733
746
  #chat_send_btn {
734
747
  width: 12;
735
748
  margin-left: 1;
749
+ background: #1F2937;
750
+ color: white;
751
+ border: none;
752
+ }
753
+
754
+ #chat_send_btn:hover {
755
+ background: #3B82F6;
736
756
  }
737
757
 
738
758
  #search_bar {
@@ -742,25 +762,40 @@ class MemoryOSTUIApp(App):
742
762
 
743
763
  #search_query_input {
744
764
  width: 1fr;
745
- background: #1c2333;
746
- border: solid cyan;
765
+ background: #161B22;
766
+ border: solid #1F2937;
747
767
  color: white;
748
768
  }
749
769
 
750
770
  #search_run_btn {
751
771
  width: 12;
752
772
  margin-left: 1;
773
+ background: #1F2937;
774
+ color: white;
775
+ border: none;
776
+ }
777
+
778
+ #search_run_btn:hover {
779
+ background: #3B82F6;
753
780
  }
754
781
 
755
782
  #doctor_results_scroll, #sync_results_scroll, #search_results_scroll {
756
783
  height: 1fr;
757
- border: solid cyan;
784
+ border: solid #1F2937;
758
785
  margin-top: 1;
759
786
  padding: 1 2;
787
+ background: #0B0F19;
760
788
  }
761
789
 
762
790
  Button {
763
791
  min-width: 15;
792
+ background: #1F2937;
793
+ color: white;
794
+ border: none;
795
+ }
796
+
797
+ Button:hover {
798
+ background: #3B82F6;
764
799
  }
765
800
 
766
801
  Label {
@@ -769,23 +804,25 @@ class MemoryOSTUIApp(App):
769
804
  """
770
805
 
771
806
  BINDINGS = [
772
- Binding("ctrl+b", "toggle_sidebar", "Toggle Sidebar"),
773
- Binding("c", "switch_view('chat')", "Chat Screen"),
774
- Binding("s", "switch_view('sync')", "Sync Screen"),
775
- Binding("d", "switch_view('doctor')", "Doctor Screen"),
776
- Binding("g", "switch_view('graph')", "Graph Screen"),
777
- Binding("f", "switch_view('search')", "Search Screen"),
778
- Binding("m", "switch_view('monitor')", "Monitor Screen"),
779
- Binding("e", "switch_view('settings')", "Settings Screen"),
780
- Binding("q", "quit", "Quit"),
807
+ Binding("ctrl+b", "toggle_sidebar", "Sidebar"),
808
+ Binding("ctrl+1", "switch_view('chat')", "Chat"),
809
+ Binding("ctrl+2", "switch_view('sync')", "Sync"),
810
+ Binding("ctrl+3", "switch_view('doctor')", "Doctor"),
811
+ Binding("ctrl+4", "switch_view('graph')", "Graph"),
812
+ Binding("ctrl+5", "switch_view('search')", "Search"),
813
+ Binding("ctrl+6", "switch_view('monitor')", "Monitor"),
814
+ Binding("ctrl+7", "switch_view('settings')", "Settings"),
815
+ Binding("ctrl+q", "quit", "Quit"),
781
816
  ]
782
817
 
783
- sidebar_visible = reactive(True)
818
+ sidebar_visible = reactive(False)
784
819
 
785
820
  def compose(self) -> ComposeResult:
786
821
  yield Header(show_clock=True)
787
822
  with Horizontal(id="main_layout"):
788
- yield Sidebar(id="sidebar_menu")
823
+ sidebar = Sidebar(id="sidebar_menu")
824
+ sidebar.display = self.sidebar_visible
825
+ yield sidebar
789
826
  with ContentSwitcher(initial="chat", id="panel_switcher"):
790
827
  yield ChatPanel(id="chat")
791
828
  yield SyncPanel(id="sync")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cli-memory-os
3
- Version: 0.1.8
3
+ Version: 0.1.10
4
4
  Summary: CLI-based Personal Knowledge Operating System
5
5
  Author-email: Anirudh T <anirudh200584@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cli-memory-os"
3
- version = "0.1.8"
3
+ version = "0.1.10"
4
4
  description = "CLI-based Personal Knowledge Operating System"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -14,8 +14,8 @@ async def test_tui_app_boot_and_default_view():
14
14
  switcher = app.query_one("#panel_switcher")
15
15
  assert switcher.current == "chat"
16
16
 
17
- # Verify sidebar menu is visible initially
18
- assert app.sidebar_visible is True
17
+ # Verify sidebar menu is hidden initially
18
+ assert app.sidebar_visible is False
19
19
 
20
20
 
21
21
  @pytest.mark.asyncio
@@ -23,17 +23,17 @@ async def test_tui_sidebar_toggle():
23
23
  """Test sidebar visibility toggles on ctrl+b keystroke."""
24
24
  app = MemoryOSTUIApp()
25
25
  async with app.run_test() as pilot:
26
- assert app.sidebar_visible is True
26
+ assert app.sidebar_visible is False
27
27
 
28
28
  # Send ctrl+b
29
29
  await pilot.press("ctrl+b")
30
30
  await pilot.pause()
31
- assert app.sidebar_visible is False
31
+ assert app.sidebar_visible is True
32
32
 
33
33
  # Send ctrl+b again
34
34
  await pilot.press("ctrl+b")
35
35
  await pilot.pause()
36
- assert app.sidebar_visible is True
36
+ assert app.sidebar_visible is False
37
37
 
38
38
 
39
39
  @pytest.mark.asyncio
@@ -47,39 +47,39 @@ async def test_tui_view_switching():
47
47
  # Unfocus input before pressing hotkeys
48
48
  app.set_focus(None)
49
49
 
50
- # Press 's' to go to Sync
50
+ # Press 'ctrl+2' to go to Sync
51
51
  app.set_focus(None)
52
- await pilot.press("s")
52
+ await pilot.press("ctrl+2")
53
53
  assert switcher.current == "sync"
54
54
 
55
- # Press 'd' to go to Doctor
55
+ # Press 'ctrl+3' to go to Doctor
56
56
  app.set_focus(None)
57
- await pilot.press("d")
57
+ await pilot.press("ctrl+3")
58
58
  assert switcher.current == "doctor"
59
59
 
60
- # Press 'g' to go to Graph
60
+ # Press 'ctrl+4' to go to Graph
61
61
  app.set_focus(None)
62
- await pilot.press("g")
62
+ await pilot.press("ctrl+4")
63
63
  assert switcher.current == "graph"
64
64
 
65
- # Press 'f' to go to Search
65
+ # Press 'ctrl+5' to go to Search
66
66
  app.set_focus(None)
67
- await pilot.press("f")
67
+ await pilot.press("ctrl+5")
68
68
  assert switcher.current == "search"
69
69
 
70
- # Press 'm' to go to Monitor
70
+ # Press 'ctrl+6' to go to Monitor
71
71
  app.set_focus(None)
72
- await pilot.press("m")
72
+ await pilot.press("ctrl+6")
73
73
  assert switcher.current == "monitor"
74
74
 
75
- # Press 'e' to go to Settings
75
+ # Press 'ctrl+7' to go to Settings
76
76
  app.set_focus(None)
77
- await pilot.press("e")
77
+ await pilot.press("ctrl+7")
78
78
  assert switcher.current == "settings"
79
79
 
80
- # Press 'c' to return to Chat
80
+ # Press 'ctrl+1' to return to Chat
81
81
  app.set_focus(None)
82
- await pilot.press("c")
82
+ await pilot.press("ctrl+1")
83
83
  assert switcher.current == "chat"
84
84
 
85
85
 
File without changes
File without changes
File without changes