monkeybot-cli 0.11.1__tar.gz → 0.12.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.
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/.gitignore +3 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/PKG-INFO +1 -1
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/pyproject.toml +1 -1
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/chat_tui.py +91 -19
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/chat_tui_widgets.py +152 -51
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_tui.py +20 -3
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/uv.lock +3 -2
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/skills/monkeybot/SKILL.md +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/skills/monkeybot/references/config-sections.md +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/__init__.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/chat_file_index.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/chat_local_shell.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/chat_renderer.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/chat_session.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/chat_status_bar.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/chat_theme.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/chat_tool_display.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/__init__.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/chat.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/doctor.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/loop.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/mcp_login.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/new.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/refresh.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/run_cmd.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/talk.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/trace.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/commands/validate.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/compat.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/config_resolve.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/exit_commands.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/extras_catalog.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/gateway_health.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/main.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/opensandbox_lifecycle.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/output.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/overrides.txt +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/process_tree.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/providers.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/__init__.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/audio_io.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/client.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/gateway_manager.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/push_to_talk.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/session.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/session_controller.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/talk_ui.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/wire_encode.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/runtime_python.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/AGENT.md +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/Dockerfile +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/__init__.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/browser/SKILL.md +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/command_allowlist.yaml +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/dockerignore +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/env.example +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/goal/SKILL.md +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/image-generator/SKILL.md +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/image-generator/generate_image.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/loop/SKILL.md +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/mcp.json +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/monkeybot.example.yaml +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/opensandbox.docker.toml +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/otel-collector.example.yaml +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/permissions.yaml +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/templates/coding/AGENT.md +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/templates/coding/command_allowlist.yaml +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/templates/coding/monkeybot.overrides.yaml +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/templates/coding/permissions.yaml +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/session_controller.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/terminal_markdown.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_continue.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_e2e.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_errors.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_file_index.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_grounding.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_local_shell.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_renderer_parity.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_session.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_status_bar.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_theme.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_chat_tool_display.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_cli.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_config_resolve.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_doctor.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_extras_catalog.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_gateway_health.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_opensandbox_lifecycle.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_realtime_session_controller.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_run_cmd.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_runtime_python.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_scaffold.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_terminal_markdown.py +0 -0
- {monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/tests/test_trace_cmd.py +0 -0
|
@@ -11,6 +11,9 @@ internal/
|
|
|
11
11
|
# Local scaffolded harness config (defaults ship in monkeybot-cli scaffold_defaults/)
|
|
12
12
|
/monkeybot_config/
|
|
13
13
|
|
|
14
|
+
# Local agent for manual CLI testing. Recreate with `monkeybot new --dest ./cli-agent`.
|
|
15
|
+
/cli-agent/
|
|
16
|
+
|
|
14
17
|
# Live eval run artifacts. Baselines under regression/t4/baselines/ stay versioned.
|
|
15
18
|
/regression/t4/runs/
|
|
16
19
|
# Live-eval agent project local state. Live secrets come from the repo-root .env; a stray key
|
|
@@ -57,6 +57,7 @@ from monkeybot_cli.chat_tui_widgets import (
|
|
|
57
57
|
ToolCallBlock,
|
|
58
58
|
TranscriptPane,
|
|
59
59
|
UserTurn,
|
|
60
|
+
activity_label,
|
|
60
61
|
write_osc52_clipboard,
|
|
61
62
|
)
|
|
62
63
|
from monkeybot_cli.config_resolve import load_config_doc, resolve_config
|
|
@@ -360,6 +361,7 @@ class ChatApp(App[int]):
|
|
|
360
361
|
self._assistant: AssistantTurn | None = None
|
|
361
362
|
self._thinking: ThinkingLine | None = None
|
|
362
363
|
self._thinking_trace: ThinkingTrace | None = None
|
|
364
|
+
self._status_note = ""
|
|
363
365
|
self._hitl_card: HitlCard | None = None
|
|
364
366
|
self._hitl_status_flash: str | None = None
|
|
365
367
|
self._ring_text = "[dim]○ 0%[/]"
|
|
@@ -433,7 +435,10 @@ class ChatApp(App[int]):
|
|
|
433
435
|
if self._hitl_status_flash:
|
|
434
436
|
parts.append(self._hitl_status_flash)
|
|
435
437
|
if self._turn_active and not self._hitl_active:
|
|
436
|
-
|
|
438
|
+
if self._status_note:
|
|
439
|
+
parts.append(f"{self._status_note} · Esc interrupt")
|
|
440
|
+
else:
|
|
441
|
+
parts.append("working · Esc interrupt")
|
|
437
442
|
elif self._hitl_active:
|
|
438
443
|
if self._hitl_kind == "elicit":
|
|
439
444
|
parts.append("Enter submit · Ctrl-C cancel")
|
|
@@ -647,8 +652,24 @@ class ChatApp(App[int]):
|
|
|
647
652
|
transcript.mount(earlier, before=0)
|
|
648
653
|
earlier.absorb(digest)
|
|
649
654
|
|
|
655
|
+
def _mark_activity_lead(self, widget: object) -> None:
|
|
656
|
+
"""First row of a thought/tool/search stack gets the gap above it."""
|
|
657
|
+
if not isinstance(widget, (ThinkingTrace, ToolCallBlock, GroundingBlock)):
|
|
658
|
+
return
|
|
659
|
+
prev = None
|
|
660
|
+
for child in reversed(self._transcript().children):
|
|
661
|
+
if child is widget or getattr(child, "id", None) == "empty-hint":
|
|
662
|
+
continue
|
|
663
|
+
if isinstance(child, ThinkingTrace) and not child._raw.strip():
|
|
664
|
+
continue
|
|
665
|
+
prev = child
|
|
666
|
+
break
|
|
667
|
+
if not isinstance(prev, (ThinkingTrace, ToolCallBlock, GroundingBlock)):
|
|
668
|
+
widget.add_class("-lead")
|
|
669
|
+
|
|
650
670
|
def _mount(self, widget: object) -> None:
|
|
651
671
|
self._hide_empty_hint()
|
|
672
|
+
self._mark_activity_lead(widget)
|
|
652
673
|
if self._is_counted_turn(widget):
|
|
653
674
|
self._trim_old_turns()
|
|
654
675
|
self._turn_count += 1
|
|
@@ -673,10 +694,33 @@ class ChatApp(App[int]):
|
|
|
673
694
|
self._thinking.remove()
|
|
674
695
|
self._thinking = None
|
|
675
696
|
|
|
697
|
+
def _drop_empty_thinking(self) -> None:
|
|
698
|
+
trace = self._thinking_trace
|
|
699
|
+
if trace is None or not trace.is_attached or trace._raw.strip():
|
|
700
|
+
return
|
|
701
|
+
already = bool(getattr(trace, "_trimmed", False))
|
|
702
|
+
trace._trimmed = True # type: ignore[attr-defined]
|
|
703
|
+
trace.remove()
|
|
704
|
+
self._thinking_trace = None
|
|
705
|
+
if not already:
|
|
706
|
+
self._turn_count = max(0, self._turn_count - 1)
|
|
707
|
+
|
|
708
|
+
def _ensure_live_thinking(self) -> None:
|
|
709
|
+
trace = self._thinking_trace
|
|
710
|
+
if trace is not None and trace.is_attached and not trace.has_class("-done"):
|
|
711
|
+
return
|
|
712
|
+
self._clear_thinking()
|
|
713
|
+
block = ThinkingTrace()
|
|
714
|
+
self._thinking_trace = block
|
|
715
|
+
self._mount(block)
|
|
716
|
+
|
|
676
717
|
def _finish_thinking_trace(self, *, clear: bool = False) -> None:
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
718
|
+
trace = self._thinking_trace
|
|
719
|
+
if trace is not None and trace.is_attached:
|
|
720
|
+
if not trace._raw.strip():
|
|
721
|
+
self._drop_empty_thinking()
|
|
722
|
+
elif not trace.has_class("-done"):
|
|
723
|
+
trace.finish()
|
|
680
724
|
if clear:
|
|
681
725
|
self._thinking_trace = None
|
|
682
726
|
|
|
@@ -973,7 +1017,11 @@ class ChatApp(App[int]):
|
|
|
973
1017
|
self._follow_scroll()
|
|
974
1018
|
|
|
975
1019
|
def _ev_thinking(self, p: dict) -> None:
|
|
976
|
-
|
|
1020
|
+
text = str(p.get("text") or "thinking…")
|
|
1021
|
+
if text.strip().lower() in {"thinking…", "thinking...", "thinking"}:
|
|
1022
|
+
self._ensure_live_thinking()
|
|
1023
|
+
return
|
|
1024
|
+
self._show_thinking(text)
|
|
977
1025
|
|
|
978
1026
|
def _ev_thinking_clear(self, _p: dict) -> None:
|
|
979
1027
|
self._clear_thinking()
|
|
@@ -981,13 +1029,16 @@ class ChatApp(App[int]):
|
|
|
981
1029
|
def _ev_turn_started(self, _p: dict) -> None:
|
|
982
1030
|
self._turn_active = True
|
|
983
1031
|
self._assistant = None
|
|
1032
|
+
self._status_note = ""
|
|
984
1033
|
self._seal_thinking_trace()
|
|
985
1034
|
self._clear_open_tools()
|
|
986
|
-
self.
|
|
1035
|
+
self._clear_thinking()
|
|
1036
|
+
self._ensure_live_thinking()
|
|
987
1037
|
self._refresh_status()
|
|
988
1038
|
|
|
989
1039
|
def _ev_assistant_start(self, _p: dict) -> None:
|
|
990
1040
|
self._clear_thinking()
|
|
1041
|
+
self._drop_empty_thinking()
|
|
991
1042
|
|
|
992
1043
|
def _ev_assistant_delta(self, p: dict) -> None:
|
|
993
1044
|
delta = str(p.get("delta", ""))
|
|
@@ -1027,30 +1078,49 @@ class ChatApp(App[int]):
|
|
|
1027
1078
|
|
|
1028
1079
|
def _ev_summarizing(self, p: dict) -> None:
|
|
1029
1080
|
tokens = int(p.get("tokens") or 0)
|
|
1030
|
-
self.
|
|
1081
|
+
self._drop_empty_thinking()
|
|
1082
|
+
self._clear_thinking()
|
|
1083
|
+
self._status_note = f"summarizing context ({tokens:,} tokens)"
|
|
1084
|
+
self._refresh_status()
|
|
1031
1085
|
|
|
1032
1086
|
def _ev_summarized(self, p: dict) -> None:
|
|
1033
1087
|
turns = int(p.get("turns") or 0)
|
|
1034
1088
|
noun = "turn" if turns == 1 else "turns"
|
|
1035
|
-
self.
|
|
1089
|
+
self._status_note = f"summarized {turns} {noun}"
|
|
1090
|
+
self._refresh_status()
|
|
1036
1091
|
|
|
1037
1092
|
def _ev_grounding(self, p: dict) -> None:
|
|
1038
1093
|
self._clear_thinking()
|
|
1094
|
+
self._drop_empty_thinking()
|
|
1039
1095
|
queries = p.get("search_queries") or []
|
|
1040
|
-
|
|
1041
|
-
if
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
continue
|
|
1096
|
+
raw_sources = p.get("sources") or []
|
|
1097
|
+
sources = [source for source in raw_sources if isinstance(source, dict)]
|
|
1098
|
+
lines: list[str] = []
|
|
1099
|
+
shown = 0
|
|
1100
|
+
linked = 0
|
|
1101
|
+
for source in sources:
|
|
1047
1102
|
title = str(source.get("title") or "").strip()
|
|
1048
1103
|
uri = str(source.get("uri") or "").strip()
|
|
1049
1104
|
if not uri:
|
|
1050
1105
|
continue
|
|
1106
|
+
linked += 1
|
|
1107
|
+
if shown >= 5:
|
|
1108
|
+
continue
|
|
1109
|
+
shown += 1
|
|
1051
1110
|
label = title or uri
|
|
1052
1111
|
lines.append(f"- [{label}]({uri})")
|
|
1053
|
-
|
|
1112
|
+
query_text = ", ".join(str(query).strip() for query in queries if str(query).strip())
|
|
1113
|
+
if query_text and linked:
|
|
1114
|
+
noun = "source" if linked == 1 else "sources"
|
|
1115
|
+
hint = f"{query_text} · {linked} {noun}"
|
|
1116
|
+
elif query_text:
|
|
1117
|
+
hint = query_text
|
|
1118
|
+
elif linked:
|
|
1119
|
+
noun = "source" if linked == 1 else "sources"
|
|
1120
|
+
hint = f"{linked} {noun}"
|
|
1121
|
+
else:
|
|
1122
|
+
hint = ""
|
|
1123
|
+
self._mount(GroundingBlock("\n".join(lines), title=activity_label("Web", hint)))
|
|
1054
1124
|
|
|
1055
1125
|
def _ev_turn_error(self, p: dict) -> None:
|
|
1056
1126
|
self._close_assistant()
|
|
@@ -1157,9 +1227,10 @@ class ChatApp(App[int]):
|
|
|
1157
1227
|
def _ev_stream_ended(self, _p: dict) -> None:
|
|
1158
1228
|
self._exit_code = 1 if self._controller.stream_error else self._exit_code
|
|
1159
1229
|
|
|
1160
|
-
def _ev_thinking_trace(self,
|
|
1161
|
-
#
|
|
1162
|
-
|
|
1230
|
+
def _ev_thinking_trace(self, _p: dict) -> None:
|
|
1231
|
+
# thinking_block_* owns the collapsed row. This legacy event would
|
|
1232
|
+
# print the trace inline.
|
|
1233
|
+
return
|
|
1163
1234
|
|
|
1164
1235
|
def _ev_thinking_block_delta(self, p: dict) -> None:
|
|
1165
1236
|
text = str(p.get("text") or "")
|
|
@@ -1230,6 +1301,7 @@ class ChatApp(App[int]):
|
|
|
1230
1301
|
def _finish_turn_ui(self) -> None:
|
|
1231
1302
|
self._turn_active = False
|
|
1232
1303
|
self._assistant = None
|
|
1304
|
+
self._status_note = ""
|
|
1233
1305
|
self._clear_open_tools()
|
|
1234
1306
|
self._refresh_status()
|
|
1235
1307
|
self.query_one("#prompt", Composer).focus()
|
|
@@ -39,6 +39,38 @@ def _plain_title(text: str) -> Content:
|
|
|
39
39
|
return Content.from_text(text, markup=False)
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
_KIND_WIDTH = 7
|
|
43
|
+
_HINT_MAX = 72
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def activity_label(kind: str, hint: str = "") -> str:
|
|
47
|
+
"""One activity row: kind padded so hints share a column (``Thought …``)."""
|
|
48
|
+
kind = " ".join(kind.split())
|
|
49
|
+
hint = " ".join(hint.split())
|
|
50
|
+
if len(hint) > _HINT_MAX:
|
|
51
|
+
hint = hint[:_HINT_MAX] + "…"
|
|
52
|
+
if not hint:
|
|
53
|
+
return kind
|
|
54
|
+
return f"{kind:<{_KIND_WIDTH}} {hint}"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def activity_label_from_title(title: str) -> str:
|
|
58
|
+
"""Align a ``Kind hint`` title that ``tool_collapsed_title`` already built."""
|
|
59
|
+
kind, sep, hint = title.partition(" ")
|
|
60
|
+
if not sep:
|
|
61
|
+
return activity_label(kind)
|
|
62
|
+
return activity_label(kind, hint)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _set_collapsed_mark(widget: Collapsible, mark: str) -> None:
|
|
66
|
+
"""The disclosure symbol is the row's only glyph (spinner, ▸, ✓, ✗)."""
|
|
67
|
+
title = widget._title
|
|
68
|
+
if title.collapsed_symbol == mark:
|
|
69
|
+
return
|
|
70
|
+
title.collapsed_symbol = mark
|
|
71
|
+
title._update_label()
|
|
72
|
+
|
|
73
|
+
|
|
42
74
|
def write_osc52_clipboard(app: App[object], text: str) -> bool:
|
|
43
75
|
"""Best-effort OSC 52 clipboard write via the Textual driver."""
|
|
44
76
|
try:
|
|
@@ -110,59 +142,105 @@ class ThinkingLine(Static):
|
|
|
110
142
|
self.update(Text(f"{self._label} {elapsed}s", style="dim italic"))
|
|
111
143
|
|
|
112
144
|
|
|
113
|
-
class ThinkingTrace(
|
|
114
|
-
"""
|
|
145
|
+
class ThinkingTrace(Collapsible):
|
|
146
|
+
"""Collapsed thinking row. Click it (or focus it and press Enter) to read the trace."""
|
|
115
147
|
|
|
116
148
|
DEFAULT_CSS = """
|
|
117
149
|
ThinkingTrace {
|
|
118
150
|
width: 1fr;
|
|
119
151
|
height: auto;
|
|
120
|
-
|
|
152
|
+
background: transparent;
|
|
153
|
+
border-top: none;
|
|
121
154
|
padding: 0 1;
|
|
122
|
-
|
|
123
|
-
ThinkingTrace > .header {
|
|
124
|
-
height: 1;
|
|
155
|
+
margin-top: 0;
|
|
125
156
|
color: $muted;
|
|
126
|
-
text-style: bold dim;
|
|
127
157
|
}
|
|
128
|
-
ThinkingTrace
|
|
129
|
-
|
|
130
|
-
color: $muted;
|
|
131
|
-
text-style: dim;
|
|
158
|
+
ThinkingTrace.-lead {
|
|
159
|
+
margin-top: 1;
|
|
132
160
|
}
|
|
133
|
-
ThinkingTrace >
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
161
|
+
ThinkingTrace > Contents {
|
|
162
|
+
width: 1fr;
|
|
163
|
+
height: auto;
|
|
164
|
+
padding: 0 1 1 3;
|
|
165
|
+
color: $disabled;
|
|
138
166
|
}
|
|
139
|
-
ThinkingTrace
|
|
140
|
-
|
|
167
|
+
ThinkingTrace .thinking-body {
|
|
168
|
+
width: 1fr;
|
|
169
|
+
height: auto;
|
|
170
|
+
margin: 0;
|
|
171
|
+
padding: 0;
|
|
172
|
+
background: transparent;
|
|
173
|
+
color: $disabled;
|
|
141
174
|
}
|
|
142
175
|
"""
|
|
143
176
|
|
|
144
177
|
def __init__(self, **kwargs: object) -> None:
|
|
145
|
-
super().__init__(**kwargs) # type: ignore[arg-type]
|
|
146
178
|
self._raw = ""
|
|
179
|
+
self._done = False
|
|
180
|
+
self._spin_i = 0
|
|
181
|
+
self._spin_timer: Timer | None = None
|
|
182
|
+
self._body = Static("", classes="thinking-body")
|
|
183
|
+
super().__init__(
|
|
184
|
+
self._body,
|
|
185
|
+
title=_plain_title("Thinking…"), # type: ignore[arg-type]
|
|
186
|
+
collapsed=True,
|
|
187
|
+
collapsed_symbol="▸",
|
|
188
|
+
expanded_symbol="▾",
|
|
189
|
+
**kwargs, # type: ignore[arg-type]
|
|
190
|
+
)
|
|
147
191
|
|
|
148
|
-
def
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
192
|
+
def on_mount(self) -> None:
|
|
193
|
+
self._start_spinner()
|
|
194
|
+
|
|
195
|
+
def on_unmount(self) -> None:
|
|
196
|
+
self._stop_spinner()
|
|
152
197
|
|
|
153
198
|
def append_delta(self, chunk: str) -> None:
|
|
154
199
|
if not chunk:
|
|
155
200
|
return
|
|
156
201
|
self._raw += chunk
|
|
157
|
-
|
|
158
|
-
self.query_one(".body", Static).update(Text(self._raw, style="dim"))
|
|
202
|
+
self._body.update(Text(self._raw, style="dim"))
|
|
159
203
|
|
|
160
204
|
def finish(self) -> None:
|
|
205
|
+
self._done = True
|
|
206
|
+
self._stop_spinner()
|
|
161
207
|
self.add_class("-done")
|
|
208
|
+
_set_collapsed_mark(self, "▸")
|
|
209
|
+
self.title = _plain_title(activity_label("Thought", self._preview())) # type: ignore[assignment]
|
|
162
210
|
|
|
163
211
|
def reopen(self) -> None:
|
|
164
212
|
"""Allow late thinking deltas to continue this block after a premature close."""
|
|
213
|
+
self._done = False
|
|
165
214
|
self.remove_class("-done")
|
|
215
|
+
self.title = _plain_title("Thinking…") # type: ignore[assignment]
|
|
216
|
+
_set_collapsed_mark(self, "▸")
|
|
217
|
+
self._start_spinner()
|
|
218
|
+
|
|
219
|
+
def _preview(self) -> str:
|
|
220
|
+
return " ".join(self._raw.split())
|
|
221
|
+
|
|
222
|
+
def _start_spinner(self) -> None:
|
|
223
|
+
if self._done or not self.is_mounted:
|
|
224
|
+
return
|
|
225
|
+
self.title = _plain_title("Thinking…") # type: ignore[assignment]
|
|
226
|
+
if not bool(getattr(self.app, "animations_enabled", True)):
|
|
227
|
+
_set_collapsed_mark(self, "▸")
|
|
228
|
+
return
|
|
229
|
+
if self._spin_timer is None:
|
|
230
|
+
self._spin_timer = self.set_interval(0.08, self._tick_spinner)
|
|
231
|
+
self._tick_spinner()
|
|
232
|
+
|
|
233
|
+
def _stop_spinner(self) -> None:
|
|
234
|
+
if self._spin_timer is not None:
|
|
235
|
+
self._spin_timer.stop()
|
|
236
|
+
self._spin_timer = None
|
|
237
|
+
|
|
238
|
+
def _tick_spinner(self) -> None:
|
|
239
|
+
if self._done:
|
|
240
|
+
return
|
|
241
|
+
glyph = _SPIN[self._spin_i % len(_SPIN)]
|
|
242
|
+
self._spin_i += 1
|
|
243
|
+
_set_collapsed_mark(self, glyph)
|
|
166
244
|
|
|
167
245
|
|
|
168
246
|
class SystemLine(Static):
|
|
@@ -193,32 +271,50 @@ class SystemLine(Static):
|
|
|
193
271
|
self.update(Text(self.body, style=style))
|
|
194
272
|
|
|
195
273
|
|
|
196
|
-
class GroundingBlock(
|
|
197
|
-
"""
|
|
274
|
+
class GroundingBlock(Collapsible):
|
|
275
|
+
"""Collapsed web-search row. Open it to read the source links."""
|
|
198
276
|
|
|
199
277
|
DEFAULT_CSS = """
|
|
200
278
|
GroundingBlock {
|
|
201
279
|
width: 1fr;
|
|
202
280
|
height: auto;
|
|
203
|
-
|
|
281
|
+
background: transparent;
|
|
282
|
+
border-top: none;
|
|
204
283
|
padding: 0 1;
|
|
284
|
+
margin-top: 0;
|
|
285
|
+
color: $muted;
|
|
286
|
+
}
|
|
287
|
+
GroundingBlock.-lead {
|
|
288
|
+
margin-top: 1;
|
|
205
289
|
}
|
|
206
|
-
GroundingBlock >
|
|
290
|
+
GroundingBlock > Contents {
|
|
291
|
+
width: 1fr;
|
|
292
|
+
height: auto;
|
|
293
|
+
padding: 0 1 1 3;
|
|
294
|
+
color: $disabled;
|
|
295
|
+
}
|
|
296
|
+
GroundingBlock .grounding-body {
|
|
297
|
+
width: 1fr;
|
|
207
298
|
height: auto;
|
|
208
299
|
margin: 0;
|
|
209
300
|
padding: 0;
|
|
210
301
|
background: transparent;
|
|
211
|
-
color: $
|
|
302
|
+
color: $disabled;
|
|
212
303
|
}
|
|
213
304
|
"""
|
|
214
305
|
|
|
215
|
-
def __init__(self, markdown: str, **kwargs: object) -> None:
|
|
216
|
-
super().__init__(**kwargs) # type: ignore[arg-type]
|
|
306
|
+
def __init__(self, markdown: str, *, title: str = "Web", **kwargs: object) -> None:
|
|
217
307
|
self.markdown = markdown
|
|
218
308
|
self.mounted_at = datetime.now()
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
309
|
+
body = Markdown(markdown, open_links=True, classes="grounding-body")
|
|
310
|
+
super().__init__(
|
|
311
|
+
body,
|
|
312
|
+
title=_plain_title(title), # type: ignore[arg-type]
|
|
313
|
+
collapsed=True,
|
|
314
|
+
collapsed_symbol="▸",
|
|
315
|
+
expanded_symbol="▾",
|
|
316
|
+
**kwargs, # type: ignore[arg-type]
|
|
317
|
+
)
|
|
222
318
|
|
|
223
319
|
|
|
224
320
|
class EarlierTurns(Collapsible):
|
|
@@ -289,7 +385,7 @@ class UserTurn(Static):
|
|
|
289
385
|
content = Text()
|
|
290
386
|
if self.show_timestamp:
|
|
291
387
|
content.append(self.mounted_at.strftime("%H:%M:%S "), style="dim")
|
|
292
|
-
content.append("you\n", style="
|
|
388
|
+
content.append("you\n", style="dim")
|
|
293
389
|
content.append(self.body)
|
|
294
390
|
self.update(content)
|
|
295
391
|
|
|
@@ -304,7 +400,7 @@ class AssistantTurn(Vertical):
|
|
|
304
400
|
margin-top: 1;
|
|
305
401
|
padding: 0 1;
|
|
306
402
|
}
|
|
307
|
-
AssistantTurn > .
|
|
403
|
+
AssistantTurn > .stamp {
|
|
308
404
|
height: 1;
|
|
309
405
|
color: $muted;
|
|
310
406
|
text-style: dim;
|
|
@@ -335,22 +431,24 @@ class AssistantTurn(Vertical):
|
|
|
335
431
|
self.show_timestamp = show_timestamp
|
|
336
432
|
|
|
337
433
|
def compose(self) -> ComposeResult:
|
|
338
|
-
yield Static(
|
|
434
|
+
yield Static("", classes="stamp")
|
|
339
435
|
yield Markdown("", open_links=False, classes="body")
|
|
340
436
|
yield Static("▍", classes="cursor")
|
|
341
437
|
|
|
342
|
-
def
|
|
438
|
+
def _stamp_text(self) -> str:
|
|
343
439
|
if self.show_timestamp:
|
|
344
|
-
return
|
|
345
|
-
return "
|
|
440
|
+
return self.mounted_at.strftime("%H:%M:%S")
|
|
441
|
+
return ""
|
|
346
442
|
|
|
347
443
|
def refresh_label(self) -> None:
|
|
348
444
|
with contextlib.suppress(NoMatches):
|
|
349
|
-
self.query_one(".
|
|
445
|
+
stamp = self.query_one(".stamp", Static)
|
|
446
|
+
text = self._stamp_text()
|
|
447
|
+
stamp.update(text)
|
|
448
|
+
stamp.display = bool(text)
|
|
350
449
|
|
|
351
450
|
def on_mount(self) -> None:
|
|
352
|
-
|
|
353
|
-
return
|
|
451
|
+
self.refresh_label()
|
|
354
452
|
|
|
355
453
|
def append_delta(self, chunk: str) -> None:
|
|
356
454
|
if not chunk:
|
|
@@ -403,6 +501,9 @@ class ToolCallBlock(Collapsible):
|
|
|
403
501
|
margin-top: 0;
|
|
404
502
|
color: $muted;
|
|
405
503
|
}
|
|
504
|
+
ToolCallBlock.-lead {
|
|
505
|
+
margin-top: 1;
|
|
506
|
+
}
|
|
406
507
|
ToolCallBlock > Contents {
|
|
407
508
|
width: 1fr;
|
|
408
509
|
height: auto;
|
|
@@ -452,10 +553,10 @@ class ToolCallBlock(Collapsible):
|
|
|
452
553
|
)
|
|
453
554
|
super().__init__(
|
|
454
555
|
self._detail,
|
|
455
|
-
title=_plain_title(
|
|
556
|
+
title=_plain_title(activity_label_from_title(title)), # type: ignore[arg-type]
|
|
456
557
|
collapsed=True,
|
|
457
|
-
collapsed_symbol="
|
|
458
|
-
expanded_symbol="
|
|
558
|
+
collapsed_symbol="▸",
|
|
559
|
+
expanded_symbol="▾",
|
|
459
560
|
classes="running",
|
|
460
561
|
**kwargs, # type: ignore[arg-type]
|
|
461
562
|
)
|
|
@@ -466,14 +567,14 @@ class ToolCallBlock(Collapsible):
|
|
|
466
567
|
self._spin_timer = self.set_interval(0.08, self._tick_spinner)
|
|
467
568
|
self._tick_spinner()
|
|
468
569
|
else:
|
|
469
|
-
self
|
|
570
|
+
_set_collapsed_mark(self, "▸")
|
|
470
571
|
|
|
471
572
|
def _tick_spinner(self) -> None:
|
|
472
573
|
if self.status != "running":
|
|
473
574
|
return
|
|
474
575
|
glyph = _SPIN[self._spin_i % len(_SPIN)]
|
|
475
576
|
self._spin_i += 1
|
|
476
|
-
self
|
|
577
|
+
_set_collapsed_mark(self, glyph)
|
|
477
578
|
|
|
478
579
|
def mark_finished(self, *, error: object = None, result: str = "") -> None:
|
|
479
580
|
self.status = "error" if error else "ok"
|
|
@@ -482,8 +583,8 @@ class ToolCallBlock(Collapsible):
|
|
|
482
583
|
if self._spin_timer is not None:
|
|
483
584
|
self._spin_timer.stop()
|
|
484
585
|
self._spin_timer = None
|
|
485
|
-
|
|
486
|
-
self.title = _plain_title(
|
|
586
|
+
_set_collapsed_mark(self, "✗" if error else "✓")
|
|
587
|
+
self.title = _plain_title(activity_label_from_title(self.display_label)) # type: ignore[assignment]
|
|
487
588
|
self._detail.update(
|
|
488
589
|
format_tool_expand_body(
|
|
489
590
|
self.tool_name,
|
|
@@ -592,6 +592,10 @@ def test_grounding_mounts_markdown_links(tmp_path: Path) -> None:
|
|
|
592
592
|
await pilot.pause()
|
|
593
593
|
blocks = list(app.query(GroundingBlock))
|
|
594
594
|
assert len(blocks) == 1
|
|
595
|
+
assert blocks[0].collapsed is True
|
|
596
|
+
assert "Web" in str(blocks[0].title)
|
|
597
|
+
assert "monkeys" in str(blocks[0].title)
|
|
598
|
+
assert "1 source" in str(blocks[0].title)
|
|
595
599
|
assert "https://example.com" in blocks[0].markdown
|
|
596
600
|
assert "[Docs]" in blocks[0].markdown
|
|
597
601
|
|
|
@@ -1212,24 +1216,36 @@ def test_thinking_trace_streams_and_finishes(tmp_path: Path) -> None:
|
|
|
1212
1216
|
await pilot.pause()
|
|
1213
1217
|
assert app._thinking_trace is not None
|
|
1214
1218
|
assert "The user said hello" in app._thinking_trace._raw
|
|
1215
|
-
|
|
1216
|
-
assert "Thinking" in str(
|
|
1219
|
+
assert app._thinking_trace.collapsed is True
|
|
1220
|
+
assert "Thinking" in str(app._thinking_trace.title)
|
|
1217
1221
|
assert not app._thinking_trace.has_class("-done")
|
|
1218
1222
|
|
|
1219
1223
|
app._ev_thinking_block_delta({"text": " — reply briefly."})
|
|
1220
1224
|
await pilot.pause()
|
|
1221
1225
|
assert "reply briefly" in app._thinking_trace._raw
|
|
1226
|
+
assert app._thinking_trace.collapsed is True
|
|
1222
1227
|
|
|
1223
1228
|
app._ev_thinking_block_complete({})
|
|
1224
1229
|
await pilot.pause()
|
|
1225
|
-
# Finished block stays mounted; pointer kept for late re-entry.
|
|
1230
|
+
# Finished block stays mounted and collapsed; pointer kept for late re-entry.
|
|
1226
1231
|
assert app._thinking_trace is not None
|
|
1227
1232
|
assert app._thinking_trace.has_class("-done")
|
|
1233
|
+
assert app._thinking_trace.collapsed is True
|
|
1234
|
+
assert "Thought" in str(app._thinking_trace.title)
|
|
1235
|
+
assert "hello" in str(app._thinking_trace.title)
|
|
1236
|
+
assert app._thinking_trace._title.collapsed_symbol == "▸"
|
|
1228
1237
|
traces = list(app.query(ThinkingTrace))
|
|
1229
1238
|
assert len(traces) == 1
|
|
1230
1239
|
assert traces[0].has_class("-done")
|
|
1240
|
+
assert traces[0].collapsed is True
|
|
1231
1241
|
assert "The user said hello — reply briefly." in traces[0]._raw
|
|
1232
1242
|
|
|
1243
|
+
await pilot.click(traces[0].children[0])
|
|
1244
|
+
await pilot.pause()
|
|
1245
|
+
assert traces[0].collapsed is False
|
|
1246
|
+
body = traces[0].query_one(".thinking-body")
|
|
1247
|
+
assert "The user said hello — reply briefly." in str(body.render())
|
|
1248
|
+
|
|
1233
1249
|
app._ev_turn_complete({})
|
|
1234
1250
|
await pilot.pause()
|
|
1235
1251
|
assert app._thinking_trace is None
|
|
@@ -1272,6 +1288,7 @@ def test_late_thinking_delta_reopens_same_block(tmp_path: Path) -> None:
|
|
|
1272
1288
|
assert len(traces) == 1
|
|
1273
1289
|
assert "ask what they'd like me to build." in traces[0]._raw
|
|
1274
1290
|
assert traces[0].has_class("-done")
|
|
1291
|
+
assert traces[0].collapsed is True
|
|
1275
1292
|
|
|
1276
1293
|
# Thinking block must still sit above the assistant turn.
|
|
1277
1294
|
children = list(app._transcript().children)
|
|
@@ -633,7 +633,7 @@ wheels = [
|
|
|
633
633
|
|
|
634
634
|
[[package]]
|
|
635
635
|
name = "monkeybot"
|
|
636
|
-
version = "3.
|
|
636
|
+
version = "3.11.0"
|
|
637
637
|
source = { editable = "../" }
|
|
638
638
|
dependencies = [
|
|
639
639
|
{ name = "aiosqlite" },
|
|
@@ -725,6 +725,7 @@ provides-extras = ["memory", "gemini", "vertex", "claude", "vertex-claude", "bed
|
|
|
725
725
|
dev = [
|
|
726
726
|
{ name = "anthropic", extras = ["vertex", "bedrock"], specifier = ">=0.40.0" },
|
|
727
727
|
{ name = "asgi-lifespan", specifier = ">=2.1.0" },
|
|
728
|
+
{ name = "jsonschema", specifier = ">=4.26.0" },
|
|
728
729
|
{ name = "monkeybot", extras = ["memory"] },
|
|
729
730
|
{ name = "monkeybot", extras = ["postgres"] },
|
|
730
731
|
{ name = "monkeybot-cli", editable = "." },
|
|
@@ -773,7 +774,7 @@ dev = [{ name = "pytest", specifier = ">=8.0.0" }]
|
|
|
773
774
|
|
|
774
775
|
[[package]]
|
|
775
776
|
name = "monkeybot-cli"
|
|
776
|
-
version = "0.11.
|
|
777
|
+
version = "0.11.1"
|
|
777
778
|
source = { editable = "." }
|
|
778
779
|
dependencies = [
|
|
779
780
|
{ name = "httpx" },
|
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/skills/monkeybot/references/config-sections.md
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/realtime/session_controller.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/Dockerfile
RENAMED
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/__init__.py
RENAMED
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/browser/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/dockerignore
RENAMED
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/env.example
RENAMED
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/goal/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/loop/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{monkeybot_cli-0.11.1 → monkeybot_cli-0.12.0}/src/monkeybot_cli/scaffold_defaults/permissions.yaml
RENAMED
|
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
|
|
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
|