octo-agent 0.11.2
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.
- checksums.yaml +7 -0
- data/.clacky/skills/commit/SKILL.md +423 -0
- data/.clacky/skills/gem-release/SKILL.md +199 -0
- data/.clacky/skills/gem-release/scripts/release.sh +304 -0
- data/.clacky/skills/oss-upload/SKILL.md +47 -0
- data/.octorules +106 -0
- data/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +76 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/CONTRIBUTING.md +92 -0
- data/Dockerfile +28 -0
- data/LICENSE.txt +22 -0
- data/POSITIONING.md +46 -0
- data/README.md +134 -0
- data/README_CN.md +134 -0
- data/Rakefile +34 -0
- data/benchmark/fixtures/sample_project/Gemfile +3 -0
- data/benchmark/fixtures/sample_project/lib/api_handler.rb +32 -0
- data/benchmark/fixtures/sample_project/lib/order_calculator.rb +23 -0
- data/benchmark/fixtures/sample_project/lib/user_renderer.rb +20 -0
- data/benchmark/fixtures/sample_project/spec/order_calculator_spec.rb +20 -0
- data/benchmark/results/EVALUATION_REPORT.md +165 -0
- data/benchmark/results/baseline_20260511_174424.json +128 -0
- data/benchmark/results/report_20260511_175256.json +271 -0
- data/benchmark/results/report_20260511_175444.json +271 -0
- data/benchmark/results/treatment_20260511_175103.json +130 -0
- data/benchmark/runner.rb +441 -0
- data/bin/octo +7 -0
- data/docs/agent-first-ui-design.md +77 -0
- data/docs/billing-system.md +318 -0
- data/docs/channel-architecture.md +235 -0
- data/docs/engineering-article.md +343 -0
- data/docs/session-skill-invocation.md +69 -0
- data/docs/time_machine_design.md +247 -0
- data/docs/ui2-architecture.md +124 -0
- data/homebrew/README.md +96 -0
- data/homebrew/openocto.rb +24 -0
- data/lib/octo/agent/hook_manager.rb +61 -0
- data/lib/octo/agent/llm_caller.rb +800 -0
- data/lib/octo/agent/memory_updater.rb +246 -0
- data/lib/octo/agent/message_compressor.rb +225 -0
- data/lib/octo/agent/message_compressor_helper.rb +869 -0
- data/lib/octo/agent/next_message_suggester.rb +215 -0
- data/lib/octo/agent/session_serializer.rb +685 -0
- data/lib/octo/agent/skill_auto_creator.rb +114 -0
- data/lib/octo/agent/skill_evolution.rb +61 -0
- data/lib/octo/agent/skill_manager.rb +466 -0
- data/lib/octo/agent/skill_reflector.rb +89 -0
- data/lib/octo/agent/system_prompt_builder.rb +101 -0
- data/lib/octo/agent/time_machine.rb +214 -0
- data/lib/octo/agent/tool_executor.rb +454 -0
- data/lib/octo/agent/tool_registry.rb +150 -0
- data/lib/octo/agent.rb +2180 -0
- data/lib/octo/agent_config.rb +989 -0
- data/lib/octo/agent_profile.rb +112 -0
- data/lib/octo/anthropic_stream_aggregator.rb +137 -0
- data/lib/octo/background_task_registry.rb +324 -0
- data/lib/octo/banner.rb +34 -0
- data/lib/octo/bedrock_stream_aggregator.rb +137 -0
- data/lib/octo/block_font.rb +331 -0
- data/lib/octo/cli.rb +968 -0
- data/lib/octo/client.rb +623 -0
- data/lib/octo/default_agents/SOUL.md +3 -0
- data/lib/octo/default_agents/USER.md +1 -0
- data/lib/octo/default_agents/base_prompt.md +66 -0
- data/lib/octo/default_agents/coding/profile.yml +2 -0
- data/lib/octo/default_agents/coding/system_prompt.md +67 -0
- data/lib/octo/default_agents/general/profile.yml +2 -0
- data/lib/octo/default_agents/general/system_prompt.md +16 -0
- data/lib/octo/default_parsers/doc_parser.rb +69 -0
- data/lib/octo/default_parsers/docx_parser.rb +188 -0
- data/lib/octo/default_parsers/pdf_parser.rb +120 -0
- data/lib/octo/default_parsers/pdf_parser_ocr.py +103 -0
- data/lib/octo/default_parsers/pdf_parser_plumber.py +62 -0
- data/lib/octo/default_parsers/pptx_parser.rb +140 -0
- data/lib/octo/default_parsers/xlsx_parser.rb +121 -0
- data/lib/octo/default_skills/browser-setup/SKILL.md +426 -0
- data/lib/octo/default_skills/channel-manager/SKILL.md +623 -0
- data/lib/octo/default_skills/channel-manager/dingtalk_setup.rb +191 -0
- data/lib/octo/default_skills/channel-manager/discord_setup.rb +199 -0
- data/lib/octo/default_skills/channel-manager/feishu_setup.rb +574 -0
- data/lib/octo/default_skills/channel-manager/import_lark_skills.rb +97 -0
- data/lib/octo/default_skills/channel-manager/install_feishu_skills.rb +105 -0
- data/lib/octo/default_skills/channel-manager/weixin_setup.rb +274 -0
- data/lib/octo/default_skills/code-explorer/SKILL.md +36 -0
- data/lib/octo/default_skills/cron-task-creator/SKILL.md +257 -0
- data/lib/octo/default_skills/cron-task-creator/evals/evals.json +38 -0
- data/lib/octo/default_skills/onboard/SKILL.md +578 -0
- data/lib/octo/default_skills/onboard/scripts/import_external_skills.rb +413 -0
- data/lib/octo/default_skills/onboard/scripts/install_builtin_skills.rb +97 -0
- data/lib/octo/default_skills/persist-memory/SKILL.md +59 -0
- data/lib/octo/default_skills/personal-website/SKILL.md +113 -0
- data/lib/octo/default_skills/personal-website/publish.rb +235 -0
- data/lib/octo/default_skills/product-help/SKILL.md +123 -0
- data/lib/octo/default_skills/product-help/docs/agent-config.md +74 -0
- data/lib/octo/default_skills/product-help/docs/best-practices.md +49 -0
- data/lib/octo/default_skills/product-help/docs/browser-tool.md +53 -0
- data/lib/octo/default_skills/product-help/docs/built-in-skills.md +43 -0
- data/lib/octo/default_skills/product-help/docs/cli-reference.md +82 -0
- data/lib/octo/default_skills/product-help/docs/create-your-first-skill.md +47 -0
- data/lib/octo/default_skills/product-help/docs/faq.md +98 -0
- data/lib/octo/default_skills/product-help/docs/how-to-use-a-skill.md +58 -0
- data/lib/octo/default_skills/product-help/docs/installation.md +59 -0
- data/lib/octo/default_skills/product-help/docs/memory-system.md +61 -0
- data/lib/octo/default_skills/product-help/docs/octorules.md +62 -0
- data/lib/octo/default_skills/product-help/docs/session-management.md +63 -0
- data/lib/octo/default_skills/product-help/docs/skill-basics.md +55 -0
- data/lib/octo/default_skills/product-help/docs/skill-frontmatter.md +61 -0
- data/lib/octo/default_skills/product-help/docs/web-server.md +49 -0
- data/lib/octo/default_skills/product-help/docs/what-is-octo.md +37 -0
- data/lib/octo/default_skills/product-help/docs/windows-installation.md +36 -0
- data/lib/octo/default_skills/product-help/docs/writing-tips.md +53 -0
- data/lib/octo/default_skills/recall-memory/SKILL.md +65 -0
- data/lib/octo/default_skills/skill-add/SKILL.md +59 -0
- data/lib/octo/default_skills/skill-add/scripts/install_from_zip.rb +295 -0
- data/lib/octo/default_skills/skill-creator/SKILL.md +602 -0
- data/lib/octo/default_skills/skill-creator/agents/analyzer.md +274 -0
- data/lib/octo/default_skills/skill-creator/agents/comparator.md +202 -0
- data/lib/octo/default_skills/skill-creator/agents/grader.md +223 -0
- data/lib/octo/default_skills/skill-creator/eval-viewer/generate_review.py +471 -0
- data/lib/octo/default_skills/skill-creator/eval-viewer/viewer.html +1325 -0
- data/lib/octo/default_skills/skill-creator/references/schemas.md +430 -0
- data/lib/octo/default_skills/skill-creator/scripts/__init__.py +0 -0
- data/lib/octo/default_skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- data/lib/octo/default_skills/skill-creator/scripts/generate_report.py +326 -0
- data/lib/octo/default_skills/skill-creator/scripts/improve_description.py +310 -0
- data/lib/octo/default_skills/skill-creator/scripts/quick_validate.py +103 -0
- data/lib/octo/default_skills/skill-creator/scripts/run_eval.py +317 -0
- data/lib/octo/default_skills/skill-creator/scripts/run_loop.py +331 -0
- data/lib/octo/default_skills/skill-creator/scripts/utils.py +47 -0
- data/lib/octo/default_skills/skill-creator/scripts/validate_skill_frontmatter.rb +143 -0
- data/lib/octo/idle_compression_timer.rb +115 -0
- data/lib/octo/json_ui_controller.rb +204 -0
- data/lib/octo/message_format/anthropic.rb +409 -0
- data/lib/octo/message_format/bedrock.rb +361 -0
- data/lib/octo/message_format/open_ai.rb +222 -0
- data/lib/octo/message_history.rb +373 -0
- data/lib/octo/openai_stream_aggregator.rb +130 -0
- data/lib/octo/plain_ui_controller.rb +166 -0
- data/lib/octo/providers.rb +534 -0
- data/lib/octo/server/browser_manager.rb +397 -0
- data/lib/octo/server/channel/adapters/base.rb +82 -0
- data/lib/octo/server/channel/adapters/dingtalk/adapter.rb +314 -0
- data/lib/octo/server/channel/adapters/dingtalk/api_client.rb +391 -0
- data/lib/octo/server/channel/adapters/dingtalk/stream_client.rb +203 -0
- data/lib/octo/server/channel/adapters/discord/adapter.rb +229 -0
- data/lib/octo/server/channel/adapters/discord/api_client.rb +107 -0
- data/lib/octo/server/channel/adapters/discord/gateway_client.rb +270 -0
- data/lib/octo/server/channel/adapters/feishu/adapter.rb +320 -0
- data/lib/octo/server/channel/adapters/feishu/bot.rb +478 -0
- data/lib/octo/server/channel/adapters/feishu/file_processor.rb +36 -0
- data/lib/octo/server/channel/adapters/feishu/message_parser.rb +129 -0
- data/lib/octo/server/channel/adapters/feishu/ws_client.rb +423 -0
- data/lib/octo/server/channel/adapters/telegram/adapter.rb +375 -0
- data/lib/octo/server/channel/adapters/telegram/api_client.rb +205 -0
- data/lib/octo/server/channel/adapters/wecom/adapter.rb +148 -0
- data/lib/octo/server/channel/adapters/wecom/media_downloader.rb +115 -0
- data/lib/octo/server/channel/adapters/wecom/ws_client.rb +395 -0
- data/lib/octo/server/channel/adapters/weixin/adapter.rb +692 -0
- data/lib/octo/server/channel/adapters/weixin/api_client.rb +402 -0
- data/lib/octo/server/channel/channel_config.rb +178 -0
- data/lib/octo/server/channel/channel_manager.rb +468 -0
- data/lib/octo/server/channel/channel_ui_controller.rb +224 -0
- data/lib/octo/server/channel.rb +33 -0
- data/lib/octo/server/discover.rb +77 -0
- data/lib/octo/server/epipe_safe_io.rb +105 -0
- data/lib/octo/server/http_server.rb +3554 -0
- data/lib/octo/server/scheduler.rb +317 -0
- data/lib/octo/server/server_master.rb +325 -0
- data/lib/octo/server/session_registry.rb +431 -0
- data/lib/octo/server/web_ui_controller.rb +487 -0
- data/lib/octo/session_manager.rb +385 -0
- data/lib/octo/skill.rb +466 -0
- data/lib/octo/skill_loader.rb +328 -0
- data/lib/octo/tools/base.rb +118 -0
- data/lib/octo/tools/browser.rb +625 -0
- data/lib/octo/tools/edit.rb +165 -0
- data/lib/octo/tools/file_reader.rb +549 -0
- data/lib/octo/tools/glob.rb +162 -0
- data/lib/octo/tools/grep.rb +356 -0
- data/lib/octo/tools/invoke_skill.rb +96 -0
- data/lib/octo/tools/list_tasks.rb +54 -0
- data/lib/octo/tools/redo_task.rb +41 -0
- data/lib/octo/tools/request_user_feedback.rb +84 -0
- data/lib/octo/tools/security.rb +333 -0
- data/lib/octo/tools/terminal/output_cleaner.rb +63 -0
- data/lib/octo/tools/terminal/persistent_session.rb +268 -0
- data/lib/octo/tools/terminal/safe_rm.sh +106 -0
- data/lib/octo/tools/terminal/session_manager.rb +213 -0
- data/lib/octo/tools/terminal.rb +1828 -0
- data/lib/octo/tools/todo_manager.rb +374 -0
- data/lib/octo/tools/trash_manager.rb +388 -0
- data/lib/octo/tools/undo_task.rb +35 -0
- data/lib/octo/tools/web_fetch.rb +242 -0
- data/lib/octo/tools/web_search.rb +260 -0
- data/lib/octo/tools/write.rb +77 -0
- data/lib/octo/ui2/block_font.rb +10 -0
- data/lib/octo/ui2/components/base_component.rb +163 -0
- data/lib/octo/ui2/components/command_suggestions.rb +290 -0
- data/lib/octo/ui2/components/common_component.rb +96 -0
- data/lib/octo/ui2/components/inline_input.rb +226 -0
- data/lib/octo/ui2/components/input_area.rb +1338 -0
- data/lib/octo/ui2/components/message_component.rb +99 -0
- data/lib/octo/ui2/components/modal_component.rb +419 -0
- data/lib/octo/ui2/components/todo_area.rb +149 -0
- data/lib/octo/ui2/components/tool_component.rb +107 -0
- data/lib/octo/ui2/components/welcome_banner.rb +139 -0
- data/lib/octo/ui2/layout_manager.rb +807 -0
- data/lib/octo/ui2/line_editor.rb +363 -0
- data/lib/octo/ui2/markdown_renderer.rb +100 -0
- data/lib/octo/ui2/output_buffer.rb +370 -0
- data/lib/octo/ui2/progress_handle.rb +362 -0
- data/lib/octo/ui2/progress_indicator.rb +55 -0
- data/lib/octo/ui2/screen_buffer.rb +273 -0
- data/lib/octo/ui2/terminal_detector.rb +119 -0
- data/lib/octo/ui2/theme_manager.rb +85 -0
- data/lib/octo/ui2/themes/base_theme.rb +105 -0
- data/lib/octo/ui2/themes/hacker_theme.rb +62 -0
- data/lib/octo/ui2/themes/minimal_theme.rb +56 -0
- data/lib/octo/ui2/thinking_verbs.rb +26 -0
- data/lib/octo/ui2/ui_controller.rb +1625 -0
- data/lib/octo/ui2/view_renderer.rb +177 -0
- data/lib/octo/ui2.rb +40 -0
- data/lib/octo/ui_interface.rb +154 -0
- data/lib/octo/utils/arguments_parser.rb +191 -0
- data/lib/octo/utils/browser_detector.rb +195 -0
- data/lib/octo/utils/encoding.rb +92 -0
- data/lib/octo/utils/environment_detector.rb +140 -0
- data/lib/octo/utils/file_ignore_helper.rb +170 -0
- data/lib/octo/utils/file_processor.rb +601 -0
- data/lib/octo/utils/gitignore_parser.rb +154 -0
- data/lib/octo/utils/limit_stack.rb +152 -0
- data/lib/octo/utils/logger.rb +124 -0
- data/lib/octo/utils/login_shell.rb +72 -0
- data/lib/octo/utils/model_pricing.rb +646 -0
- data/lib/octo/utils/parser_manager.rb +165 -0
- data/lib/octo/utils/path_helper.rb +15 -0
- data/lib/octo/utils/scripts_manager.rb +59 -0
- data/lib/octo/utils/string_matcher.rb +158 -0
- data/lib/octo/utils/trash_directory.rb +112 -0
- data/lib/octo/utils/workspace_rules.rb +46 -0
- data/lib/octo/version.rb +5 -0
- data/lib/octo/web/app.css +7141 -0
- data/lib/octo/web/app.js +543 -0
- data/lib/octo/web/apple-touch-icon.png +0 -0
- data/lib/octo/web/auth.js +150 -0
- data/lib/octo/web/channels.js +276 -0
- data/lib/octo/web/datepicker.js +205 -0
- data/lib/octo/web/favicon.png +0 -0
- data/lib/octo/web/i18n.js +1073 -0
- data/lib/octo/web/icon-512.png +0 -0
- data/lib/octo/web/icon-dark.svg +25 -0
- data/lib/octo/web/icon.svg +29 -0
- data/lib/octo/web/index.html +871 -0
- data/lib/octo/web/marked.min.js +69 -0
- data/lib/octo/web/onboard.js +491 -0
- data/lib/octo/web/profile.js +442 -0
- data/lib/octo/web/sessions.js +4421 -0
- data/lib/octo/web/settings.js +913 -0
- data/lib/octo/web/sidebar.js +32 -0
- data/lib/octo/web/skills.js +885 -0
- data/lib/octo/web/tasks.js +297 -0
- data/lib/octo/web/theme.js +105 -0
- data/lib/octo/web/trash.js +343 -0
- data/lib/octo/web/vendor/hljs/highlight.min.js +1244 -0
- data/lib/octo/web/vendor/hljs/hljs-theme.css +95 -0
- data/lib/octo/web/vendor/katex/auto-render.min.js +1 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- data/lib/octo/web/vendor/katex/katex.min.css +1 -0
- data/lib/octo/web/vendor/katex/katex.min.js +1 -0
- data/lib/octo/web/version.js +449 -0
- data/lib/octo/web/weixin-qr.html +209 -0
- data/lib/octo/web/ws-dispatcher.js +357 -0
- data/lib/octo/web/ws.js +128 -0
- data/lib/octo.rb +145 -0
- data/scripts/build/build.sh +329 -0
- data/scripts/build/lib/apt.sh +56 -0
- data/scripts/build/lib/brew.sh +89 -0
- data/scripts/build/lib/colors.sh +17 -0
- data/scripts/build/lib/gem.sh +95 -0
- data/scripts/build/lib/mise.sh +125 -0
- data/scripts/build/lib/network.sh +157 -0
- data/scripts/build/lib/os.sh +57 -0
- data/scripts/build/lib/shell.sh +37 -0
- data/scripts/build/src/install.sh.cc +174 -0
- data/scripts/build/src/install_browser.sh.cc +101 -0
- data/scripts/build/src/install_full.sh.cc +290 -0
- data/scripts/build/src/install_rails_deps.sh.cc +145 -0
- data/scripts/build/src/install_system_deps.sh.cc +123 -0
- data/scripts/build/src/uninstall.sh.cc +101 -0
- data/scripts/install.ps1 +532 -0
- data/scripts/install.sh +567 -0
- data/scripts/install_browser.sh +479 -0
- data/scripts/install_full.sh +838 -0
- data/scripts/install_rails_deps.sh +746 -0
- data/scripts/install_system_deps.sh +518 -0
- data/scripts/uninstall.sh +287 -0
- data/sig/octo.rbs +4 -0
- metadata +614 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# UI2 Architecture
|
|
2
|
+
|
|
3
|
+
## Core Principle
|
|
4
|
+
**Strict Layering**: UI layer must NOT directly access Agent layer. Use callbacks for communication.
|
|
5
|
+
|
|
6
|
+
## Component Hierarchy
|
|
7
|
+
```
|
|
8
|
+
UIController (single external interface)
|
|
9
|
+
├── LayoutManager (layout coordination)
|
|
10
|
+
│ ├── OutputArea (output display)
|
|
11
|
+
│ ├── InputArea (user input)
|
|
12
|
+
│ ├── TodoArea (task list)
|
|
13
|
+
│ └── InlineInput (confirmation prompt)
|
|
14
|
+
└── Callbacks (external communication)
|
|
15
|
+
├── on_input -> CLI handles input
|
|
16
|
+
├── on_interrupt -> CLI handles interruption
|
|
17
|
+
└── on_mode_toggle -> CLI handles mode change
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Data Flow
|
|
21
|
+
|
|
22
|
+
### Agent → UI: One-way calls
|
|
23
|
+
```ruby
|
|
24
|
+
# Agent calls UI to display
|
|
25
|
+
@ui&.show_tool_call(...)
|
|
26
|
+
@ui&.append_output(...)
|
|
27
|
+
@ui&.show_token_usage(...)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### UI → Agent: Via callbacks
|
|
31
|
+
```ruby
|
|
32
|
+
# ❌ Wrong: UI directly calls Agent
|
|
33
|
+
agent.run(input)
|
|
34
|
+
|
|
35
|
+
# ✅ Correct: Via callback
|
|
36
|
+
ui_controller.on_input { |input| agent.run(input) }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Common Mistakes
|
|
40
|
+
|
|
41
|
+
### ❌ Directly accessing Agent in UI components
|
|
42
|
+
```ruby
|
|
43
|
+
# Bad example
|
|
44
|
+
def toggle_mode
|
|
45
|
+
@agent.config.mode = "auto_approve" # ❌ Violates separation
|
|
46
|
+
end
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### ✅ Notify via callback
|
|
50
|
+
```ruby
|
|
51
|
+
# Good example
|
|
52
|
+
def toggle_mode
|
|
53
|
+
@mode_toggle_callback&.call("auto_approve") # ✅ Proper separation
|
|
54
|
+
end
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### ❌ Using puts for logging
|
|
58
|
+
```ruby
|
|
59
|
+
puts "Debug info" # ❌ Breaks UI rendering
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### ✅ Use UIController.log
|
|
63
|
+
```ruby
|
|
64
|
+
ui_controller.log("Debug info") # ✅ Displays in output area
|
|
65
|
+
ui_controller.log("Warning", level: :warning)
|
|
66
|
+
ui_controller.log("Error", level: :error)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Logging System
|
|
70
|
+
|
|
71
|
+
Use `ui_controller.log(message, level: :info)` to display debug information in the output area without breaking rendering.
|
|
72
|
+
|
|
73
|
+
**Available log levels:**
|
|
74
|
+
- `:debug` - Gray dimmed text
|
|
75
|
+
- `:info` - Normal text with info symbol
|
|
76
|
+
- `:warning` - Yellow warning text
|
|
77
|
+
- `:error` - Red error text
|
|
78
|
+
|
|
79
|
+
**Example:**
|
|
80
|
+
```ruby
|
|
81
|
+
# In UIController or components with access to UIController
|
|
82
|
+
@ui_controller.log("Tool execution started", level: :debug)
|
|
83
|
+
@ui_controller.log("Cache hit", level: :info)
|
|
84
|
+
@ui_controller.log("Retry attempt 3/10", level: :warning)
|
|
85
|
+
@ui_controller.log("Network failed", level: :error)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Rendering Flow
|
|
89
|
+
|
|
90
|
+
### Fixed Areas
|
|
91
|
+
- **InputArea**: Fixed at bottom (hidden when InlineInput is active via `paused?`)
|
|
92
|
+
- **TodoArea**: Fixed above InputArea
|
|
93
|
+
|
|
94
|
+
### Scrolling Area
|
|
95
|
+
- **OutputArea**: Natural scrolling, all content appended here
|
|
96
|
+
|
|
97
|
+
### Thread Safety
|
|
98
|
+
- All rendering protected by `@render_mutex`
|
|
99
|
+
- Never call render methods outside LayoutManager
|
|
100
|
+
|
|
101
|
+
## Key Methods
|
|
102
|
+
|
|
103
|
+
### Display Methods (Agent → UI)
|
|
104
|
+
- `append_output(content)` - Add content to output area
|
|
105
|
+
- `update_sessionbar(tasks:, cost:)` - Update session bar
|
|
106
|
+
- `show_token_usage(token_data)` - Display token statistics
|
|
107
|
+
- `show_tool_call(name, args)` - Display tool execution
|
|
108
|
+
- `request_confirmation(message)` - Blocking user confirmation
|
|
109
|
+
|
|
110
|
+
### Callback Registration (CLI sets these)
|
|
111
|
+
- `on_input { |text, images| ... }` - Handle user input
|
|
112
|
+
- `on_interrupt { |input_was_empty:| ... }` - Handle Ctrl+C
|
|
113
|
+
- `on_mode_toggle { |new_mode| ... }` - Handle Shift+Tab
|
|
114
|
+
|
|
115
|
+
### Logging (Use instead of puts)
|
|
116
|
+
- `log(message, level: :info)` - Display debug/info in output
|
|
117
|
+
|
|
118
|
+
## Best Practices
|
|
119
|
+
|
|
120
|
+
1. **Never bypass UIController** - All UI updates go through UIController
|
|
121
|
+
2. **Use callbacks for upward communication** - UI notifies CLI/Agent via callbacks
|
|
122
|
+
3. **Log via UIController** - Never use `puts` or `print` directly
|
|
123
|
+
4. **Check paused state** - Don't render InputArea when InlineInput is active
|
|
124
|
+
5. **Trust the render flow** - Let LayoutManager handle rendering coordination
|
data/homebrew/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Homebrew Formula for Octo
|
|
2
|
+
|
|
3
|
+
This directory contains the Homebrew formula for Octo.
|
|
4
|
+
|
|
5
|
+
## For Maintainers: Publishing to Homebrew Tap
|
|
6
|
+
|
|
7
|
+
### One-time Setup
|
|
8
|
+
|
|
9
|
+
1. Create a GitHub repository named `homebrew-octo` (must start with `homebrew-`)
|
|
10
|
+
2. Push this formula to the repository
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# In your GitHub account, create: homebrew-octo
|
|
14
|
+
git clone https://github.com/YOUR_USERNAME/homebrew-octo.git
|
|
15
|
+
cd homebrew-octo
|
|
16
|
+
cp /path/to/octo/homebrew/octo.rb ./Formula/octo.rb
|
|
17
|
+
git add Formula/octo.rb
|
|
18
|
+
git commit -m "Add octo formula"
|
|
19
|
+
git push origin main
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Update Formula for New Release
|
|
23
|
+
|
|
24
|
+
When you release a new version:
|
|
25
|
+
|
|
26
|
+
1. Download the new gem and calculate SHA256:
|
|
27
|
+
```bash
|
|
28
|
+
VERSION=0.6.1
|
|
29
|
+
wget https://rubygems.org/downloads/octo-${VERSION}.gem
|
|
30
|
+
shasum -a 256 octo-${VERSION}.gem
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
2. Update the formula in `homebrew-octo` repository:
|
|
34
|
+
- Update `url` with new version
|
|
35
|
+
- Update `sha256` with calculated hash
|
|
36
|
+
- Commit and push
|
|
37
|
+
|
|
38
|
+
3. Users can then upgrade:
|
|
39
|
+
```bash
|
|
40
|
+
brew update
|
|
41
|
+
brew upgrade octo
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## For Users: Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Add the tap (one-time)
|
|
48
|
+
brew tap YOUR_USERNAME/octo
|
|
49
|
+
|
|
50
|
+
# Install
|
|
51
|
+
brew install octo
|
|
52
|
+
|
|
53
|
+
# Or in one command
|
|
54
|
+
brew install YOUR_USERNAME/octo/octo
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Testing the Formula Locally
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Install from local formula
|
|
61
|
+
brew install --build-from-source ./homebrew/octo.rb
|
|
62
|
+
|
|
63
|
+
# Or test without installing
|
|
64
|
+
brew test ./homebrew/octo.rb
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Automation Script
|
|
68
|
+
|
|
69
|
+
For easier updates, use this script:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
#!/bin/bash
|
|
73
|
+
# update_formula.sh
|
|
74
|
+
|
|
75
|
+
VERSION=$1
|
|
76
|
+
if [ -z "$VERSION" ]; then
|
|
77
|
+
echo "Usage: ./update_formula.sh VERSION"
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Download gem
|
|
82
|
+
wget https://rubygems.org/downloads/octo-${VERSION}.gem -O /tmp/octo.gem
|
|
83
|
+
|
|
84
|
+
# Calculate SHA256
|
|
85
|
+
SHA256=$(shasum -a 256 /tmp/octo.gem | cut -d' ' -f1)
|
|
86
|
+
|
|
87
|
+
# Update formula
|
|
88
|
+
sed -i '' "s|url \".*\"|url \"https://rubygems.org/downloads/octo-${VERSION}.gem\"|" octo.rb
|
|
89
|
+
sed -i '' "s|sha256 \".*\"|sha256 \"${SHA256}\"|" octo.rb
|
|
90
|
+
|
|
91
|
+
echo "Formula updated to version ${VERSION}"
|
|
92
|
+
echo "SHA256: ${SHA256}"
|
|
93
|
+
echo "Don't forget to commit and push to homebrew-octo repository!"
|
|
94
|
+
|
|
95
|
+
rm /tmp/octo.gem
|
|
96
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Openocto < Formula
|
|
4
|
+
desc "Command-line interface for AI models with autonomous agent capabilities"
|
|
5
|
+
homepage "https://github.com/octo-ai/octo"
|
|
6
|
+
url "https://rubygems.org/downloads/octo-0.6.1.gem"
|
|
7
|
+
sha256 "" # Will be updated when gem is published
|
|
8
|
+
license "MIT"
|
|
9
|
+
|
|
10
|
+
depends_on "ruby@3.3"
|
|
11
|
+
|
|
12
|
+
def install
|
|
13
|
+
ENV["GEM_HOME"] = libexec
|
|
14
|
+
system "gem", "install", cached_download, "--no-document"
|
|
15
|
+
|
|
16
|
+
# Create wrapper scripts
|
|
17
|
+
(bin/"octo").write_env_script libexec/"bin/octo", GEM_HOME: ENV["GEM_HOME"]
|
|
18
|
+
(bin/"octo").write_env_script libexec/"bin/octo", GEM_HOME: ENV["GEM_HOME"]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
test do
|
|
22
|
+
assert_match "octo version #{version}", shell_output("#{bin}/octo version")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Octo
|
|
4
|
+
class HookManager
|
|
5
|
+
HOOK_EVENTS = [
|
|
6
|
+
:before_tool_use,
|
|
7
|
+
:after_tool_use,
|
|
8
|
+
:on_tool_error,
|
|
9
|
+
:on_start,
|
|
10
|
+
:on_complete,
|
|
11
|
+
:on_iteration,
|
|
12
|
+
:session_rollback
|
|
13
|
+
].freeze
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@hooks = Hash.new { |h, k| h[k] = [] }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def add(event, &block)
|
|
20
|
+
validate_event!(event)
|
|
21
|
+
@hooks[event] << block
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def trigger(event, *args)
|
|
25
|
+
validate_event!(event)
|
|
26
|
+
result = { action: :allow }
|
|
27
|
+
|
|
28
|
+
@hooks[event].each do |hook|
|
|
29
|
+
begin
|
|
30
|
+
hook_result = hook.call(*args)
|
|
31
|
+
result.merge!(hook_result) if hook_result.is_a?(Hash)
|
|
32
|
+
rescue StandardError => e
|
|
33
|
+
# Log error but don't fail
|
|
34
|
+
Octo::Logger.error("Hook error", event: event, error: e)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
result
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def has_hooks?(event)
|
|
42
|
+
@hooks[event].any?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def clear(event = nil)
|
|
46
|
+
if event
|
|
47
|
+
validate_event!(event)
|
|
48
|
+
@hooks[event].clear
|
|
49
|
+
else
|
|
50
|
+
@hooks.clear
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def validate_event!(event)
|
|
56
|
+
return if HOOK_EVENTS.include?(event)
|
|
57
|
+
|
|
58
|
+
raise ArgumentError, "Invalid hook event: #{event}. Must be one of #{HOOK_EVENTS.join(', ')}"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|