pico-cli 0.1.1__tar.gz → 0.1.2__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 (109) hide show
  1. {pico_cli-0.1.1 → pico_cli-0.1.2}/PKG-INFO +34 -1
  2. {pico_cli-0.1.1 → pico_cli-0.1.2}/README.md +33 -0
  3. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/pyproject.toml +1 -1
  4. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/pyproject.toml +1 -1
  5. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/pyproject.toml +1 -1
  6. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/pyproject.toml +1 -1
  7. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/app.py +16 -2
  8. {pico_cli-0.1.1 → pico_cli-0.1.2}/pyproject.toml +1 -1
  9. pico_cli-0.1.2/tests/test_first_run_setup.py +70 -0
  10. {pico_cli-0.1.1 → pico_cli-0.1.2}/uv.lock +5 -5
  11. pico_cli-0.1.1/IMPLEMENTATION_SUMMARY.md +0 -80
  12. {pico_cli-0.1.1 → pico_cli-0.1.2}/.gitignore +0 -0
  13. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/headless-agent/issues/01-unified-ai-call.md +0 -0
  14. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/headless-agent/issues/02-tracer-bullet-headless-text-response.md +0 -0
  15. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/headless-agent/issues/03-tools.md +0 -0
  16. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/headless-agent/issues/04-session-fork.md +0 -0
  17. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/headless-agent/issues/05-compaction.md +0 -0
  18. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/headless-agent/issues/06-extension-binding.md +0 -0
  19. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/headless-agent/issues/07-config-file.md +0 -0
  20. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/headless-agent/spec.md +0 -0
  21. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/pico-tui/spec.md +0 -0
  22. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/trace-view/01-assistant-duration.md +0 -0
  23. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/trace-view/02-row-assembly.md +0 -0
  24. {pico_cli-0.1.1 → pico_cli-0.1.2}/.scratch/trace-view/03-overlay.md +0 -0
  25. {pico_cli-0.1.1 → pico_cli-0.1.2}/AGENTS.md +0 -0
  26. {pico_cli-0.1.1 → pico_cli-0.1.2}/CONTEXT.md +0 -0
  27. {pico_cli-0.1.1 → pico_cli-0.1.2}/LICENSE +0 -0
  28. {pico_cli-0.1.1 → pico_cli-0.1.2}/docs/adr/0001-monorepo-package-split.md +0 -0
  29. {pico_cli-0.1.1 → pico_cli-0.1.2}/docs/adr/0002-tree-based-session.md +0 -0
  30. {pico_cli-0.1.1 → pico_cli-0.1.2}/docs/adr/0003-hardcoded-core.md +0 -0
  31. {pico_cli-0.1.1 → pico_cli-0.1.2}/docs/adr/0004-native-provider-adapters.md +0 -0
  32. {pico_cli-0.1.1 → pico_cli-0.1.2}/docs/adr/0005-task-tool-subagents.md +0 -0
  33. {pico_cli-0.1.1 → pico_cli-0.1.2}/docs/adr/0006-trace-view-durations.md +0 -0
  34. {pico_cli-0.1.1 → pico_cli-0.1.2}/docs/agents/domain.md +0 -0
  35. {pico_cli-0.1.1 → pico_cli-0.1.2}/docs/agents/issue-tracker.md +0 -0
  36. {pico_cli-0.1.1 → pico_cli-0.1.2}/docs/agents/triage-labels.md +0 -0
  37. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/README.md +0 -0
  38. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/__init__.py +0 -0
  39. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/openrouter.py +0 -0
  40. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/provider.py +0 -0
  41. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/providers/__init__.py +0 -0
  42. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/providers/_compat.py +0 -0
  43. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/providers/anthropic.py +0 -0
  44. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/providers/deepseek.py +0 -0
  45. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/providers/gemini.py +0 -0
  46. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/providers/ollama.py +0 -0
  47. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/providers/openai.py +0 -0
  48. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/providers/spec.py +0 -0
  49. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/py.typed +0 -0
  50. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_ai/src/pico_ai/types.py +0 -0
  51. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/README.md +0 -0
  52. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/src/pico_core/__init__.py +0 -0
  53. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/src/pico_core/fsm.py +0 -0
  54. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/src/pico_core/py.typed +0 -0
  55. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/src/pico_core/session.py +0 -0
  56. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/src/pico_core/subagents.py +0 -0
  57. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/src/pico_core/todos.py +0 -0
  58. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/src/pico_core/tools.py +0 -0
  59. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_core/src/pico_core/trace.py +0 -0
  60. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/README.md +0 -0
  61. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/src/pico_sdk/__init__.py +0 -0
  62. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/src/pico_sdk/__main__.py +0 -0
  63. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/src/pico_sdk/cli.py +0 -0
  64. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/src/pico_sdk/config.py +0 -0
  65. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/src/pico_sdk/extensions.py +0 -0
  66. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/src/pico_sdk/providers.py +0 -0
  67. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/src/pico_sdk/py.typed +0 -0
  68. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/src/pico_sdk/session.py +0 -0
  69. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_sdk/src/pico_sdk/skills.py +0 -0
  70. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/README.md +0 -0
  71. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/__init__.py +0 -0
  72. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/commands.py +0 -0
  73. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/history_picker.py +0 -0
  74. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/modal.py +0 -0
  75. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/model_picker.py +0 -0
  76. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/provider_form.py +0 -0
  77. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/provider_picker.py +0 -0
  78. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/py.typed +0 -0
  79. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/render.py +0 -0
  80. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/skill_picker.py +0 -0
  81. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/status_bar.py +0 -0
  82. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/todo_panel.py +0 -0
  83. {pico_cli-0.1.1 → pico_cli-0.1.2}/packages/pico_tui/src/pico_tui/trace_view.py +0 -0
  84. {pico_cli-0.1.1 → pico_cli-0.1.2}/src/pico/__init__.py +0 -0
  85. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/conftest.py +0 -0
  86. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_agent_session.py +0 -0
  87. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_ai_call.py +0 -0
  88. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_cli.py +0 -0
  89. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_config.py +0 -0
  90. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_extensions.py +0 -0
  91. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_first_token_timeout.py +0 -0
  92. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_fsm.py +0 -0
  93. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_history_picker.py +0 -0
  94. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_model_persistence.py +0 -0
  95. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_model_picker.py +0 -0
  96. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_picker_search.py +0 -0
  97. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_pointer_shape.py +0 -0
  98. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_providers.py +0 -0
  99. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_result_display.py +0 -0
  100. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_session.py +0 -0
  101. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_skill_picker.py +0 -0
  102. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_status_bar.py +0 -0
  103. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_stream_order.py +0 -0
  104. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_subagents.py +0 -0
  105. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_todos.py +0 -0
  106. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_tools.py +0 -0
  107. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_trace.py +0 -0
  108. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_trace_view.py +0 -0
  109. {pico_cli-0.1.1 → pico_cli-0.1.2}/tests/test_tui.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pico-cli
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: A Python CLI coding agent — autonomous, tool-using, and session-persistent.
5
5
  Project-URL: Homepage, https://github.com/Arya-Ojha/PicoCLI_Learn
