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,235 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# publish.rb — Publish or delete a profile card on the platform
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ruby publish.rb publish --name "NAME" --html-file /path/to/card.html
|
|
6
|
+
# ruby publish.rb delete --slug SLUG
|
|
7
|
+
#
|
|
8
|
+
# On first publish, prints the card URL and saves the update token to
|
|
9
|
+
# ~/.octo/card_token (used for future updates/deletes).
|
|
10
|
+
#
|
|
11
|
+
# Environment:
|
|
12
|
+
# OCTO_LICENSE_SERVER — platform base URL override (default: https://www.octo.com)
|
|
13
|
+
# CARD_HMAC_SECRET — shared secret (default matches platform default)
|
|
14
|
+
|
|
15
|
+
require "net/http"
|
|
16
|
+
require "uri"
|
|
17
|
+
require "json"
|
|
18
|
+
require "openssl"
|
|
19
|
+
require "digest"
|
|
20
|
+
require "optparse"
|
|
21
|
+
require "fileutils"
|
|
22
|
+
|
|
23
|
+
# ── Config ───────────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
# Primary CDN-accelerated endpoint.
|
|
26
|
+
# Fallback bypasses EdgeOne and is used when the primary times out or errors.
|
|
27
|
+
PRIMARY_HOST = ENV.fetch("OCTO_LICENSE_SERVER", "https://www.octo.com")
|
|
28
|
+
FALLBACK_HOST = "https://octo.up.railway.app"
|
|
29
|
+
# When the env override is set we use only that host (dev/test mode).
|
|
30
|
+
API_HOSTS = ENV["OCTO_LICENSE_SERVER"] ? [PRIMARY_HOST] : [PRIMARY_HOST, FALLBACK_HOST]
|
|
31
|
+
|
|
32
|
+
HMAC_SECRET = ENV.fetch("CARD_HMAC_SECRET", "octo-card-v1-default-secret-change-me")
|
|
33
|
+
TOKEN_FILE = File.expand_path("~/octo_workspace/personal_website/token.json")
|
|
34
|
+
|
|
35
|
+
# Retry / timeout config
|
|
36
|
+
OPEN_TIMEOUT = 8
|
|
37
|
+
READ_TIMEOUT = 15
|
|
38
|
+
ATTEMPTS_PER_HOST = 2
|
|
39
|
+
INITIAL_BACKOFF = 0.5
|
|
40
|
+
|
|
41
|
+
# ── HMAC signing ─────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
def device_fingerprint
|
|
44
|
+
parts = []
|
|
45
|
+
parts << `hostname`.strip
|
|
46
|
+
hw = `system_profiler SPHardwareDataType 2>/dev/null | grep 'Hardware UUID'`.strip
|
|
47
|
+
parts << hw unless hw.empty?
|
|
48
|
+
parts << ENV["USER"].to_s
|
|
49
|
+
Digest::SHA256.hexdigest(parts.join("|"))[0, 16]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def hmac_headers
|
|
53
|
+
ts = Time.now.to_i.to_s
|
|
54
|
+
fingerprint = device_fingerprint
|
|
55
|
+
payload = "octo:#{ts}:#{fingerprint}"
|
|
56
|
+
signature = OpenSSL::HMAC.hexdigest("SHA256", HMAC_SECRET, payload)
|
|
57
|
+
{
|
|
58
|
+
"X-Card-Timestamp" => ts,
|
|
59
|
+
"X-Card-Fingerprint" => fingerprint,
|
|
60
|
+
"X-Card-Signature" => signature,
|
|
61
|
+
"Content-Type" => "application/json"
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# ── HTTP helpers ──────────────────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
# Resilient HTTP request: retries on transient errors, then fails over to the
|
|
68
|
+
# fallback host before giving up.
|
|
69
|
+
#
|
|
70
|
+
# Returns [http_code_int, parsed_body_hash].
|
|
71
|
+
# Calls exit(1) on network failure (all hosts/attempts exhausted).
|
|
72
|
+
def http_request(method, path, body: nil, extra_headers: {})
|
|
73
|
+
last_error = nil
|
|
74
|
+
|
|
75
|
+
API_HOSTS.each_with_index do |base, host_index|
|
|
76
|
+
ATTEMPTS_PER_HOST.times do |attempt|
|
|
77
|
+
begin
|
|
78
|
+
result = do_http_request(method, base, path, body: body, extra_headers: extra_headers)
|
|
79
|
+
return result
|
|
80
|
+
rescue RetryableError => e
|
|
81
|
+
last_error = e
|
|
82
|
+
backoff = INITIAL_BACKOFF * (2**attempt)
|
|
83
|
+
sleep(backoff)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
warn "❌ Network error: #{last_error&.message || "unknown"}"
|
|
89
|
+
exit 1
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def do_http_request(method, base, path, body:, extra_headers:)
|
|
93
|
+
uri = URI.parse("#{base}#{path}")
|
|
94
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
95
|
+
http.use_ssl = uri.scheme == "https"
|
|
96
|
+
http.open_timeout = OPEN_TIMEOUT
|
|
97
|
+
http.read_timeout = READ_TIMEOUT
|
|
98
|
+
|
|
99
|
+
req_class = { "POST" => Net::HTTP::Post, "PATCH" => Net::HTTP::Patch,
|
|
100
|
+
"DELETE" => Net::HTTP::Delete }[method]
|
|
101
|
+
req = req_class.new(uri.path)
|
|
102
|
+
hmac_headers.each { |k, v| req[k] = v }
|
|
103
|
+
extra_headers.each { |k, v| req[k] = v }
|
|
104
|
+
req.body = body.to_json if body
|
|
105
|
+
|
|
106
|
+
response = http.request(req)
|
|
107
|
+
parsed = JSON.parse(response.body) rescue { "raw" => response.body }
|
|
108
|
+
[response.code.to_i, parsed]
|
|
109
|
+
rescue Net::OpenTimeout, Net::ReadTimeout,
|
|
110
|
+
Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH,
|
|
111
|
+
Errno::ECONNRESET, EOFError, OpenSSL::SSL::SSLError => e
|
|
112
|
+
raise RetryableError, e.message
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Sentinel for transient network errors that should trigger retry/failover.
|
|
116
|
+
class RetryableError < StandardError; end
|
|
117
|
+
|
|
118
|
+
# ── Token storage ─────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
def load_token_data
|
|
121
|
+
return {} unless File.exist?(TOKEN_FILE)
|
|
122
|
+
JSON.parse(File.read(TOKEN_FILE)) rescue {}
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def save_token_data(data)
|
|
126
|
+
FileUtils.mkdir_p(File.dirname(TOKEN_FILE))
|
|
127
|
+
File.write(TOKEN_FILE, JSON.pretty_generate(data))
|
|
128
|
+
File.chmod(0600, TOKEN_FILE)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# ── Commands ──────────────────────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
def cmd_publish(name:, html_file:)
|
|
134
|
+
unless File.exist?(html_file)
|
|
135
|
+
warn "❌ HTML file not found: #{html_file}"
|
|
136
|
+
exit 1
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
html_content = File.read(html_file, encoding: "utf-8")
|
|
140
|
+
|
|
141
|
+
if html_content.bytesize > 1_048_576
|
|
142
|
+
warn "❌ HTML file exceeds 1MB (#{html_content.bytesize / 1024}KB)"
|
|
143
|
+
exit 1
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
token_data = load_token_data
|
|
147
|
+
|
|
148
|
+
# If we already have a slug + token, do an update (PATCH) instead of create
|
|
149
|
+
if token_data["slug"] && token_data["update_token"]
|
|
150
|
+
slug = token_data["slug"]
|
|
151
|
+
token = token_data["update_token"]
|
|
152
|
+
|
|
153
|
+
status, body = http_request("PATCH", "/api/v1/personal_websites/#{slug}",
|
|
154
|
+
body: { html_content: html_content },
|
|
155
|
+
extra_headers: { "X-Card-Token" => token })
|
|
156
|
+
|
|
157
|
+
if status == 200
|
|
158
|
+
puts "✅ Website updated: #{body["url"]}"
|
|
159
|
+
else
|
|
160
|
+
warn "❌ Update failed (#{status}): #{body["error"] || body.inspect}"
|
|
161
|
+
exit 1
|
|
162
|
+
end
|
|
163
|
+
else
|
|
164
|
+
# First publish — POST to create
|
|
165
|
+
status, body = http_request("POST", "/api/v1/personal_websites",
|
|
166
|
+
body: { name: name, html_content: html_content })
|
|
167
|
+
|
|
168
|
+
if status == 201
|
|
169
|
+
save_token_data("slug" => body["slug"], "update_token" => body["update_token"])
|
|
170
|
+
puts "✅ Website published: #{body["url"]}"
|
|
171
|
+
puts " Slug: #{body["slug"]}"
|
|
172
|
+
puts " Token saved to: #{TOKEN_FILE}"
|
|
173
|
+
else
|
|
174
|
+
warn "❌ Publish failed (#{status}): #{body["error"] || body.inspect}"
|
|
175
|
+
exit 1
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def cmd_delete(slug: nil)
|
|
181
|
+
token_data = load_token_data
|
|
182
|
+
token = token_data["update_token"]
|
|
183
|
+
slug = slug || token_data["slug"]
|
|
184
|
+
|
|
185
|
+
unless token && slug
|
|
186
|
+
warn "❌ No published website found (#{TOKEN_FILE} missing or incomplete)."
|
|
187
|
+
warn " Nothing to delete."
|
|
188
|
+
exit 1
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
status, body = http_request("DELETE", "/api/v1/personal_websites/#{slug}",
|
|
192
|
+
extra_headers: { "X-Card-Token" => token })
|
|
193
|
+
|
|
194
|
+
if status == 200
|
|
195
|
+
File.delete(TOKEN_FILE) if File.exist?(TOKEN_FILE)
|
|
196
|
+
puts "✅ Personal website deleted: /~#{slug}"
|
|
197
|
+
else
|
|
198
|
+
warn "❌ Delete failed (#{status}): #{body["error"] || body.inspect}"
|
|
199
|
+
exit 1
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# ── CLI parsing ───────────────────────────────────────────────────────────────
|
|
204
|
+
|
|
205
|
+
command = ARGV.shift
|
|
206
|
+
|
|
207
|
+
case command
|
|
208
|
+
when "publish"
|
|
209
|
+
options = {}
|
|
210
|
+
OptionParser.new do |opts|
|
|
211
|
+
opts.on("--name NAME") { |v| options[:name] = v }
|
|
212
|
+
opts.on("--html-file FILE") { |v| options[:html_file] = v }
|
|
213
|
+
end.parse!
|
|
214
|
+
|
|
215
|
+
unless options[:name] && options[:html_file]
|
|
216
|
+
warn "Usage: ruby publish.rb publish --name NAME --html-file FILE"
|
|
217
|
+
exit 1
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
cmd_publish(name: options[:name], html_file: File.expand_path(options[:html_file]))
|
|
221
|
+
|
|
222
|
+
when "delete"
|
|
223
|
+
options = {}
|
|
224
|
+
OptionParser.new do |opts|
|
|
225
|
+
opts.on("--slug SLUG") { |v| options[:slug] = v } # optional, auto-read from token file
|
|
226
|
+
end.parse!
|
|
227
|
+
|
|
228
|
+
cmd_delete(slug: options[:slug])
|
|
229
|
+
|
|
230
|
+
else
|
|
231
|
+
warn "Usage: ruby publish.rb publish|delete [options]"
|
|
232
|
+
warn " publish --name NAME --html-file FILE"
|
|
233
|
+
warn " delete --slug SLUG"
|
|
234
|
+
exit 1
|
|
235
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: product-help
|
|
3
|
+
description: 'Use this skill when the user asks about my own features, configuration, or usage — installation, skills, Web UI, CLI, API config, memory, sessions, troubleshooting, or restarting the server. Do NOT trigger for general coding tasks unrelated to me.'
|
|
4
|
+
fork_agent: true
|
|
5
|
+
user-invocable: false
|
|
6
|
+
auto_summarize: true
|
|
7
|
+
forbidden_tools:
|
|
8
|
+
- write
|
|
9
|
+
- edit
|
|
10
|
+
- web_search
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Product Help Subagent
|
|
14
|
+
|
|
15
|
+
## My self-understanding
|
|
16
|
+
|
|
17
|
+
I am an AI assistant powered by **Octo**.
|
|
18
|
+
|
|
19
|
+
Octo is a Ruby tool for interacting with AI models. It speaks **Anthropic Messages**, **OpenAI** (Chat Completions + Responses), and **AWS Bedrock** natively, and works with any provider exposing one of those API shapes. Core capabilities include:
|
|
20
|
+
|
|
21
|
+
- **Skills** — installable capability packs in Markdown format
|
|
22
|
+
- **Web UI** — browser interface at `localhost:8888`
|
|
23
|
+
- **Memory** — persistent long-term memory across sessions
|
|
24
|
+
- **Sessions** — conversation history and context
|
|
25
|
+
- **CLI** — command-line interface
|
|
26
|
+
- **Config** — model and API key setup
|
|
27
|
+
|
|
28
|
+
Answer the user's question using the built-in documentation below. Always read the doc first — never answer from memory alone.
|
|
29
|
+
|
|
30
|
+
## Doc File Table
|
|
31
|
+
|
|
32
|
+
All docs are bundled inside the gem at `lib/octo/default_skills/product-help/docs/`.
|
|
33
|
+
|
|
34
|
+
| Topic | File |
|
|
35
|
+
|-------|------|
|
|
36
|
+
| What is Octo, product overview | `what-is-octo.md` |
|
|
37
|
+
| Install on macOS / Linux, setup, install errors | `installation.md` |
|
|
38
|
+
| Install on Windows | `windows-installation.md` |
|
|
39
|
+
| What is a Skill, how to install / use a Skill | `how-to-use-a-skill.md` |
|
|
40
|
+
| Common errors, troubleshooting, FAQ | `faq.md` |
|
|
41
|
+
| Quickstart: create your first Skill | `create-your-first-skill.md` |
|
|
42
|
+
| Skill structure, SKILL.md format, frontmatter options | `skill-basics.md` |
|
|
43
|
+
| Skill writing best practices, prompt tips | `writing-tips.md` |
|
|
44
|
+
| SKILL.md frontmatter fields reference | `skill-frontmatter.md` |
|
|
45
|
+
| Built-in skills, default skills | `built-in-skills.md` |
|
|
46
|
+
| Web UI, octo server, browser interface | `web-server.md` |
|
|
47
|
+
| CLI commands, command line reference | `cli-reference.md` |
|
|
48
|
+
| Model config, API key setup, provider selection | `agent-config.md` |
|
|
49
|
+
| Project rules file, .octorules, custom instructions | `octorules.md` |
|
|
50
|
+
| Memory system, long-term memory | `memory-system.md` |
|
|
51
|
+
| Session management, conversation history | `session-management.md` |
|
|
52
|
+
| Browser automation, browser tool, Chrome, Edge, CDP | `browser-tool.md` |
|
|
53
|
+
| Advanced patterns, best practices | `best-practices.md` |
|
|
54
|
+
|
|
55
|
+
## Workflow
|
|
56
|
+
|
|
57
|
+
### Step 1 — Pick the file
|
|
58
|
+
|
|
59
|
+
Look at the user's question and pick the **single most relevant file** from the table above.
|
|
60
|
+
|
|
61
|
+
Match on intent, not just keywords. Examples:
|
|
62
|
+
- "帮我打开webui" → `web-server.md`
|
|
63
|
+
- "api key怎么配" → `agent-config.md`
|
|
64
|
+
- "skill怎么写" → `skill-basics.md`
|
|
65
|
+
- "怎么安装skill" → `how-to-use-a-skill.md`
|
|
66
|
+
|
|
67
|
+
If genuinely unsure between two topics, pick both (max 2).
|
|
68
|
+
|
|
69
|
+
### Step 2 — Resolve the doc path
|
|
70
|
+
|
|
71
|
+
The docs are bundled inside the gem. First get the gem installation root:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
terminal(command: "ruby -e \"require 'rubygems'; puts begin; Gem::Specification.find_by_name('octo').gem_dir; rescue Exception; Dir.pwd; end\"")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Then read the doc:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
file_reader(path: "<gem-root>/lib/octo/default_skills/product-help/docs/<FILE>")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If the gem command fails (e.g. running from source), fall back to searching from the current working directory:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
glob(pattern: "**/product-help/docs/<FILE>")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Step 3 — Answer directly
|
|
90
|
+
|
|
91
|
+
- Answer the question directly — don't say "the docs say…"
|
|
92
|
+
- Match the user's language (Chinese question → Chinese answer)
|
|
93
|
+
- Use numbered steps for sequences
|
|
94
|
+
- Use code blocks for commands
|
|
95
|
+
|
|
96
|
+
## Rules
|
|
97
|
+
|
|
98
|
+
- Always read the doc first — never answer from memory
|
|
99
|
+
- Only use files from the table above — do NOT search the web
|
|
100
|
+
- If the doc doesn't answer the question, try the next most relevant file (max 2 reads)
|
|
101
|
+
- If still no answer, tell the user: "请访问 https://github.com/Leihb/octo 查看更多信息"
|
|
102
|
+
- Keep answers concise — extract what's relevant, don't paste the whole page
|
|
103
|
+
|
|
104
|
+
## Server restart
|
|
105
|
+
|
|
106
|
+
### Normal restart
|
|
107
|
+
|
|
108
|
+
If the user asks to restart the server normally (e.g. "重启", "restart", "请重启octo") — without mentioning failure or errors:
|
|
109
|
+
|
|
110
|
+
**Do NOT read any docs.** Just return this answer directly:
|
|
111
|
+
|
|
112
|
+
> To restart the server gracefully (hot restart, zero downtime):
|
|
113
|
+
> ```
|
|
114
|
+
> kill -USR1 $OCTO_MASTER_PID
|
|
115
|
+
> ```
|
|
116
|
+
> This sends USR1 to the Master process, which spawns a new Worker and gracefully stops the old one.
|
|
117
|
+
> The `$OCTO_MASTER_PID` environment variable is already set in the current session.
|
|
118
|
+
|
|
119
|
+
### Restart failure, upgrade failure, or downgrade
|
|
120
|
+
|
|
121
|
+
If the user mentions restart failure, upgrade failure, or how to downgrade (e.g. "重启失败", "升级失败", "降级", "restart failed", "upgrade failed", "downgrade", "如何降级"):
|
|
122
|
+
|
|
123
|
+
→ Read `faq.md` — it has a dedicated Troubleshooting section covering all three scenarios.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Model & API Key Configuration
|
|
2
|
+
|
|
3
|
+
## Interactive Configuration
|
|
4
|
+
|
|
5
|
+
During a session:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
> /config
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This opens an interactive prompt to set:
|
|
12
|
+
|
|
13
|
+
- **API Key** — Your model provider key
|
|
14
|
+
- **Model** — Model identifier (e.g., `anthropic/claude-opus-4-7`)
|
|
15
|
+
- **Base URL** — Provider endpoint
|
|
16
|
+
- **Anthropic Format** — Whether to use native Anthropic Messages format
|
|
17
|
+
|
|
18
|
+
## Config File
|
|
19
|
+
|
|
20
|
+
Configuration is stored in `~/.octo/config.yml`:
|
|
21
|
+
|
|
22
|
+
```yaml
|
|
23
|
+
models:
|
|
24
|
+
- model: anthropic/claude-opus-4-7
|
|
25
|
+
api_key: sk-xxx
|
|
26
|
+
base_url: https://api.anthropic.com
|
|
27
|
+
type: default
|
|
28
|
+
anthropic_format: true
|
|
29
|
+
- model: anthropic/claude-haiku-4-5
|
|
30
|
+
api_key: sk-xxx
|
|
31
|
+
base_url: https://api.anthropic.com
|
|
32
|
+
type: lite
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Environment Variables
|
|
36
|
+
|
|
37
|
+
| Variable | Description |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `OCTO_API_KEY` | Default model API key |
|
|
40
|
+
| `OCTO_BASE_URL` | Default model base URL |
|
|
41
|
+
| `OCTO_MODEL` | Default model name |
|
|
42
|
+
| `OCTO_ANTHROPIC_FORMAT` | Use anthropic format |
|
|
43
|
+
| `OCTO_LITE_API_KEY` | Lite model API key |
|
|
44
|
+
| `OCTO_LITE_BASE_URL` | Lite model base URL |
|
|
45
|
+
| `OCTO_LITE_MODEL` | Lite model name |
|
|
46
|
+
|
|
47
|
+
ClaudeCode-compatible variables are also supported:
|
|
48
|
+
|
|
49
|
+
| Variable | Description |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `ANTHROPIC_API_KEY` | API key |
|
|
52
|
+
| `ANTHROPIC_BASE_URL` | Base URL |
|
|
53
|
+
|
|
54
|
+
## Model Types
|
|
55
|
+
|
|
56
|
+
- **default** — Primary model for main agent work
|
|
57
|
+
- **lite** — Cheaper/faster model for subagents and simple tasks
|
|
58
|
+
- **fallback** — Used when the primary model is unavailable
|
|
59
|
+
|
|
60
|
+
## Supported Providers
|
|
61
|
+
|
|
62
|
+
Octo has built-in presets for:
|
|
63
|
+
|
|
64
|
+
- **openrouter** — `https://openrouter.ai/api/v1`
|
|
65
|
+
- **anthropic** — `https://api.anthropic.com`
|
|
66
|
+
- **openai** — `https://api.openai.com`
|
|
67
|
+
- **bedrock** — AWS Bedrock
|
|
68
|
+
- **deepseek** — `https://api.deepseek.com`
|
|
69
|
+
- **kimi** — `https://api.moonshot.cn`
|
|
70
|
+
- **minimax** — `https://api.minimax.chat`
|
|
71
|
+
- **qwen** — `https://dashscope.aliyuncs.com`
|
|
72
|
+
- **glm** — `https://open.bigmodel.cn/api/paas/v4`
|
|
73
|
+
|
|
74
|
+
Use any custom endpoint by specifying `base_url` directly.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Advanced Patterns & Best Practices
|
|
2
|
+
|
|
3
|
+
## Skill Composition
|
|
4
|
+
|
|
5
|
+
Break complex workflows into smaller skills that call each other:
|
|
6
|
+
|
|
7
|
+
- `setup-project` — Initialize repository structure
|
|
8
|
+
- `add-auth` — Add authentication
|
|
9
|
+
- `add-tests` — Add test suite
|
|
10
|
+
|
|
11
|
+
## Context Management
|
|
12
|
+
|
|
13
|
+
- Use `fork_agent: true` for tasks that need clean context
|
|
14
|
+
- Use `auto_summarize: true` for long-running tasks
|
|
15
|
+
- Use `forbidden_tools` to restrict what a skill can do
|
|
16
|
+
|
|
17
|
+
## Testing Skills
|
|
18
|
+
|
|
19
|
+
Before distributing a skill:
|
|
20
|
+
|
|
21
|
+
1. Run it yourself in multiple scenarios
|
|
22
|
+
2. Check edge cases (empty input, invalid paths)
|
|
23
|
+
3. Verify it handles errors gracefully
|
|
24
|
+
|
|
25
|
+
## Versioning
|
|
26
|
+
|
|
27
|
+
Version skills by directory name:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
skills/
|
|
31
|
+
my-skill-v1/
|
|
32
|
+
my-skill-v2/
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Project-Specific Defaults
|
|
36
|
+
|
|
37
|
+
Place a `.octorules` file in project root to give the agent context about your codebase conventions.
|
|
38
|
+
|
|
39
|
+
## Performance
|
|
40
|
+
|
|
41
|
+
- Lite models (`anthropic/claude-haiku-4-5`, etc.) are great for simple tasks
|
|
42
|
+
- Use fallback models for reliability
|
|
43
|
+
- Disable memory with `--no-memory` if you don't need persistence
|
|
44
|
+
|
|
45
|
+
## Security
|
|
46
|
+
|
|
47
|
+
- Never commit API keys to version control
|
|
48
|
+
- Use `forbidden_tools` to restrict file/shell access for untrusted skills
|
|
49
|
+
- Run with `--mode=confirm_all` when working with sensitive codebases
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Browser Automation
|
|
2
|
+
|
|
3
|
+
Octo can control a real browser (Chrome or Edge) for web automation tasks.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
Use the built-in `browser-setup` skill:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
> /browser-setup
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or manually configure `~/.octo/browser.yml`:
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
browser: chrome
|
|
17
|
+
remote_debugging_port: 9222
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
- **macOS**: Chrome or Edge installed
|
|
23
|
+
- **Linux**: Chrome/Chromium installed
|
|
24
|
+
- **Windows/WSL**: Chrome on Windows accessible via remote debugging
|
|
25
|
+
|
|
26
|
+
## How It Works
|
|
27
|
+
|
|
28
|
+
Octo connects to the browser via Chrome DevTools Protocol (CDP):
|
|
29
|
+
|
|
30
|
+
1. Start browser with remote debugging enabled
|
|
31
|
+
2. Octo connects to `localhost:9222`
|
|
32
|
+
3. Agent can navigate, click, type, scroll, and extract page content
|
|
33
|
+
|
|
34
|
+
## Supported Actions
|
|
35
|
+
|
|
36
|
+
- Navigate to URLs
|
|
37
|
+
- Click elements
|
|
38
|
+
- Type text / fill forms
|
|
39
|
+
- Scroll pages
|
|
40
|
+
- Take screenshots
|
|
41
|
+
- Evaluate JavaScript
|
|
42
|
+
- Extract page content
|
|
43
|
+
|
|
44
|
+
## WSL Setup
|
|
45
|
+
|
|
46
|
+
For WSL users, the `browser-setup` skill guides you through connecting to Windows Chrome from WSL.
|
|
47
|
+
|
|
48
|
+
## Troubleshooting
|
|
49
|
+
|
|
50
|
+
If browser automation fails:
|
|
51
|
+
1. Ensure Chrome/Edge is running with `--remote-debugging-port=9222`
|
|
52
|
+
2. Check `~/.octo/browser.yml` configuration
|
|
53
|
+
3. Run `/browser-setup` to reconfigure
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Built-in Skills
|
|
2
|
+
|
|
3
|
+
Octo ships with the following default skills:
|
|
4
|
+
|
|
5
|
+
| Skill | Description |
|
|
6
|
+
|---|---|
|
|
7
|
+
| **browser-setup** | Configure Chrome/Edge for browser automation |
|
|
8
|
+
| **channel-manager** | Set up IM platform integrations (Feishu, WeCom, WeChat, Discord, Telegram) |
|
|
9
|
+
| **code-explorer** | Explore and analyze project/code structure |
|
|
10
|
+
| **cron-task-creator** | Create and manage scheduled automated tasks |
|
|
11
|
+
| **onboard** | New user onboarding guide |
|
|
12
|
+
| **persist-memory** | Save information to long-term memory |
|
|
13
|
+
| **personal-website** | Generate and publish a personal homepage |
|
|
14
|
+
| **product-help** | Help with Octo features, configuration, and usage |
|
|
15
|
+
| **recall-memory** | Recall information from long-term memory |
|
|
16
|
+
| **skill-add** | Install skills from zip URLs or local files |
|
|
17
|
+
| **skill-creator** | Create, modify, and optimize skills |
|
|
18
|
+
|
|
19
|
+
## Location
|
|
20
|
+
|
|
21
|
+
Built-in skills are stored in:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
lib/octo/default_skills/
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Customization
|
|
28
|
+
|
|
29
|
+
You can override built-in skills by placing a skill with the same name in:
|
|
30
|
+
|
|
31
|
+
- `.octo/skills/` (project-level)
|
|
32
|
+
- `~/.octo/skills/` (user-level)
|
|
33
|
+
|
|
34
|
+
User-level skills take precedence over built-in skills.
|
|
35
|
+
|
|
36
|
+
## Removed Skills
|
|
37
|
+
|
|
38
|
+
The following skills were previously built-in but removed due to being too opinionated:
|
|
39
|
+
|
|
40
|
+
- **deploy** — Coupled to Railway + Rails
|
|
41
|
+
- **new** — Assumed specific Rails scaffolding
|
|
42
|
+
|
|
43
|
+
These can still be installed as custom skills via `/skill-add`.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# CLI Reference
|
|
2
|
+
|
|
3
|
+
## Commands
|
|
4
|
+
|
|
5
|
+
### `octo agent` (default)
|
|
6
|
+
|
|
7
|
+
Run an AI agent in interactive mode.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
octo agent [OPTIONS]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**Options:**
|
|
14
|
+
|
|
15
|
+
| Option | Description |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `--mode=MODE` | Permission mode: `auto_approve`, `confirm_safes`, `confirm_all` (default: `confirm_safes`) |
|
|
18
|
+
| `--theme=THEME` | UI theme: `hacker`, `minimal` (default: `hacker`) |
|
|
19
|
+
| `-v, --verbose` | Show detailed output |
|
|
20
|
+
| `--path=PATH` | Project directory path (default: current directory) |
|
|
21
|
+
| `-c, --continue` | Continue most recent session |
|
|
22
|
+
| `-l, --list` | List recent sessions |
|
|
23
|
+
| `-a, --attach=N` | Attach to session by number or ID prefix |
|
|
24
|
+
| `--json` | Output NDJSON to stdout |
|
|
25
|
+
| `-m, --message=MSG` | Run non-interactively and exit |
|
|
26
|
+
| `-f, --file=PATH` | Attach file(s) (use with `-m`) |
|
|
27
|
+
| `--agent=PROFILE` | Agent profile: `coding`, `general` (default: `coding`) |
|
|
28
|
+
| `--model=MODEL` | Override the model to use |
|
|
29
|
+
|
|
30
|
+
**Examples:**
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Interactive mode
|
|
34
|
+
octo
|
|
35
|
+
|
|
36
|
+
# Auto-approve all tools
|
|
37
|
+
octo --mode=auto_approve
|
|
38
|
+
|
|
39
|
+
# Continue previous session
|
|
40
|
+
octo -c
|
|
41
|
+
|
|
42
|
+
# One-shot task
|
|
43
|
+
octo -m "write a hello world script"
|
|
44
|
+
|
|
45
|
+
# Attach files
|
|
46
|
+
octo -m "review this code" -f src/main.rb
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### `octo server`
|
|
50
|
+
|
|
51
|
+
Start the Web UI server.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
octo server [OPTIONS]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
| Option | Description |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `-b, --host=HOST` | Bind host (default: `127.0.0.1`) |
|
|
60
|
+
| `-p, --port=N` | Listen port (default: `8888`) |
|
|
61
|
+
| `--no-compression` | Disable message compression |
|
|
62
|
+
| `--no-memory` | Disable automatic memory updates |
|
|
63
|
+
| `--no-caching` | Disable prompt caching |
|
|
64
|
+
| `--no-skill-evolution` | Disable automatic skill evolution |
|
|
65
|
+
|
|
66
|
+
### `octo tree`
|
|
67
|
+
|
|
68
|
+
Print a tree of all available commands.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
octo tree
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Interactive Commands
|
|
75
|
+
|
|
76
|
+
During an agent session, you can use:
|
|
77
|
+
|
|
78
|
+
| Command | Description |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `/config` | Open configuration editor |
|
|
81
|
+
| `/` | List and invoke skills |
|
|
82
|
+
| `exit` or `quit` | End the session |
|