monkeybot-cli 0.2.1__py3-none-any.whl

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 (51) hide show
  1. monkeybot_cli/__init__.py +3 -0
  2. monkeybot_cli/chat_renderer.py +87 -0
  3. monkeybot_cli/chat_session.py +911 -0
  4. monkeybot_cli/chat_status_bar.py +205 -0
  5. monkeybot_cli/chat_theme.py +91 -0
  6. monkeybot_cli/chat_tool_display.py +334 -0
  7. monkeybot_cli/chat_tui.py +1491 -0
  8. monkeybot_cli/chat_tui_widgets.py +996 -0
  9. monkeybot_cli/commands/__init__.py +1 -0
  10. monkeybot_cli/commands/chat.py +817 -0
  11. monkeybot_cli/commands/doctor.py +293 -0
  12. monkeybot_cli/commands/loop.py +207 -0
  13. monkeybot_cli/commands/new.py +207 -0
  14. monkeybot_cli/commands/run_cmd.py +41 -0
  15. monkeybot_cli/commands/talk.py +102 -0
  16. monkeybot_cli/commands/validate.py +385 -0
  17. monkeybot_cli/compat.py +7 -0
  18. monkeybot_cli/config_resolve.py +55 -0
  19. monkeybot_cli/exit_commands.py +13 -0
  20. monkeybot_cli/extras_catalog.py +95 -0
  21. monkeybot_cli/gateway_health.py +34 -0
  22. monkeybot_cli/main.py +38 -0
  23. monkeybot_cli/opensandbox_lifecycle.py +314 -0
  24. monkeybot_cli/output.py +110 -0
  25. monkeybot_cli/providers.py +112 -0
  26. monkeybot_cli/realtime/__init__.py +13 -0
  27. monkeybot_cli/realtime/audio_io.py +147 -0
  28. monkeybot_cli/realtime/client.py +17 -0
  29. monkeybot_cli/realtime/gateway_manager.py +142 -0
  30. monkeybot_cli/realtime/push_to_talk.py +128 -0
  31. monkeybot_cli/realtime/session.py +256 -0
  32. monkeybot_cli/realtime/session_controller.py +501 -0
  33. monkeybot_cli/realtime/talk_ui.py +243 -0
  34. monkeybot_cli/realtime/wire_encode.py +39 -0
  35. monkeybot_cli/runtime_python.py +91 -0
  36. monkeybot_cli/scaffold.py +287 -0
  37. monkeybot_cli/scaffold_defaults/AGENT.md +56 -0
  38. monkeybot_cli/scaffold_defaults/__init__.py +1 -0
  39. monkeybot_cli/scaffold_defaults/command_allowlist.yaml +57 -0
  40. monkeybot_cli/scaffold_defaults/env.example +35 -0
  41. monkeybot_cli/scaffold_defaults/mcp.json +49 -0
  42. monkeybot_cli/scaffold_defaults/monkeybot.example.yaml +191 -0
  43. monkeybot_cli/scaffold_defaults/otel-collector.example.yaml +57 -0
  44. monkeybot_cli/scaffold_defaults/permissions.yaml +32 -0
  45. monkeybot_cli/scaffold_defaults/setup-workspace.sh +24 -0
  46. monkeybot_cli/session_controller.py +7 -0
  47. monkeybot_cli/terminal_markdown.py +48 -0
  48. monkeybot_cli-0.2.1.dist-info/METADATA +10 -0
  49. monkeybot_cli-0.2.1.dist-info/RECORD +51 -0
  50. monkeybot_cli-0.2.1.dist-info/WHEEL +4 -0
  51. monkeybot_cli-0.2.1.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,56 @@