6
6
  Project-URL: Repository, https://github.com/Arya-Ojha/PicoCLI_Learn
@@ -84,6 +84,39 @@ In the TUI, `/provider` opens a picker with ✓/✗ setup status, then a setup f
84
84
 
85
85
  ## Installation
86
86
 
87
+ Requires Python **3.12+**.
88
+
89
+ ```bash
90
+ # recommended: isolated install — `picocli` + `picocli-chat` work in any
91
+ # directory, like `npm i -g`
92
+ pipx install pico-cli
93
+
94
+ # ... or via uv (same result)
95
+ uv tool install pico-cli
96
+
97
+ # plain pip also works (see the Windows PATH note below)
98
+ pip install pico-cli
99
+
100
+ # try without installing (npx-style)
101
+ uvx pico-cli --help
102
+ ```
103
+
104
+ Then open a terminal **in any directory** and run `picocli`. On first launch (no API key yet) the provider setup opens automatically — pick a provider, paste the key, done. Keys can also come from environment variables (see Configuration below).
105
+
106
+ ### Windows: `pip install` and PATH
107
+
108
+ `pip --user` installs (the default when site-packages isn't writable) drop the commands into `~/.local`-style user Scripts, which is often **not** on PATH — that's when `picocli` is "not recognized". Prefer `pipx`/`uv tool` above, or add the dir once (then open a fresh terminal):
109
+
110
+ ```powershell
111
+ $userPath = [Environment]::GetEnvironmentVariable("Path", "User")
112
+ $newDir = "$env:APPDATA\Python\Python314\Scripts" # adjust version to yours
113
+ if ($userPath -split ";" -notcontains $newDir) {
114
+ [Environment]::SetEnvironmentVariable("Path", "$userPath;$newDir", "User")
115
+ }
116
+ ```
117
+
118
+ ### From source (contributors)
119
+
87
120
  ```bash
88
121
  uv sync
89
122
  ```
@@ -59,6 +59,39 @@ In the TUI, `/provider` opens a picker with ✓/✗ setup status, then a setup f
59
59
 
60
60
  ## Installation
61
61
 
62
+ Requires Python **3.12+**.
63
+
64
+ ```bash
65
+ # recommended: isolated install — `picocli` + `picocli-chat` work in any
66
+ # directory, like `npm i -g`
67
+ pipx install pico-cli
68
+
69
+ # ... or via uv (same result)
70
+ uv tool install pico-cli
71
+
72
+ # plain pip also works (see the Windows PATH note below)
73
+ pip install pico-cli
74
+
75
+ # try without installing (npx-style)
76
+ uvx pico-cli --help
77
+ ```
78
+
79
+ Then open a terminal **in any directory** and run `picocli`. On first launch (no API key yet) the provider setup opens automatically — pick a provider, paste the key, done. Keys can also come from environment variables (see Configuration below).
80
+
81
+ ### Windows: `pip install` and PATH
82
+
83
+ `pip --user` installs (the default when site-packages isn't writable) drop the commands into `~/.local`-style user Scripts, which is often **not** on PATH — that's when `picocli` is "not recognized". Prefer `pipx`/`uv tool` above, or add the dir once (then open a fresh terminal):
84
+
85
+ ```powershell
86
+ $userPath = [Environment]::GetEnvironmentVariable("Path", "User")
87
+ $newDir = "$env:APPDATA\Python\Python314\Scripts" # adjust version to yours
88
+ if ($userPath -split ";" -notcontains $newDir) {
89
+ [Environment]::SetEnvironmentVariable("Path", "$userPath;$newDir", "User")
90
+ }
91
+ ```
92
+
93
+ ### From source (contributors)
94
+
62
95
  ```bash
63
96
  uv sync
64
97
  ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pico-cli-ai"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "LLM abstraction and protocol normalisation."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pico-cli-core"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "Agent loop and session tree."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pico-cli-sdk"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "Headless library API and extension/plugin binding."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pico-cli-tui"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "Terminal user interface view."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -357,10 +357,20 @@ class PicoApp(App[None]):
357
357
  ("f1", "show_help", "Help"),
358
358
  ]
359
359
 
360
- def __init__(self, mgr: _SessionManager, *, startup_notice: str = "") -> None:
360
+ def __init__(
361
+ self,
362
+ mgr: _SessionManager,
363
+ *,
364
+ startup_notice: str = "",
365
+ auto_setup: bool = False,
366
+ ) -> None:
361
367
  super().__init__()
362
368
  self._mgr = mgr
363
369
  self._startup_notice = startup_notice
370
+ # First-run onboarding: when True and the active provider is
371
+ # missing required config, the provider picker opens on launch
372
+ # so keys/URLs are entered in-UI instead of discovered via /help.
373
+ self._auto_setup = auto_setup
364
374
  self._streaming = False
365
375
  # Everything written to the chat log, in order. Thinking blocks are
366
376
  # stored as ThinkingSegment so they can collapse/expand on click.
@@ -399,6 +409,10 @@ class PicoApp(App[None]):
399
409
  self._write_chat(
400
410
  Panel(self._startup_notice, title="setup", border_style="yellow")
401
411
  )
412
+ if self._auto_setup:
413
+ settings = self._mgr.session.settings
414
+ if missing_required(settings.provider, settings):
415
+ self.call_after_refresh(self._show_provider_picker)
402
416
 
403
417
  def _refresh_todo_panel(self) -> None:
404
418
  """Re-render the todo side panel (auto-hides while empty)."""
@@ -955,7 +969,7 @@ def main(argv: list[str] | None = None) -> int:
955
969
  f"Provider {provider_label} is missing required config: "
956
970
  f"{', '.join(missing)}. Use /provider to configure it."
957
971
  )
958
- app = PicoApp(mgr, startup_notice=startup_notice)
972
+ app = PicoApp(mgr, startup_notice=startup_notice, auto_setup=True)
959
973
  app.run()
960
974
  return 0
961
975
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pico-cli"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "A Python CLI coding agent — autonomous, tool-using, and session-persistent."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -0,0 +1,70 @@
1
+ """First-run onboarding: missing provider config auto-opens setup."""
2
+
3
+ import pytest
4
+
5
+ from pico_sdk.config import Settings
6
+ from pico_sdk.providers import create_provider, missing_required
7
+ from pico_tui.app import PicoApp, _SessionManager
8
+ from pico_tui.provider_picker import ProviderPickerScreen
9
+
10
+ from conftest import FakeProvider, make_session
11
+
12
+
13
+ @pytest.fixture
14
+ def fresh_settings(monkeypatch):
15
+ """Settings as on a brand-new machine: no keys anywhere."""
16
+ for var in (
17
+ "OPENROUTER_API_KEY",
18
+ "OPENAI_API_KEY",
19
+ "ANTHROPIC_API_KEY",
20
+ "GOOGLE_API_KEY",
21
+ "DEEPSEEK_API_KEY",
22
+ ):
23
+ monkeypatch.delenv(var, raising=False)
24
+ settings = Settings()
25
+ assert missing_required(settings.provider, settings), "expected missing config"
26
+ return settings
27
+
28
+
29
+ def _app(tmp_path, settings, auto_setup=False):
30
+ session = make_session(
31
+ FakeProvider([]), tmp_path, settings=settings, load_skills=False
32
+ )
33
+ return PicoApp(_SessionManager(session), auto_setup=auto_setup)
34
+
35
+
36
+ async def test_missing_config_auto_opens_provider_picker(tmp_path, fresh_settings):
37
+ app = _app(tmp_path, fresh_settings, auto_setup=True)
38
+ async with app.run_test() as pilot:
39
+ await pilot.pause()
40
+ await pilot.pause()
41
+ assert isinstance(app.screen, ProviderPickerScreen)
42
+
43
+
44
+ async def test_auto_setup_off_by_default(tmp_path, fresh_settings):
45
+ app = _app(tmp_path, fresh_settings)
46
+ async with app.run_test() as pilot:
47
+ await pilot.pause()
48
+ assert not isinstance(app.screen, ProviderPickerScreen)
49
+
50
+
51
+ async def test_configured_never_auto_opens(tmp_path, monkeypatch):
52
+ monkeypatch.setenv("OPENROUTER_API_KEY", "test-key")
53
+ settings = Settings()
54
+ assert not missing_required(settings.provider, settings)
55
+ session = make_session(
56
+ create_provider(settings), tmp_path, settings=settings, load_skills=False
57
+ )
58
+ app = PicoApp(_SessionManager(session), auto_setup=True)
59
+ async with app.run_test() as pilot:
60
+ await pilot.pause()
61
+ await pilot.pause()
62
+ assert not isinstance(app.screen, ProviderPickerScreen)
63
+
64
+
65
+ def test_main_requests_auto_setup():
66
+ import inspect
67
+
68
+ from pico_tui.app import main
69
+
70
+ assert "auto_setup=True" in inspect.getsource(main)
@@ -408,7 +408,7 @@ wheels = [
408
408
 
409
409
  [[package]]
410
410
  name = "pico-cli"
411
- version = "0.1.1"
411
+ version = "0.1.2"
412
412
  source = { editable = "." }
413
413
  dependencies = [
414
414
  { name = "pico-cli-sdk" },
@@ -437,7 +437,7 @@ dev = [
437
437
 
438
438
  [[package]]
439
439
  name = "pico-cli-ai"
440
- version = "0.1.1"
440
+ version = "0.1.2"
441
441
  source = { editable = "packages/pico_ai" }
442
442
  dependencies = [
443
443
  { name = "httpx" },
@@ -452,7 +452,7 @@ requires-dist = [
452
452
 
453
453
  [[package]]
454
454
  name = "pico-cli-core"
455
- version = "0.1.1"
455
+ version = "0.1.2"
456
456
  source = { editable = "packages/pico_core" }
457
457
  dependencies = [
458
458
  { name = "httpx" },
@@ -469,7 +469,7 @@ requires-dist = [
469
469
 
470
470
  [[package]]
471
471
  name = "pico-cli-sdk"
472
- version = "0.1.1"
472
+ version = "0.1.2"
473
473
  source = { editable = "packages/pico_sdk" }
474
474
  dependencies = [
475
475
  { name = "pico-cli-ai" },
@@ -486,7 +486,7 @@ requires-dist = [
486
486
 
487
487
  [[package]]
488
488
  name = "pico-cli-tui"
489
- version = "0.1.1"
489
+ version = "0.1.2"
490
490
  source = { editable = "packages/pico_tui" }
491
491
  dependencies = [
492
492
  { name = "pico-cli-sdk" },
@@ -1,80 +0,0 @@
1
- # Context Status Bar Implementation Summary
2
-
3
- ## Overview
4
- Added a context status bar widget to the PicoCLI TUI that displays:
5
- - Provider name (e.g., "OpenRouter")
6
- - Model name (e.g., "nvidia/nemotron-3.5-lightning:free")
7
- - Thinking indicator (shown when the model is reasoning)
8
- - Context window progress bar (fills as context fills, color-coded by usage level)
9
- - Current token count (formatted with commas, e.g., "38,932")
10
-
11
- ## Files Modified
12
-
13
- ### 1. `packages/pico_core/src/pico_core/fsm.py`
14
- - Added public `estimate_tokens()` method to `AgentLoop` class
15
- - This exposes the private `_estimate_tokens()` functionality
16
-
17
- ### 2. `packages/pico_sdk/src/pico_sdk/session.py`
18
- - Added `provider_name` property to `AgentSession` class
19
- - Extracts provider name from the provider class name
20
- - Returns "OpenRouter" for OpenRouterProvider
21
- - Added `context_window` property to `AgentSession` class
22
- - Returns the context window size from the agent loop
23
- - Added `estimate_tokens()` method to `AgentSession` class
24
- - Returns current estimated token count from the agent loop
25
-
26
- ### 3. `packages/pico_tui/src/pico_tui/status_bar.py` (NEW FILE)
27
- - Created `ContextStatusBar` widget extending Textual's `Static`
28
- - Features:
29
- - Displays provider | model information
30
- - Shows "thinking" indicator in yellow italic when active
31
- - Renders a 20-character progress bar for context window usage
32
- - Color-codes the progress bar:
33
- - Green: 0-50% usage (░ character)
34
- - Yellow: 50-70% usage (▒ character)
35
- - Orange: 70-90% usage (▓ character)
36
- - Red: 90-100% usage (█ character)
37
- - Shows token count with comma formatting in cyan
38
- - Methods:
39
- - `on_mount()`: Renders initial display after widget mount
40
- - `update_info()`: Updates all status information
41
- - `set_thinking()`: Updates thinking state
42
- - `_update_display()`: Renders the status bar with Rich Text
43
-
44
- ### 4. `packages/pico_tui/src/pico_tui/app.py`
45
- - Imported `ContextStatusBar` widget
46
- - Added CSS styling for `#status-bar`:
47
- - Docked to bottom
48
- - Height: 1 line
49
- - Background: $surface color
50
- - Padding: 0 1
51
- - Added `ContextStatusBar` to `compose()` method after Input widget
52
- - Added `_update_status_bar()` method to update the status bar with current session info
53
- - Updated `on_mount()` to call `_update_status_bar()` on initialization
54
- - Updated `_run_prompt()` to call `_update_status_bar()` when streaming starts
55
- - Updated `_stream_worker()` to call `_update_status_bar()` when streaming completes
56
-
57
- ### 5. `tests/test_status_bar.py` (NEW FILE)
58
- - Added 3 tests for the ContextStatusBar widget:
59
- - `test_status_bar_initialization`: Verifies default values
60
- - `test_status_bar_stores_info`: Verifies info storage
61
- - `test_status_bar_set_thinking`: Verifies thinking state updates
62
-
63
- ## Test Results
64
- All 92 tests pass successfully, including:
65
- - 19 existing TUI tests
66
- - 3 new status bar tests
67
- - All other existing tests remain passing
68
-
69
- ## Usage
70
- The status bar automatically appears below the input bar in the TUI and updates:
71
- - On application startup (shows initial provider, model, and 0 tokens)
72
- - When a prompt is submitted (shows "thinking" indicator)
73
- - When streaming completes (updates token count and hides "thinking")
74
- - When the model changes via `/model` command
75
-
76
- The status bar provides real-time visibility into:
77
- - Which AI provider and model is being used
78
- - Whether the model is currently thinking/reasoning
79
- - How much of the context window is being used
80
- - The exact token count in the current context
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
File without changes