1
+ # Identity
2
+
3
+ You are a capable agent running inside **monkeybot** — not a generic chatbot in a browser. You pair with the user to get work done: research, writing, analysis, file and code work, and everyday tasks. You have a **writable workspace** and tools every turn; use them.
4
+
5
+ Act like someone the user can rely on: do the work, give a real answer, and stop. You are not a demo, a script, or a tool-calling showcase.
6
+
7
+ The **monkeybot harness (fixed)** section appended each turn defines exact tool names, path rules, and invocation protocol. When it conflicts with anything below, follow the harness — this file is about judgment, not mechanics.
8
+
9
+ # How you work
10
+
11
+ - **Understand the request before acting.** If ambiguity would change the outcome, ask one focused question. If intent is clear, proceed — don't stall on trivia.
12
+ - **Use tools for outcomes that live outside this message** — a file on disk, live data, a command result, fetched content. Text in chat is not a substitute for a deliverable the user asked for.
13
+ - **One good result ends the search.** When you have enough to answer — from a tool, a file, or verified knowledge — stop gathering. Extra "just in case" calls usually waste time.
14
+ - **Match effort to the task.** Quick questions get quick answers. Multi-file work, ambiguous design, or conflicting sources earn more steps and explanation.
15
+ - **Say what you don't know.** If a tool failed, access is missing, or a fact is unverified, say so plainly and state what would resolve it. Don't guess and present it as fact.
16
+
17
+ # Making files and code changes
18
+
19
+ When the user asks you to **build, create, edit, or save** a file, use workspace tools (`write_file`, `replace_in_file`, or `run_command` when appropriate). **Do not paste full file contents and tell them to save manually** unless they explicitly asked to see the code in chat.
20
+
21
+ - **New file or full rewrite** → `write_file`.
22
+ - **Targeted change to an existing file** → `read_file` then `replace_in_file`.
23
+ - **Deliverables live in the workspace.** After writing, give the workspace-relative path (e.g. `code/lumina/index.html`) so they can open it.
24
+ - **Never claim you cannot create files** because of "chat limitations" or "no access to the hard drive" when workspace tools are available — check the active tool list and harness paths first.
25
+ - **Don't output long code blocks in chat** when the request was to produce a file. A short snippet for explanation is fine; the full artifact belongs on disk.
26
+
27
+ # Choosing and using tools
28
+
29
+ Pick the narrowest tool that satisfies the request.
30
+
31
+ - **Live or external content** (website, app, current info): fetch with browser/MCP or web search — don't guess from memory.
32
+ - **Web search**: when you need information you don't have and can't get more directly.
33
+ - **Memory / past context**: when the user references prior conversations or saved notes. Use a specific query — not a fragment of your own last message.
34
+ - **Commands**: when the task requires running something, within what's permitted. Don't run commands to narrate progress.
35
+ - **After a failure**: check for `ok: false`, non-zero exit codes, or empty results. Don't retry the identical call; fix the cause or report the blocker.
36
+
37
+ # Communication
38
+
39
+ - **Answer first.** Lead with the takeaway or result; add detail only if useful.
40
+ - **Be concise by default.** Expand when asked for depth — not before.
41
+ - **One coherent outcome per turn** — a clear result or one focused follow-up, not an unprompted menu.
42
+ - **Don't name tools to the user** unless they ask; say what you're doing ("I'll create the landing page file") not which API you call.
43
+ - **Formatting aids reading, not decoration.** Never fabricate tool output — only show what actually ran or exists.
44
+
45
+ # Honesty, including about yourself
46
+
47
+ - **Be accurate about your own actions.** If asked what you did or whether you used a tool, check the actual record — don't reconstruct from assumption or prior claims.
48
+ - **Own mistakes plainly.** If you should have written a file and pasted code instead, say so and fix it with the right tool.
49
+ - **Never fabricate** tool results, file contents, command output, or citations.
50
+
51
+ # Judgment and safety
52
+
53
+ - Don't help with harm intended against systems the user doesn't own, malware, or deceiving real people — say briefly why.
54
+ - Treat credentials and secrets as sensitive; suggest proper secret storage if shared in chat.
55
+ - Don't promise outcomes this setup can't deliver (e.g. production deployment when not configured). Writing files under the workspace **is** in scope.
56
+ - Before destructive or irreversible operations, say what you're about to do and why.
@@ -0,0 +1 @@
1
+ """Packaged default ``monkeybot_config/`` files copied by ``monkeybot new``."""
@@ -0,0 +1,57 @@
1
+ # run_command: binary allowlist (enforced at execution).
2
+ allowed_commands:
3
+ - cat
4
+ - ls
5
+ - grep
6
+ - echo
7
+ - python
8
+ - python3
9
+ - uv
10
+ - git
11
+ - gh
12
+ - bash
13
+
14
+ # Path prefixes permitted in run_command argv (./ and / arguments).
15
+ allowed_path_prefixes:
16
+ - ./data/memory/
17
+ - ./data/memory
18
+ - ./skills/
19
+ - ./skills
20
+ - ./test-data/
21
+ - ./code/
22
+ - ./code
23
+
24
+ # Optional: regexes matched against the normalized invocation (deny wins).
25
+ # Omit this key to use built-in DEFAULT_DENY_PATTERNS (install blocking).
26
+ deny_patterns:
27
+ - "pip3?\\s+install"
28
+ - "python3?\\s+-m\\s+pip\\s+install"
29
+ - "(^|\\s)uv\\s+(add|remove|sync|pip\\s+install|pip\\s+sync)"
30
+ - "(^|\\s)poetry\\s+(add|install)"
31
+ - "(^|\\s)conda\\s+install"
32
+ - "(^|\\s)(npm|pnpm|yarn)\\s+(install|add|i)(\\s|$)"
33
+ - "(^|\\s)(apt|apt-get)\\s+install"
34
+ - "(^|\\s)brew\\s+install"
35
+ - "^curl\\s+"
36
+ - "^wget\\s+"
37
+ - "^rm\\s+-rf"
38
+ - "^sudo\\s+"
39
+ - ".*>\\s*/etc/.*"
40
+
41
+ # Per-tool output shaping (token optimization). Merged with built-in defaults for
42
+ # run_command and web_search when keys are omitted here.
43
+ tool_output:
44
+ run_command:
45
+ content_type: logs
46
+ max_output_lines: 400
47
+ collapse_repeated: true
48
+ keep_patterns:
49
+ - "(?i)\\berror\\b"
50
+ - "(?i)\\bfatal\\b"
51
+ - "(?i)traceback"
52
+ - "(?i)\\bexception\\b"
53
+ web_search:
54
+ content_type: json
55
+ max_array_items: 30
56
+ read_file:
57
+ content_type: code
@@ -0,0 +1,35 @@
1
+ # Copy to .env and fill in secrets / machine-local values only.
2
+
3
+ # Conversation history — SQLite is fine for single-agent dev.
4
+ DB_URL=sqlite:///data/monkeybot.db
5
+ # DB_URL=postgresql://postgres:postgres@localhost:5432/monkeybot
6
+ # DB_URL=firestore://your-gcp-project/(default)
7
+
8
+ # Gemini / Vertex (pick one approach)
9
+ # GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
10
+ # GCP_PROJECT_ID=your-gcp-project
11
+ # GOOGLE_CLOUD_PROJECT=your-gcp-project
12
+ # GEMINI_API_KEY=
13
+
14
+ # OpenAI
15
+ # OPENAI_API_KEY=
16
+
17
+ # Anthropic
18
+ # ANTHROPIC_API_KEY=
19
+
20
+ # Vertex Claude
21
+ # ANTHROPIC_VERTEX_PROJECT_ID=
22
+ # ANTHROPIC_VERTEX_REGION=us-east5
23
+
24
+ # AWS Bedrock
25
+ # AWS_REGION=us-east-1
26
+
27
+ # Hugging Face
28
+ # HF_TOKEN=
29
+
30
+ # Ollama (local models — no API key needed)
31
+ # OLLAMA_BASE_URL=http://localhost:11434
32
+
33
+ # Optional web search
34
+ # TAVILY_API_KEY=
35
+ # FIRECRAWL_API_KEY=
@@ -0,0 +1,49 @@
1
+ {
2
+ "mcpServers": {
3
+ "filesystem": {
4
+ "command": "npx",
5
+ "args": [
6
+ "-y",
7
+ "@modelcontextprotocol/server-filesystem",
8
+ "/path/to/workspace-readable-by-this-server"
9
+ ],
10
+ "env": {
11
+ "NODE_ENV": "production",
12
+ "EXAMPLE_SECRET": "${MY_SECRET_ENV_VAR}"
13
+ }
14
+ },
15
+ "remote-http": {
16
+ "url": "https://your-mcp-host.example.com/mcp",
17
+ "headers": {
18
+ "Authorization": "Bearer ${MY_STATIC_BEARER_TOKEN}"
19
+ }
20
+ },
21
+ "remote-oauth": {
22
+ "url": "https://your-mcp-host.example.com/mcp",
23
+ "auth": {
24
+ "flow": "client_credentials",
25
+ "token_url": "https://identity.provider.example.com/oauth2/token",
26
+ "client_id": "${OAUTH_CLIENT_ID}",
27
+ "client_secret": "${OAUTH_CLIENT_SECRET}",
28
+ "scope": "read:tools write:tools",
29
+ "client_auth_method": "body"
30
+ }
31
+ },
32
+ "browser": {
33
+ "command": "uv",
34
+ "args": [
35
+ "run",
36
+ "--project",
37
+ "/path/to/monkeybot/integrations/browser-mcp",
38
+ "python",
39
+ "-m",
40
+ "browser_mcp.server"
41
+ ],
42
+ "env": {
43
+ "BU_NAME": "monkeybot",
44
+ "BROWSER_MCP_PLAYBOOKS_DIR": "./workspace/skills/browser/playbooks",
45
+ "BROWSER_MCP_SCREENSHOTS_DIR": "${MONKEYBOT_WORKSPACE_ROOT}/browser/Screenshots"
46
+ }
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,191 @@
1
+ # monkeybot harness — copy to monkeybot.yaml and edit (paths relative to process cwd).
2
+ #
3
+ # cp monkeybot_config/monkeybot.example.yaml monkeybot_config/monkeybot.yaml
4
+ #
5
+ # Precedence: environment variables (and optional `.env` in cwd) win over values here.
6
+ #
7
+ # Secrets are not committed here. Create a `.env` in the repo root when you need keys or
8
+ # machine-local paths, for example:
9
+ # GOOGLE_APPLICATION_CREDENTIALS, VERTEX_AI_PROJECT_ID, GCP_PROJECT_ID, GOOGLE_CLOUD_PROJECT,
10
+ # VERTEX_AI_LOCATION, GOOGLE_CLOUD_LOCATION, GEMINI_API_KEY,
11
+ # OPENAI_API_KEY, ANTHROPIC_API_KEY,
12
+ # ANTHROPIC_VERTEX_PROJECT_ID, ANTHROPIC_VERTEX_REGION,
13
+ # OLLAMA_BASE_URL (default http://localhost:11434, no API key needed),
14
+ # NVIDIA_API_KEY (free key from https://build.nvidia.com),
15
+ # TAVILY_API_KEY, FIRECRAWL_API_KEY, SANDBOX_API_KEY,
16
+ # MONKEYBOT_TOOL_DENIED_PATTERNS, MONKEYBOT_CORS_ALLOW_ORIGINS, MONKEYBOT_CONFIG, …
17
+ #
18
+ # Optional fragments: add top-level ``includes: [includes/extra.yaml]`` (paths relative
19
+ # to this file’s directory); later files deep-merge over earlier ones.
20
+ #
21
+ # Env-only overrides (not in this YAML schema) still work when set in the shell or `.env`.
22
+
23
+ runtime:
24
+ # DEBUG | INFO | WARNING | ERROR
25
+ log_level: INFO
26
+ port: 8080
27
+ # Optional second port env (same as PORT if unset in code paths that read GATEWAY_PORT)
28
+ # gateway_port: 8080
29
+ # Internal debugging only (not agent-visible): write every AgentEvent and raw
30
+ # provider request/response for each session to
31
+ # {workspace_root}/.monkeybot/transcripts/{session_id}.ndjson. Opt-in; default off.
32
+ # (env: MONKEYBOT_TRANSCRIPT_ENABLED)
33
+ transcript_enabled: false
34
+
35
+ # Required: choose the conversational harness for this deployment.
36
+ # turn_based - existing HTTP POST /reply + SSE (default, backwards-compatible)
37
+ # realtime - WebSocket /realtime with full-duplex audio/text (requires monkeybot[realtime])
38
+ harness:
39
+ mode: turn_based
40
+
41
+ # Realtime settings are validated at startup even when mode is turn_based, but only
42
+ # take effect when harness.mode is realtime. Requires monkeybot[realtime] (or the
43
+ # vendor-specific extra, e.g. monkeybot[realtime-gemini]).
44
+ realtime:
45
+ # Optional model override for the realtime session. Live-only models (e.g.
46
+ # gemini-3.1-flash-live-preview) cannot be used for turn-based work, so the
47
+ # realtime session can point to a different model than model.name. When omitted,
48
+ # the realtime session falls back to model.name and MODEL_PROVIDER.
49
+ # model:
50
+ # name: gemini-3.1-flash-live-preview
51
+ # provider: google_genai
52
+ websocket:
53
+ enabled: true
54
+ # port defaults to runtime.port when unset
55
+ # port: 8080
56
+ audio:
57
+ input_format: pcm_s16le_24khz_mono
58
+ output_format: pcm_s16le_24khz_mono
59
+ chunk_ms: 200
60
+ max_utterance_sec: 60
61
+ session:
62
+ max_duration_sec: 1800
63
+ idle_timeout_sec: 120
64
+ max_response_turn_sec: 300
65
+ max_concurrent_sessions: 100
66
+ metrics:
67
+ emit_summary_on_close: true
68
+
69
+ paths:
70
+ agent_md: ./monkeybot_config/AGENT.md
71
+ memory_storage_uri: local://./data/memory
72
+ skills_path: ./skills
73
+ db_url: sqlite:///data/monkeybot.db
74
+ # Apply SQLite/Postgres DDL on startup (true | false). Default true. Set false when migrations own the schema.
75
+ auto_schema: true
76
+ mcp_config: ./monkeybot_config/mcp.json
77
+ command_allowlist_config: ./monkeybot_config/command_allowlist.yaml
78
+ # Soft permission ruleset (allow/ask/deny). Hard allowlists stay in command_allowlist.yaml.
79
+ permission_config: ./monkeybot_config/permissions.yaml
80
+ workspace_root: ./workspace
81
+
82
+ model:
83
+ # gemini | openai | anthropic | vertex-claude | huggingface | ollama | nvidia | aws_bedrock | fake
84
+ provider: gemini
85
+ name: gemini-3.1-flash-live-preview
86
+ temperature: 0.7
87
+ max_tokens: 60000
88
+ # Gemini: -1 = model default, 0 = off, N = token budget
89
+ # Ollama (Gemma 4, Qwen3, …): -1 = server default, 0 = off (reasoning_effort: none)
90
+ thinking_budget: -1
91
+ # Summarisation trigger (tokens)
92
+ context_window: 1000000
93
+ max_turns: 50
94
+ # Prompt-cache session hints: none | short | long (env: MODEL_CACHE_RETENTION)
95
+ # cache_retention: short
96
+ # Optional cheaper model for sync history summarization (env: CONTEXT_SUMMARIZATION_MODEL); omit = main model
97
+ # summarization_model: gemini-3-flash
98
+
99
+ # Non-secret GCP identifiers (prefer .env for secrets / ADC path).
100
+ # gcp:
101
+ # project_id: your-gcp-project
102
+ # location: us-central1
103
+
104
+ # anthropic_vertex:
105
+ # project_id: your-gcp-project
106
+ # region: us-east5
107
+
108
+ gateway:
109
+ pending_response_timeout_sec: 300
110
+ sse_replay_max: 256
111
+ graceful_shutdown_timeout_sec: 5
112
+ # FastAPI CORS allow_origins (comma-separated, or "*" for any origin). Sets MONKEYBOT_CORS_ALLOW_ORIGINS.
113
+ # Default in code when unset: http://localhost:5173 (Vite dev). Add http://127.0.0.1:5173 if needed.
114
+ cors_allow_origins: "http://localhost:5173"
115
+
116
+ context_curation:
117
+ # When false, curation is skipped (env: CONTEXT_CURATION_ENABLED)
118
+ enabled: true
119
+ # Recent INDEX lines injected by default; also caps curator-selected lines
120
+ memory_window_lines: 12
121
+ memory_index_cap: 200
122
+ # Call LLM curator when estimated memory-index tokens exceed this
123
+ # (env: CONTEXT_CURATION_MEMORY_TOKEN_THRESHOLD). Below this, use the window only.
124
+ memory_token_threshold: 2000
125
+ # Separate small model for curator (env: CONTEXT_CURATOR_MODEL); empty uses main model id
126
+ curator_model: gemini-3-flash
127
+ timeout_sec: 10
128
+
129
+ emission:
130
+ # Terse emission-style guidance injected into the cached harness prefix.
131
+ # Two named modes:
132
+ # off (default) — no prompt change. Use for conversational / user-facing
133
+ # agents where warmth and explanation are the deliverable.
134
+ # terse — cut model output volume (less code, less prose). When the
135
+ # `task` tool is active, also requests dense, minified
136
+ # agent-to-agent handoffs (Lever 3).
137
+ # Env override: MONKEYBOT_EMISSION_STYLE — accepts off | terse | true | 1 | on | yes
138
+ # (any value other than the terse-set means off).
139
+ style: off
140
+
141
+ memory_hook:
142
+ enabled: true
143
+
144
+ subagent:
145
+ timeout_sec: 600
146
+ max_turns: 25
147
+ # Gemini only: enable native google_search grounding for subagent task runs.
148
+ # Config-file only (no env var override). Defaults to false.
149
+ vertex_google_search: false
150
+ # Default AGENT.md for task calls with no subagent_type (relative to bot project root).
151
+ agent_md: ./monkeybot_config/AGENT.md
152
+
153
+ # Named subagent personas — parent selects via task(subagent_type=...).
154
+ # Add entries and matching AGENT.md files under monkeybot_config/agents/ when needed.
155
+ # subagents:
156
+ # - name: researcher
157
+ # description: "Deep-dives a topic and returns a structured summary."
158
+ # agent_md: ./monkeybot_config/agents/researcher.md
159
+
160
+ tools:
161
+ # List of substrings blocked in tool args (also env MONKEYBOT_TOOL_DENIED_PATTERNS as comma-separated)
162
+ # denied_patterns:
163
+ # - "rm -rf"
164
+ # read_max_lines: 50000
165
+ # read_default_lines: 20000
166
+ # spill_read_max_lines: 50000
167
+ # spill_min_chars: 8000
168
+ # result_budget_fraction: 0.8
169
+ # result_budget_floor_tokens: 2000
170
+
171
+ web_search:
172
+ # duckduckgo | tavily | firecrawl | none (Tavily/Firecrawl need keys in .env)
173
+ backend: duckduckgo
174
+ max_results: 5
175
+ # Gemini only, additive to `backend` above (both can be on at once): enables Vertex
176
+ # Gemini's native `google_search` grounding tool. Ignored for other model providers.
177
+ # Config-file only (no env var override).
178
+ vertex_google_search: false
179
+
180
+ sandbox:
181
+ enabled: false
182
+ server_url: http://localhost:8080
183
+ image: python:3.12
184
+ ttl_seconds: 1800
185
+
186
+ # Optional JSON for MODEL_PROVIDER=fake tests (env: MONKEYBOT_FAKE_PROVIDER_EVENTS)
187
+ # fake_provider:
188
+ # events_json: '[[]]'
189
+
190
+ # includes:
191
+ # - includes/local.yaml
@@ -0,0 +1,57 @@
1
+ # OpenTelemetry Collector — dual export (Phoenix + Langfuse)
2
+ #
3
+ # Prerequisites:
4
+ # - otel/opentelemetry-collector-contrib image (or core collector with otlphttp)
5
+ # - Langfuse: set LANGFUSE_OTEL_BASIC_AUTH to "Basic <base64(public_key:secret_key)>"
6
+ # (same value you would put in OTEL_EXPORTER_OTLP_HEADERS for direct export)
7
+ # - Phoenix: substitute PHOENIX_HOST (local Docker often phoenix:6006 or localhost:6006)
8
+ #
9
+ # Run collector (adjust mount path):
10
+ # docker run --rm -p 4318:4318 \
11
+ # -e LANGFUSE_OTEL_BASIC_AUTH \
12
+ # -v "$(pwd)/monkeybot_config/otel-collector.example.yaml:/etc/otelcol/config.yaml:ro" \
13
+ # otel/opentelemetry-collector-contrib:latest \
14
+ # --config=/etc/otelcol/config.yaml
15
+ #
16
+ # Point monkeybot at the collector (HTTP/protobuf, no path suffix on endpoint):
17
+ # export MONKEYBOT_OTEL_ENABLED=true
18
+ # export OTEL_TRACES_EXPORTER=otlp
19
+ # export OTEL_METRICS_EXPORTER=none
20
+ # export OTEL_LOGS_EXPORTER=none
21
+ # export OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318
22
+ #
23
+ # Optional: gRPC ingest on 4317 — add protocols.grpc.endpoint: 0.0.0.0:4317 under receivers.otlp
24
+ # Manual verification (AC-012): send one chat turn; confirm the same trace in Phoenix and Langfuse UIs.
25
+
26
+ receivers:
27
+ otlp:
28
+ protocols:
29
+ http:
30
+ endpoint: 0.0.0.0:4318
31
+ # grpc:
32
+ # endpoint: 0.0.0.0:4317
33
+
34
+ processors:
35
+ batch: {}
36
+ # memory_limiter: # enable if large batches cause OOM on small hosts
37
+ # check_interval: 1s
38
+ # limit_mib: 512
39
+
40
+ exporters:
41
+ otlphttp/phoenix:
42
+ # otlphttp appends /v1/traces — do not include it in endpoint
43
+ endpoint: http://PHOENIX_HOST:6006
44
+ # Local Phoenix often needs no auth; Phoenix Cloud may use OTEL_EXPORTER_OTLP_HEADERS on the collector.
45
+
46
+ otlphttp/langfuse:
47
+ endpoint: https://cloud.langfuse.com/api/public/otel
48
+ # Self-hosted: e.g. https://langfuse.example.com/api/public/otel
49
+ headers:
50
+ Authorization: ${env:LANGFUSE_OTEL_BASIC_AUTH}
51
+
52
+ service:
53
+ pipelines:
54
+ traces:
55
+ receivers: [otlp]
56
+ processors: [batch]
57
+ exporters: [otlphttp/phoenix, otlphttp/langfuse]
@@ -0,0 +1,32 @@
1
+ # Soft permission ruleset (last-match-wins). Hard execution constraints remain in
2
+ # command_allowlist.yaml (allowed_commands / allowed_path_prefixes) + sandbox.
3
+ #
4
+ # Effects: allow | ask | deny
5
+ # Patterns: fnmatch wildcards (*, ?) against tool name and a normalized resource
6
+ # (run_command line, path arg, or str(args) fallback).
7
+ #
8
+ # default: applied when no rule matches.
9
+ default: allow
10
+
11
+ rules: []
12
+
13
+ # Examples (replace rules: [] with a list to enable):
14
+ # rules:
15
+ # - tool: read_file
16
+ # pattern: "*"
17
+ # effect: allow
18
+ # - tool: run_command
19
+ # pattern: "git *"
20
+ # effect: allow
21
+ # - tool: run_command
22
+ # pattern: "rm *"
23
+ # effect: deny
24
+ # message: "Destructive rm is blocked by permissions.yaml"
25
+ # - tool: write_file
26
+ # pattern: "*"
27
+ # effect: ask
28
+ # message: "Approve writing this file?"
29
+ # - tool: "*__*"
30
+ # pattern: "*"
31
+ # effect: ask
32
+ # message: "Approve this MCP tool call?"
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env bash
2
+ # Ensure workspace/ exists and workspace/skills points at skills/ (for read_file in sandbox).
3
+ set -euo pipefail
4
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
5
+ WS="$ROOT/workspace"
6
+ SKILLS_SRC="$ROOT/skills"
7
+ LINK="$WS/skills"
8
+
9
+ mkdir -p "$WS"
10
+ touch "$WS/.gitkeep"
11
+ mkdir -p "$SKILLS_SRC"
12
+
13
+ if [[ -L "$LINK" ]]; then
14
+ echo "workspace/skills symlink already exists"
15
+ exit 0
16
+ fi
17
+
18
+ if [[ -e "$LINK" ]]; then
19
+ echo "error: $LINK exists and is not a symlink — remove it or run from a clean scaffold" >&2
20
+ exit 1
21
+ fi
22
+
23
+ ln -sfn "../skills" "$LINK"
24
+ echo "Created workspace/skills -> ../skills"
@@ -0,0 +1,7 @@
1
+ """Deprecated re-export — import from ``monkeybot_cli.chat_renderer`` instead."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from monkeybot_cli.chat_renderer import ChatRenderer, SessionController
6
+
7
+ __all__ = ["ChatRenderer", "SessionController"]
@@ -0,0 +1,48 @@
1
+ """Plain-text rendering for streamed assistant markdown in the terminal."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+
7
+ _HEADER = re.compile(r"^#{1,6}\s+")
8
+ _BOLD = re.compile(r"\*\*(.+?)\*\*")
9
+ _ITALIC = re.compile(r"(?<!\*)\*([^*\n]+)\*(?!\*)")
10
+ _BULLET = re.compile(r"^(\s*)[\*\-]\s+")
11
+ _CODE = re.compile(r"`([^`]+)`")
12
+ _ORPHAN_MARKERS = re.compile(r"\*+")
13
+
14
+
15
+ def plain_text_markdown_line(line: str) -> str:
16
+ """Strip common inline markdown markers from a single line."""
17
+ text = _HEADER.sub("", line)
18
+ text = _BOLD.sub(r"\1", text)
19
+ text = _ITALIC.sub(r"\1", text)
20
+ text = _BULLET.sub(r"\1• ", text)
21
+ text = _CODE.sub(r"\1", text)
22
+ text = _ORPHAN_MARKERS.sub("", text)
23
+ return text
24
+
25
+
26
+ class MarkdownPlainStream:
27
+ """Buffer streamed assistant text and emit line-wise plain text."""
28
+
29
+ def __init__(self) -> None:
30
+ self._pending = ""
31
+
32
+ def feed(self, chunk: str) -> str:
33
+ if not chunk:
34
+ return ""
35
+ self._pending += chunk
36
+ parts: list[str] = []
37
+ while "\n" in self._pending:
38
+ line, self._pending = self._pending.split("\n", 1)
39
+ parts.append(plain_text_markdown_line(line))
40
+ parts.append("\n")
41
+ return "".join(parts)
42
+
43
+ def flush(self) -> str:
44
+ if not self._pending:
45
+ return ""
46
+ rendered = plain_text_markdown_line(self._pending)
47
+ self._pending = ""
48
+ return rendered
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.4
2
+ Name: monkeybot-cli
3
+ Version: 0.2.1
4
+ Summary: CLI to create, configure, validate, and chat with monkeybot agents.
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: httpx>=0.27.0
7
+ Requires-Dist: monkeybot[cli]<3,>=2.1.0
8
+ Requires-Dist: python-dotenv>=1.0.0
9
+ Requires-Dist: pyyaml>=6.0.2
10
+ Requires-Dist: textual>=8.2.8
@@ -0,0 +1,51 @@
1
+ monkeybot_cli/__init__.py,sha256=wY_ibP8EOvlRJ-ilQCELArtd50fWMEfES-AWVIW55n0,105
2
+ monkeybot_cli/chat_renderer.py,sha256=vNViB76sRDO9CngHENeCmZCwoYVXRXNMv5Ca1C2A_lw,2287
3
+ monkeybot_cli/chat_session.py,sha256=8S9ravk2I8PlkTGbgZTqYN6S83-rLVOHVzAZ8wys7OI,34416
4
+ monkeybot_cli/chat_status_bar.py,sha256=Hs3QhzFW2awTqsgFMb2iNxrYb01Kk-NnonYiIy2_9Cs,7015
5
+ monkeybot_cli/chat_theme.py,sha256=GGXyARkN-VZBNdhU0ZX9Tzz-xZVfWTVg5YwyXxXPuPY,2207
6
+ monkeybot_cli/chat_tool_display.py,sha256=ebAcwB7atxyrzwe3IDQBXurI8pnyQla5PKoqRHQE3ws,9655
7
+ monkeybot_cli/chat_tui.py,sha256=hLuR-sQiedl9qbCNIp0rIFQZDN06e6ncLts56p1HsE0,54201
8
+ monkeybot_cli/chat_tui_widgets.py,sha256=LnA3p1CormGgng2MrKI1mBUANonLgrugkGUqsTUeLOw,31252
9
+ monkeybot_cli/compat.py,sha256=LpanA7hvRKUPCBh_wyAgZ9TvS2_TtSD0z7mVZvDz13Q,287
10
+ monkeybot_cli/config_resolve.py,sha256=QegH7lEQ6INrNKyB7XbRzDltqXdYYI3VwA3oUX76sWs,2029
11
+ monkeybot_cli/exit_commands.py,sha256=6bN2xfMvTJ0e1vKfQ97UJI7m7jCT18v-K1ITFn7mMEE,447
12
+ monkeybot_cli/extras_catalog.py,sha256=QLcZvNDBM9KK0kUq9l3ux02KunYK6_IgNXyTZjrLc4o,3587
13
+ monkeybot_cli/gateway_health.py,sha256=CHoJr3NyNsoUyE8xECbw7MnVf5XqyNfnY4mnfVoCT8s,927
14
+ monkeybot_cli/main.py,sha256=2Q0-ZKu7gvVsxE-zsrQfbsWSzdlEWX9I5RsO9cHJiuQ,1027
15
+ monkeybot_cli/opensandbox_lifecycle.py,sha256=FgN11n7f-05509VVLYQeqfDsp4jCfAZgU9F-wT7Tza0,9241
16
+ monkeybot_cli/output.py,sha256=u50fc_ebzV3eJMhwTQgDljxJD8m6mQCwh8lZCyxOuzQ,3154
17
+ monkeybot_cli/providers.py,sha256=18-jvjgVv19A9bGh_oVTps5cVgKxDbq45XXAgBa_ROc,3794
18
+ monkeybot_cli/runtime_python.py,sha256=a50d3tAL1cOSv0ftljMfqoHbjSaq9q94DIM36xPxvb8,3306
19
+ monkeybot_cli/scaffold.py,sha256=laeiL7FJO254XsDyBj8UDhqwJuGxrqdnPk19yFW8F0M,9943
20
+ monkeybot_cli/session_controller.py,sha256=xZUvFUmkCUrbVyq6j_MwZuvqkva7exzFgPzakd93_x8,242
21
+ monkeybot_cli/terminal_markdown.py,sha256=teL9EIsHOcbHRduqmJcUbK4rpsM1hTipCAh2hamHASc,1426
22
+ monkeybot_cli/commands/__init__.py,sha256=QN-uD3qaiBO7K7E4QEfRPnoh3rvXcIe89veVtfE8c38,23
23
+ monkeybot_cli/commands/chat.py,sha256=pCcE6HwGv5Eb304oy5BL1GmI_7lRiLxpv3LqwiLJnKg,29582
24
+ monkeybot_cli/commands/doctor.py,sha256=fUWHRD9dJm_gk1zI8KBZ51GafK9pfZFPXvl-TY3q_YU,10576
25
+ monkeybot_cli/commands/loop.py,sha256=U9nFz7xUkXN96zUEuo8LsM4cnNFWQ80cnPgWrZNvevk,7969
26
+ monkeybot_cli/commands/new.py,sha256=A5V2w3NWsRHmH9HA0wV-epZdwf1QfXLAK3jRDmGoQWs,6896
27
+ monkeybot_cli/commands/run_cmd.py,sha256=4aS0k46Hhxi1JUelIewPcE4XGtCtfPUTLH4hysCqD_Y,1700
28
+ monkeybot_cli/commands/talk.py,sha256=ZbZnylhCuqhygeFxmNUkyV3NnSD5dWcjNzxnkqdgssY,3353
29
+ monkeybot_cli/commands/validate.py,sha256=T1EPrY6cEzcgwMuHocS2ulnSKS1QvjVv2kwhCi6XwGI,14792
30
+ monkeybot_cli/realtime/__init__.py,sha256=MoHbb_vyPzbUhEUjBCsNxIRu222i-59zE0rM91QhiIw,403
31
+ monkeybot_cli/realtime/audio_io.py,sha256=cBrQ4CtvtnJXWP75NzBPMDCL6HvaYAAHDcg4PbGGc9Y,4747
32
+ monkeybot_cli/realtime/client.py,sha256=GQd9unAh3LlBYTKfvo1o1yYOAR91XLfqo3icG-1ff74,428
33
+ monkeybot_cli/realtime/gateway_manager.py,sha256=K5gFozKDJL1RzNQFLQ96YpDcatzWXc1fzP0MFpd8afQ,4455
34
+ monkeybot_cli/realtime/push_to_talk.py,sha256=ssZVY2UzgRLLDi_zn8ZgDHIpxXIDTCWnNBgW3R7H25E,4352
35
+ monkeybot_cli/realtime/session.py,sha256=HkTqyQfOJs2JDmN1uLLytKyEpqIiljHb4MXYm6WWXPI,7597
36
+ monkeybot_cli/realtime/session_controller.py,sha256=Hv7csdP2rim5HxzikBgSdFlOMHMOgCdEbALZNAliLN8,19488
37
+ monkeybot_cli/realtime/talk_ui.py,sha256=TNrsdBHyIrAF8dvya32uU6YEJEuFc5IZzhzXlAC4wqY,7575
38
+ monkeybot_cli/realtime/wire_encode.py,sha256=ARME556aULnaxq6QHUgnSFnAb9Hxo0bhsvsoeiIkR6U,1234
39
+ monkeybot_cli/scaffold_defaults/AGENT.md,sha256=Lk9uThJ6VAFvwnXZTe2ksq0qR6dh5Z0noer2mMQJIpk,4651
40
+ monkeybot_cli/scaffold_defaults/__init__.py,sha256=yMy9-a5uQUCDrAuiu_hIozkPFgBlQbKT_88GgRSKFiM,80
41
+ monkeybot_cli/scaffold_defaults/command_allowlist.yaml,sha256=i1xkmD6QIj3QVvOoWdgUc6Ucwe-3pRBuISwFV-YxiOY,1391
42
+ monkeybot_cli/scaffold_defaults/env.example,sha256=itYqeyjbcuHPgrqgB54oWwVZ4qYPht0c3RIsw7-gFjY,832
43
+ monkeybot_cli/scaffold_defaults/mcp.json,sha256=s2owUAAkKwFZmM84pBEV6tGNrxSSjAMNtvi4MZmxn4U,1333
44
+ monkeybot_cli/scaffold_defaults/monkeybot.example.yaml,sha256=yqatkC4wqBrobwLLIsld-jn3QK3sebKGjVPLxDnnKzw,7699
45
+ monkeybot_cli/scaffold_defaults/otel-collector.example.yaml,sha256=AqhbJEPHLV0BZ6i3q2Tvlt17R0B7wDWM0kzUuLnNrXw,2086
46
+ monkeybot_cli/scaffold_defaults/permissions.yaml,sha256=Vmr0JuRiIgHUZ4l33NGJC4-98ZZcaNwa2aY0Yo8bJQc,923
47
+ monkeybot_cli/scaffold_defaults/setup-workspace.sh,sha256=eNZ-LXjRun5jrsyCqnNJP7zR9vuBrA0eQR7wFjdR0zA,596
48
+ monkeybot_cli-0.2.1.dist-info/METADATA,sha256=R9mHeKyWTIBseWM4XF7ndCi18MM1NXHC7GeFx9pLFes,322
49
+ monkeybot_cli-0.2.1.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
50
+ monkeybot_cli-0.2.1.dist-info/entry_points.txt,sha256=BCUQ-d2jRWJszkNo9tCr6YHLqAhDTr1mh9Txxi7dVJI,54
51
+ monkeybot_cli-0.2.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ monkeybot = monkeybot_cli.main:main