on main help sign in
8775 files changed+5726259−40329
since splitsnapshots
unifiedsplit
.agents/skills/builtin-skills/SKILL.md+42 .agents/skills/shell-builtins/SKILL.md+72 .envrc+1 .gitattributes+2 .github/CODEOWNERS−1 .github/cla-signatures.json+1368 .github/dependabot.yml+1 .github/labeler.yml+14 .github/workflows/build.yml+26−7 .github/workflows/cla.yml+2−2 .github/workflows/labeler.yml+1−1 .github/workflows/lint.yml+2−1 .github/workflows/nightly.yml+1−1 .github/workflows/release.yml+1−3 .github/workflows/schema-update.yml+11−8 .github/workflows/security.yml+92 .github/workflows/snapshot.yml+34 .gitignore+7−2 .golangci.yml+16−4 .goreleaser.yml+22−6 AGENTS.md+223 CRUSH.md−65 LICENSE.md+1−1 README.md+399−76 Taskfile.yaml+102−4 crush.json+35−1 cspell.json−1 docs/hooks/FUTURE.md+260 docs/hooks/README.md+759 docs/hooks/examples/rtk-rewrite.sh+60 flake.lock+60 flake.nix+75 go.mod+162−111 go.sum+367−212 internal/agent/.env.sample+1 internal/agent/accepted_run_test.go+231 internal/agent/agent.go+1672−196 internal/agent/agent_test.go+417−16 internal/agent/agent_tool.go+14−55 internal/agent/agentic_fetch_tool.go+206 internal/agent/agenttest/coordinator.go+80 internal/agent/common_test.go+72−73 internal/agent/convert_test.go+94 internal/agent/coordinator.go+1164−170 internal/agent/coordinator_test.go+554 internal/agent/dispatch_cancel_test.go+447 internal/agent/errors.go+1−8 internal/agent/event.go+51 internal/agent/hooked_tool.go+142 internal/agent/hooked_tool_test.go+147 internal/agent/hyper/provider.go+105 internal/agent/hyper/provider.json+295 internal/agent/loop_detection.go+92 internal/agent/loop_detection_test.go+205 internal/agent/notify/notify.go+63 internal/agent/prompt/prompt.go+151−43 internal/agent/prompts.go+10−4 internal/agent/queued_runid_test.go+181 internal/agent/recorder_test.go−104 internal/agent/run_complete_test.go+322 internal/agent/run_marker.go+52 internal/agent/runid.go+33 internal/agent/templates/agent_tool.md+1−15 internal/agent/templates/agentic_fetch.md+1 internal/agent/templates/agentic_fetch_prompt.md.tpl+76 internal/agent/templates/coder.md.tpl+250−22 internal/agent/templates/initialize.md−9 internal/agent/templates/initialize.md.tpl+29 internal/agent/templates/summary.md+43−12 internal/agent/templates/title.md+8−7 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/bash_tool.yaml−204 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/download_tool.yaml−227 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/fetch_tool.yaml−245 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/glob_tool.yaml−168 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/grep_tool.yaml−183 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/ls_tool.yaml−174 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/multiedit_tool.yaml−314 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/parallel_tool_calls.yaml−201 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/read_a_file.yaml−183 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/simple_test.yaml−109 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/sourcegraph_tool.yaml−223 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/update_a_file.yaml−293 internal/agent/testdata/TestCoderAgent/anthropic-sonnet/write_tool.yaml−243 internal/agent/testdata/TestCoderAgent/glm-5.1/bash_tool.yaml+425 internal/agent/testdata/TestCoderAgent/glm-5.1/download_tool.yaml+483 internal/agent/testdata/TestCoderAgent/glm-5.1/fetch_tool.yaml+650 internal/agent/testdata/TestCoderAgent/glm-5.1/glob_tool.yaml+737 internal/agent/testdata/TestCoderAgent/glm-5.1/grep_tool.yaml+499 internal/agent/testdata/TestCoderAgent/glm-5.1/ls_tool.yaml+485 internal/agent/testdata/TestCoderAgent/glm-5.1/multiedit_tool.yaml+1439 internal/agent/testdata/TestCoderAgent/glm-5.1/parallel_tool_calls.yaml+685 internal/agent/testdata/TestCoderAgent/glm-5.1/read_a_file.yaml+413 internal/agent/testdata/TestCoderAgent/glm-5.1/simple_test.yaml+277 internal/agent/testdata/TestCoderAgent/glm-5.1/sourcegraph_tool.yaml+1479 internal/agent/testdata/TestCoderAgent/glm-5.1/update_a_file.yaml+747 internal/agent/testdata/TestCoderAgent/glm-5.1/write_tool.yaml+547 internal/agent/testdata/TestCoderAgent/openai-gpt-5/bash_tool.yaml−174 internal/agent/testdata/TestCoderAgent/openai-gpt-5/download_tool.yaml−198 internal/agent/testdata/TestCoderAgent/openai-gpt-5/fetch_tool.yaml−218 internal/agent/testdata/TestCoderAgent/openai-gpt-5/glob_tool.yaml−182 internal/agent/testdata/TestCoderAgent/openai-gpt-5/grep_tool.yaml−212 internal/agent/testdata/TestCoderAgent/openai-gpt-5/ls_tool.yaml−144 internal/agent/testdata/TestCoderAgent/openai-gpt-5/multiedit_tool.yaml−553 internal/agent/testdata/TestCoderAgent/openai-gpt-5/parallel_tool_calls.yaml−254 internal/agent/testdata/TestCoderAgent/openai-gpt-5/read_a_file.yaml−293 internal/agent/testdata/TestCoderAgent/openai-gpt-5/simple_test.yaml−83 internal/agent/testdata/TestCoderAgent/openai-gpt-5/sourcegraph_tool.yaml−386 internal/agent/testdata/TestCoderAgent/openai-gpt-5/update_a_file.yaml−509 internal/agent/testdata/TestCoderAgent/openai-gpt-5/write_tool.yaml−220 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/bash_tool.yaml−279 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/download_tool.yaml−220 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/fetch_tool.yaml−194 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/glob_tool.yaml−136 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/grep_tool.yaml−160 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/ls_tool.yaml−176 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/multiedit_tool.yaml−563 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/parallel_tool_calls.yaml−210 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/read_a_file.yaml−198 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/simple_test.yaml−83 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/sourcegraph_tool.yaml−186 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/update_a_file.yaml−385 internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/write_tool.yaml−212 internal/agent/testdata/TestCoderAgent/zai-glm4.6/bash_tool.yaml−310 internal/agent/testdata/TestCoderAgent/zai-glm4.6/download_tool.yaml−162 internal/agent/testdata/TestCoderAgent/zai-glm4.6/fetch_tool.yaml−228 internal/agent/testdata/TestCoderAgent/zai-glm4.6/glob_tool.yaml−162 internal/agent/testdata/TestCoderAgent/zai-glm4.6/grep_tool.yaml−196 internal/agent/testdata/TestCoderAgent/zai-glm4.6/ls_tool.yaml−222 internal/agent/testdata/TestCoderAgent/zai-glm4.6/multiedit_tool.yaml−269 internal/agent/testdata/TestCoderAgent/zai-glm4.6/parallel_tool_calls.yaml−298 internal/agent/testdata/TestCoderAgent/zai-glm4.6/read_a_file.yaml−142 internal/agent/testdata/TestCoderAgent/zai-glm4.6/simple_test.yaml−189 internal/agent/testdata/TestCoderAgent/zai-glm4.6/sourcegraph_tool.yaml−334 internal/agent/testdata/TestCoderAgent/zai-glm4.6/update_a_file.yaml−189 internal/agent/testdata/TestCoderAgent/zai-glm4.6/write_tool.yaml−142 internal/agent/tools/bash.go+214−92 internal/agent/tools/bash.md.tpl+173 internal/agent/tools/bash.tpl−116 internal/agent/tools/bash_test.go+213 internal/agent/tools/context_test.go+233 internal/agent/tools/crush_info.go+487 internal/agent/tools/crush_info.md+19 internal/agent/tools/crush_info_test.go+505 internal/agent/tools/crush_logs.go+514 internal/agent/tools/crush_logs.md.tpl+13 internal/agent/tools/crush_logs_test.go+529 internal/agent/tools/diagnostics.go+101−21 internal/agent/tools/diagnostics.md+1−24 internal/agent/tools/download.go+48−41 internal/agent/tools/download.md−28 internal/agent/tools/download.md.tpl+1 internal/agent/tools/edit.go+108−75 internal/agent/tools/edit.md+1−57 internal/agent/tools/fetch.go+62−54 internal/agent/tools/fetch.md−28 internal/agent/tools/fetch.md.tpl+2 internal/agent/tools/fetch_helpers.go+175 internal/agent/tools/fetch_types.go+50 internal/agent/tools/file.go−53 internal/agent/tools/glob.go+106−29 internal/agent/tools/glob.md−40 internal/agent/tools/glob.md.tpl+1 internal/agent/tools/glob_test.go+74 internal/agent/tools/grep.go+73−46 internal/agent/tools/grep.md−49 internal/agent/tools/grep.md.tpl+1 internal/agent/tools/job_kill.go+60 internal/agent/tools/job_kill.md+18 internal/agent/tools/job_output.go+92 internal/agent/tools/job_output.md+1 internal/agent/tools/job_test.go+334 internal/agent/tools/list_mcp_resources.go+100 internal/agent/tools/list_mcp_resources.md+1 internal/agent/tools/ls.go+46−20 internal/agent/tools/ls.md−34 internal/agent/tools/ls.md.tpl+1 internal/agent/tools/lsp_restart.go+80 internal/agent/tools/lsp_restart.md+1 internal/agent/tools/mcp-tools.go+75−449 internal/agent/tools/mcp/init.go+554 internal/agent/tools/mcp/init_test.go+526 internal/agent/tools/mcp/prompts.go+88 internal/agent/tools/mcp/resources.go+109 internal/agent/tools/mcp/tools.go+248 internal/agent/tools/mcp/tools_test.go+117 internal/agent/tools/multiedit.go+140−55 internal/agent/tools/multiedit.md+1−47 internal/agent/tools/multiedit_test.go+214 internal/agent/tools/read_mcp_resource.go+103 internal/agent/tools/read_mcp_resource.md+1 internal/agent/tools/references.go+17−21 internal/agent/tools/references.md+1−36 internal/agent/tools/rg.go+10−1 internal/agent/tools/safe.go+99−6 internal/agent/tools/safe_test.go+74 internal/agent/tools/search.go+219 internal/agent/tools/sourcegraph.go+41−23 internal/agent/tools/sourcegraph.md−55 internal/agent/tools/sourcegraph.md.tpl+1 internal/agent/tools/todos.go+135 internal/agent/tools/todos.md+1 internal/agent/tools/tools.go+81−15 internal/agent/tools/view.go+315−127 internal/agent/tools/view.md−35 internal/agent/tools/view.md.tpl+1 internal/agent/tools/view_test.go+356 internal/agent/tools/web_fetch.go+80 internal/agent/tools/web_fetch.md.tpl+2 internal/agent/tools/web_search.go+62 internal/agent/tools/web_search.md.tpl+2 internal/agent/tools/write.go+54−49 internal/agent/tools/write.md+1−30 internal/agent/tools/write_test.go+49 internal/agent/usage_fallback.go+167 internal/agent/usage_fallback_test.go+339 internal/app/app.go+521−83 internal/app/app_test.go+183 internal/app/lsp.go−80 internal/app/lsp_events.go+3−2 internal/app/provider.go+95 internal/app/provider_test.go+210 internal/app/resolve_session_test.go+174 internal/app/testing.go+72 internal/backend/accepted_run_integration_test.go+131 internal/backend/agent.go+273 internal/backend/agent_runcomplete_test.go+163 internal/backend/agent_test.go+164 internal/backend/backend.go+792 internal/backend/backend_skills_test.go+167 internal/backend/backend_test.go+1241 internal/backend/config.go+307 internal/backend/config_test.go+205 internal/backend/events.go+109 internal/backend/filetracker.go+37 internal/backend/permission.go+60 internal/backend/race_off_test.go+5 internal/backend/race_on_test.go+5 internal/backend/session.go+132 internal/backend/shell_command_test.go+54 internal/backend/testing.go+69 internal/backend/util.go+22 internal/client/client.go+213 internal/client/config.go+345 internal/client/config_test.go+101 internal/client/dial_other.go+13 internal/client/dial_windows.go+15 internal/client/proto.go+861 internal/client/proto_test.go+178 internal/clipboard/clipboard.go+44 internal/clipboard/clipboard_not_supported.go+13 internal/clipboard/clipboard_supported.go+30 internal/cmd/clientserverrace/race_test.go+361 internal/cmd/dirs.go+63−38 internal/cmd/dirs_test.go−46 internal/cmd/gitignore/default+4 internal/cmd/gitignore/old+1 internal/cmd/login.go+229 internal/cmd/login_test.go+21 internal/cmd/logout.go+182 internal/cmd/logout_test.go+41 internal/cmd/logs.go+12−7 internal/cmd/models.go+155 internal/cmd/projects.go+77 internal/cmd/projects_test.go+56 internal/cmd/root.go+653−67 internal/cmd/root_other.go+15 internal/cmd/root_windows.go+18 internal/cmd/run.go+624−18 internal/cmd/run_stream_test.go+417 internal/cmd/schema.go+35−1 internal/cmd/schema_test.go+59 internal/cmd/server.go+99 internal/cmd/server_other.go+12 internal/cmd/server_windows.go+10 internal/cmd/session.go+728 internal/cmd/stats.go+390 internal/cmd/stats/AGENTS.md+3 internal/cmd/stats/footer.svg+838 internal/cmd/stats/header.svg+673 internal/cmd/stats/heartbit.svg+43 internal/cmd/stats/index.css+270 internal/cmd/stats/index.html+136 internal/cmd/stats/index.js+356 internal/cmd/update_providers.go+33−11 internal/commands/commands.go+239 internal/commands/commands_test.go+114 internal/config/agent_id_test.go+29 internal/config/atomicwrite.go+38 internal/config/atomicwrite_test.go+43 internal/config/attribution_migration_test.go+93 internal/config/catwalk.go+82 internal/config/catwalk_test.go+221 internal/config/clone_test.go+46 internal/config/config.go+507−185 internal/config/copilot.go+1 internal/config/docker_mcp.go+141 internal/config/docker_mcp_test.go+195 internal/config/hyper.go+124 internal/config/hyper_test.go+205 internal/config/init.go+35−23 internal/config/load.go+750−147 internal/config/load_bench_test.go+103 internal/config/load_test.go+1162−117 internal/config/mcp_resolved_url_test.go+105 internal/config/merge.go−16 internal/config/merge_test.go−27 internal/config/provider.go+150−93 internal/config/provider_empty_test.go+20−28 internal/config/provider_test.go+277−42 internal/config/recent_models_test.go+158 internal/config/refresh_singleflight_test.go+175 internal/config/reload_hooks_test.go+102 internal/config/resolve.go+140−131 internal/config/resolve_real_test.go+512 internal/config/resolve_test.go+185−288 internal/config/scope.go+29 internal/config/scopeb_race_test.go+74 internal/config/store.go+1078 internal/config/store_test.go+784 internal/config/update_model_bench_test.go+108 internal/csync/maps.go+32−10 internal/csync/maps_test.go+4−3 internal/csync/slices.go+10−34 internal/csync/slices_test.go−57 internal/csync/value.go+44 internal/csync/value_test.go+97 internal/csync/versionedmap.go+5 internal/db/connect.go+195−33 internal/db/connect_modernc.go+31 internal/db/connect_ncruces.go+33 internal/db/connect_test.go+210 internal/db/datadirlock.go+131 internal/db/db.go+235−45 internal/db/embed.go−6 internal/db/files.sql.go+21−5 internal/db/messages.sql.go+132−2 internal/db/migrations/20250812000000_add_todos_to_sessions.sql+9 internal/db/migrations/20260127000000_add_read_files_table.sql+20 internal/db/migrations/20260701000000_add_composite_indexes.sql+12 internal/db/migrations/20260702000000_add_hot_path_indexes.sql+14 internal/db/models.go+8−1 internal/db/querier.go+20−1 internal/db/read_files.sql.go+79 internal/db/sessions.sql.go+117−7 internal/db/sql/files.sql+12−4 internal/db/sql/messages.sql+19 internal/db/sql/read_files.sql+20 internal/db/sql/sessions.sql+27−2 internal/db/sql/stats.sql+93 internal/db/stats.sql.go+367 internal/diffdetect/detect.go+36 internal/diffdetect/detect_test.go+152 internal/discover/discover.go+145 internal/discover/discover_test.go+221 internal/discover/enricher.go+60 internal/discover/litellm.go+87 internal/discover/litellm_test.go+173 internal/discover/llamacpp.go+83 internal/discover/llamacpp_test.go+135 internal/discover/lmstudio.go+95 internal/discover/lmstudio_test.go+154 internal/discover/ollama.go+105 internal/discover/ollama_test.go+131 internal/discover/omlx.go+73 internal/discover/omlx_test.go+92 internal/dns/android.go+41 internal/env/env.go+4−9 internal/env/env_test.go+6−4 internal/event/all.go+24 internal/event/event.go+75−20 internal/event/event_test.go+105 internal/filepathext/filepath.go+52 internal/filepathext/filepath_test.go+37 internal/filetracker/service.go+110 internal/filetracker/service_test.go+116 internal/format/spinner.go+13−25 internal/fsext/drive_other.go+16 internal/fsext/drive_windows.go+26 internal/fsext/fileutil.go+77−35 internal/fsext/fileutil_dirtrim_test.go+32 internal/fsext/fileutil_test.go+13−13 internal/fsext/ignore_test.go+3−3 internal/fsext/lookup.go+142−7 internal/fsext/lookup_test.go+125 internal/fsext/ls.go+187−124 internal/fsext/ls_test.go+3−2 internal/fsext/owner_others.go+8−5 internal/fsext/owner_windows.go+7 internal/fsext/paste.go+129 internal/fsext/paste_test.go+149 internal/herdr/client.go+405 internal/herdr/client_test.go+158 internal/herdr/translate.go+150 internal/herdr/translate_test.go+145 internal/history/file.go+28−16 internal/home/home.go+24−20 internal/hooks/hooks.go+193 internal/hooks/hooks_test.go+757 internal/hooks/input.go+211 internal/hooks/runner.go+265 internal/lock/lock.go+75 internal/lock/lock_test.go+168 internal/lock/lock_unix.go+45 internal/lock/lock_windows.go+57 internal/log/http.go+5−2 internal/log/log.go+20−4 internal/lsp/client.go+357−153 internal/lsp/client_test.go+149−2 internal/lsp/handlers.go+21−24 internal/lsp/language.go−132 internal/lsp/manager.go+412 internal/lsp/manager_test.go+35 internal/lsp/rootmarkers_test.go−37 internal/lsp/util/edit.go+94−46 internal/lsp/util/edit_test.go+376 internal/message/attachment.go+16 internal/message/content.go+183−33 internal/message/content_test.go+142 internal/message/message.go+468−65 internal/message/message_test.go+695 internal/oauth/copilot/client.go+94 internal/oauth/copilot/client_test.go+70 internal/oauth/copilot/disk.go+36 internal/oauth/copilot/http.go+17 internal/oauth/copilot/oauth.go+200 internal/oauth/copilot/urls.go+6 internal/oauth/hyper/device.go+251 internal/oauth/token.go+57 internal/permission/permission.go+176−92 internal/permission/permission_test.go+377−9 internal/projects/projects.go+126 internal/projects/projects_test.go+186 internal/proto/agent.go+82 internal/proto/history.go+12 internal/proto/mcp.go+172 internal/proto/message.go+714 internal/proto/permission.go+147 internal/proto/permission_test.go+186 internal/proto/proto.go+309 internal/proto/requests.go+137 internal/proto/requests_test.go+106 internal/proto/server.go+6 internal/proto/session.go+37 internal/proto/skills.go+28 internal/proto/tools.go+234 internal/proto/version.go+10 internal/pubsub/broker.go+189−29 internal/pubsub/broker_test.go+117 internal/pubsub/events.go+42−6 internal/server/agent_cancel_test.go+227 internal/server/config.go+525 internal/server/e2e_agent_test.go+742 internal/server/e2e_test.go+612 internal/server/events.go+311 internal/server/events_test.go+182 internal/server/logging.go+53 internal/server/multiclient_test.go+230 internal/server/net_other.go+61 internal/server/net_windows.go+37 internal/server/proto.go+1129 internal/server/recover.go+59 internal/server/recover_test.go+94 internal/server/server.go+286 internal/server/sessions_isbusy_test.go+334 internal/server/socket.go+10 internal/server/socket_classify.go+27 internal/server/socket_test.go+193 internal/session/session.go+187−10 internal/session/session_test.go+81 internal/shell/background.go+245 internal/shell/background_test.go+330 internal/shell/coreutils.go+19 internal/shell/dispatch.go+425 internal/shell/dispatch_test.go+594 internal/shell/dispatch_windows_test.go+40 internal/shell/doc.go+1−6 internal/shell/exec_unix.go+108 internal/shell/exec_windows.go+23 internal/shell/expand.go+162 internal/shell/expand_test.go+241 internal/shell/isolation_unix_test.go+143 internal/shell/jq.go+342 internal/shell/jq_test.go+212 internal/shell/persist_message.go+44 internal/shell/persist_message_test.go+69 internal/shell/persistent.go−43 internal/shell/run.go+345 internal/shell/run_test.go+364 internal/shell/shell.go+80−44 internal/shell/stream.go+52 internal/skills/builtin/crush-config/SKILL.md+370 internal/skills/builtin/crush-hooks/SKILL.md+209 internal/skills/builtin/jq/SKILL.md+97 internal/skills/catalog.go+154 internal/skills/diagnostics_test.go+104 internal/skills/embed.go+79 internal/skills/manager.go+227 internal/skills/manager_test.go+249 internal/skills/skills.go+437 internal/skills/skills_test.go+520 internal/skills/tracker.go+86 internal/skills/tracker_test.go+102 internal/stringext/string.go+40 internal/stringext/string_test.go+38 internal/swagger/docs.go+3717 internal/swagger/swagger.json+3692 internal/swagger/swagger.yaml+2457 internal/tui/components/anim/anim.go−446 internal/tui/components/chat/chat.go−807 internal/tui/components/chat/editor/editor.go−590 internal/tui/components/chat/editor/keys.go−71 internal/tui/components/chat/header/header.go−167 internal/tui/components/chat/messages/messages.go−430 internal/tui/components/chat/messages/renderer.go−892 internal/tui/components/chat/messages/tool.go−812 internal/tui/components/chat/queue.go−28 internal/tui/components/chat/sidebar/sidebar.go−613 internal/tui/components/chat/splash/keys.go−53 internal/tui/components/chat/splash/splash.go−723 internal/tui/components/completions/completions.go−308 internal/tui/components/completions/keys.go−72 internal/tui/components/core/core.go−207 internal/tui/components/core/layout/layout.go−27 internal/tui/components/core/status/status.go−109 internal/tui/components/core/status_test.go−144 internal/tui/components/core/testdata/TestStatus/AllFieldsWithExtraContent.golden−1 internal/tui/components/core/testdata/TestStatus/Default.golden−1 internal/tui/components/core/testdata/TestStatus/EmptyDescription.golden−1 internal/tui/components/core/testdata/TestStatus/LongDescription.golden−1 internal/tui/components/core/testdata/TestStatus/NarrowWidth.golden−1 internal/tui/components/core/testdata/TestStatus/NoIcon.golden−1 internal/tui/components/core/testdata/TestStatus/VeryNarrowWidth.golden−1 internal/tui/components/core/testdata/TestStatus/WithColors.golden−1 internal/tui/components/core/testdata/TestStatus/WithCustomIcon.golden−1 internal/tui/components/core/testdata/TestStatus/WithExtraContent.golden−1 internal/tui/components/core/testdata/TestStatusTruncation/Width20.golden−1 internal/tui/components/core/testdata/TestStatusTruncation/Width30.golden−1 internal/tui/components/core/testdata/TestStatusTruncation/Width40.golden−1 internal/tui/components/core/testdata/TestStatusTruncation/Width50.golden−1 internal/tui/components/core/testdata/TestStatusTruncation/Width60.golden−1 internal/tui/components/dialogs/commands/arguments.go−230 internal/tui/components/dialogs/commands/commands.go−423 internal/tui/components/dialogs/commands/keys.go−133 internal/tui/components/dialogs/commands/loader.go−203 internal/tui/components/dialogs/dialogs.go−161 internal/tui/components/dialogs/filepicker/filepicker.go−260 internal/tui/components/dialogs/filepicker/keys.go−80 internal/tui/components/dialogs/keys.go−43 internal/tui/components/dialogs/models/apikey.go−202 internal/tui/components/dialogs/models/keys.go−85 internal/tui/components/dialogs/models/list.go−254 internal/tui/components/dialogs/models/models.go−393 internal/tui/components/dialogs/permissions/keys.go−113 internal/tui/components/dialogs/permissions/permissions.go−846 internal/tui/components/dialogs/quit/keys.go−75 internal/tui/components/dialogs/quit/quit.go−120 internal/tui/components/dialogs/reasoning/reasoning.go−264 internal/tui/components/dialogs/sessions/keys.go−67 internal/tui/components/dialogs/sessions/sessions.go−181 internal/tui/components/files/files.go−146 internal/tui/components/image/image.go−86 internal/tui/components/image/load.go−146 internal/tui/components/logo/logo.go−347 internal/tui/components/lsp/lsp.go−161 internal/tui/components/mcp/mcp.go−126 internal/tui/exp/diffview/chroma.go−57 internal/tui/exp/diffview/style.go−124 internal/tui/exp/diffview/testdata/TestDiffView/Split/CustomContextLines/DarkMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffView/Split/CustomContextLines/LightMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffView/Split/Default/DarkMode.golden−7 internal/tui/exp/diffview/testdata/TestDiffView/Split/Default/LightMode.golden−7 internal/tui/exp/diffview/testdata/TestDiffView/Split/LargeWidth/DarkMode.golden−15 internal/tui/exp/diffview/testdata/TestDiffView/Split/LargeWidth/LightMode.golden−15 internal/tui/exp/diffview/testdata/TestDiffView/Split/MultipleHunks/DarkMode.golden−15 internal/tui/exp/diffview/testdata/TestDiffView/Split/MultipleHunks/LightMode.golden−15 internal/tui/exp/diffview/testdata/TestDiffView/Split/Narrow/DarkMode.golden−4 internal/tui/exp/diffview/testdata/TestDiffView/Split/Narrow/LightMode.golden−4 internal/tui/exp/diffview/testdata/TestDiffView/Split/NoLineNumbers/DarkMode.golden−7 internal/tui/exp/diffview/testdata/TestDiffView/Split/NoLineNumbers/LightMode.golden−7 internal/tui/exp/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/DarkMode.golden−15 internal/tui/exp/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/LightMode.golden−15 internal/tui/exp/diffview/testdata/TestDiffView/Split/SmallWidth/DarkMode.golden−15 internal/tui/exp/diffview/testdata/TestDiffView/Split/SmallWidth/LightMode.golden−15 internal/tui/exp/diffview/testdata/TestDiffView/Unified/CustomContextLines/DarkMode.golden−17 internal/tui/exp/diffview/testdata/TestDiffView/Unified/CustomContextLines/LightMode.golden−17 internal/tui/exp/diffview/testdata/TestDiffView/Unified/Default/DarkMode.golden−8 internal/tui/exp/diffview/testdata/TestDiffView/Unified/Default/LightMode.golden−8 internal/tui/exp/diffview/testdata/TestDiffView/Unified/LargeWidth/DarkMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffView/Unified/LargeWidth/LightMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffView/Unified/MultipleHunks/DarkMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffView/Unified/MultipleHunks/LightMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffView/Unified/Narrow/DarkMode.golden−7 internal/tui/exp/diffview/testdata/TestDiffView/Unified/Narrow/LightMode.golden−7 internal/tui/exp/diffview/testdata/TestDiffView/Unified/NoLineNumbers/DarkMode.golden−8 internal/tui/exp/diffview/testdata/TestDiffView/Unified/NoLineNumbers/LightMode.golden−8 internal/tui/exp/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/DarkMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/LightMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffView/Unified/SmallWidth/DarkMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffView/Unified/SmallWidth/LightMode.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf002.golden−2 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf003.golden−3 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf004.golden−4 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf005.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf006.golden−6 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf007.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf008.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf009.golden−9 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf010.golden−10 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf011.golden−11 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf012.golden−12 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf013.golden−13 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf014.golden−14 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf015.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf016.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf017.golden−17 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf018.golden−18 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf019.golden−19 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf020.golden−20 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf002.golden−2 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf003.golden−3 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf004.golden−4 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf005.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf006.golden−6 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf007.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf008.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf009.golden−9 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf010.golden−10 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf011.golden−11 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf012.golden−12 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf013.golden−13 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf014.golden−14 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf015.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf016.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf017.golden−17 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf018.golden−18 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf019.golden−19 internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf020.golden−20 internal/tui/exp/diffview/testdata/TestDiffViewLineBreakIssue/Split.golden−9 internal/tui/exp/diffview/testdata/TestDiffViewLineBreakIssue/Unified.golden−12 internal/tui/exp/diffview/testdata/TestDiffViewTabs/Split.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewTabs/Unified.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf001.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf002.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf003.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf004.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf005.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf006.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf007.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf008.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf009.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf010.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf011.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf012.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf013.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf014.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf015.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf016.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf017.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf018.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf019.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf020.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf021.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf022.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf023.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf024.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf025.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf026.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf027.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf028.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf029.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf030.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf031.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf032.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf033.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf034.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf035.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf036.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf037.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf038.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf039.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf040.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf041.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf042.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf043.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf044.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf045.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf046.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf047.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf048.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf049.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf050.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf051.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf052.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf053.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf054.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf055.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf056.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf057.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf058.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf059.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf060.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf061.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf062.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf063.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf064.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf065.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf066.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf067.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf068.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf069.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf070.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf071.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf072.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf073.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf074.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf075.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf076.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf077.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf078.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf079.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf080.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf081.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf082.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf083.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf084.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf085.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf086.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf087.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf088.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf089.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf090.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf091.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf092.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf093.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf094.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf095.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf096.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf097.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf098.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf099.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf100.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf101.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf102.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf103.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf104.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf105.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf106.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf107.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf108.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf109.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf110.golden−15 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf001.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf002.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf003.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf004.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf005.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf006.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf007.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf008.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf009.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf010.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf011.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf012.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf013.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf014.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf015.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf016.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf017.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf018.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf019.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf020.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf021.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf022.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf023.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf024.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf025.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf026.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf027.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf028.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf029.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf030.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf031.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf032.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf033.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf034.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf035.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf036.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf037.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf038.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf039.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf040.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf041.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf042.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf043.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf044.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf045.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf046.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf047.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf048.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf049.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf050.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf051.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf052.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf053.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf054.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf055.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf056.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf057.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf058.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf059.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf060.golden−16 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf00.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf01.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf02.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf03.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf04.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf05.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf06.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf07.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf08.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf09.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf10.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf11.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf12.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf13.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf14.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf15.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf16.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf17.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf18.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf19.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf20.golden−7 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf00.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf01.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf02.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf03.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf04.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf05.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf06.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf07.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf08.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf09.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf10.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf11.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf12.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf13.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf14.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf15.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf16.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf17.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf18.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf19.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf20.golden−8 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf00.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf01.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf02.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf03.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf04.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf05.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf06.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf07.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf08.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf09.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf10.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf11.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf12.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf13.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf14.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf15.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf16.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf00.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf01.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf02.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf03.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf04.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf05.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf06.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf07.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf08.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf09.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf10.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf11.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf12.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf13.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf14.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf15.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf16.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf00.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf01.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf02.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf03.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf04.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf05.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf06.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf07.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf08.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf09.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf10.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf11.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf12.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf13.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf14.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf15.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf16.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf00.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf01.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf02.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf03.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf04.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf05.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf06.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf07.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf08.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf09.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf10.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf11.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf12.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf13.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf14.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf15.golden−5 internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf16.golden−5 internal/tui/exp/diffview/util.go−39 internal/tui/exp/list/filterable.go−318 internal/tui/exp/list/filterable_group.go−315 internal/tui/exp/list/filterable_test.go−68 internal/tui/exp/list/grouped.go−103 internal/tui/exp/list/items.go−392 internal/tui/exp/list/keys.go−76 internal/tui/exp/list/list.go−1472 internal/tui/exp/list/list_test.go−652 internal/tui/exp/list/testdata/TestFilterableList/should_create_simple_filterable_list.golden−10 internal/tui/exp/list/testdata/TestList/should_go_to_selected_item_at_the_beginning.golden−10 internal/tui/exp/list/testdata/TestList/should_go_to_selected_item_at_the_beginning_backwards.golden−10 internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_does_not_fits_the_items.golden−10 internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_does_not_fits_the_items_and_has_multi_line_items.golden−10 internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_does_not_fits_the_items_and_has_multi_line_items_backwards.golden−10 internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_does_not_fits_the_items_backwards.golden−10 internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_fits_the_items.golden−20 internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_fits_the_items_backwards.golden−20 internal/tui/exp/list/testdata/TestListMovement/should_move_viewport_down.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_move_viewport_down_and_up.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_move_viewport_up.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_move_viewport_up_and_down.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_not_change_offset_when_new_items_are_appended_and_we_are_at_the_bottom_in_backwards_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_not_change_offset_when_new_items_are_prepended_and_we_are_at_the_top_in_forward_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_if_an_item_is_appended_and_we_are_in_forward_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_if_an_item_is_prepended_and_we_are_in_backwards_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_new_items_are_added_but_we_moved_down_in_forward_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_new_items_are_added_but_we_moved_up_in_backwards_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_above_is_decreases_in_forward_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_above_is_increased_in_backwards_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_above_is_increased_in_forward_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_below_is_decreases_in_backwards_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_below_is_increased_in_backwards_list.golden−10 internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_below_is_increased_in_forward_list.golden−10 internal/tui/highlight/highlight.go−54 internal/tui/keys.go−40 internal/tui/page/chat/chat.go−1116 internal/tui/page/chat/keys.go−38 internal/tui/page/page.go−8 internal/tui/styles/charmtone.go−75 internal/tui/styles/chroma.go−79 internal/tui/styles/icons.go−41 internal/tui/styles/markdown.go−20 internal/tui/styles/theme.go−696 internal/tui/tui.go−606 internal/tui/util/util.go−62 internal/ui/AGENTS.md+200 internal/ui/anim/anim.go+494 internal/ui/attachments/attachments.go+152 internal/ui/chat/agent.go+393 internal/ui/chat/applyhighlight_callback_test.go+207 internal/ui/chat/assistant.go+904 internal/ui/chat/assistant_render_test.go+78 internal/ui/chat/assistant_section_cache_test.go+464 internal/ui/chat/assistant_test.go+142 internal/ui/chat/assistant_thinking_bench_test.go+69 internal/ui/chat/assistant_thinking_bound_test.go+105 internal/ui/chat/assistant_thinking_window_test.go+500 internal/ui/chat/bash.go+251 internal/ui/chat/diagnostics.go+68 internal/ui/chat/docker_mcp.go+283 internal/ui/chat/fetch.go+192 internal/ui/chat/file.go+371 internal/ui/chat/generic.go+73 internal/ui/chat/incremental_glamour_test.go+981 internal/ui/chat/lsp_restart.go+62 internal/ui/chat/mcp.go+78 internal/ui/chat/mcp_test.go+406 internal/ui/chat/messages.go+440 internal/ui/chat/prefix_cache_test.go+197 internal/ui/chat/references.go+63 internal/ui/chat/search.go+256 internal/ui/chat/shell.go+358 internal/ui/chat/shell_test.go+59 internal/ui/chat/streaming_markdown.go+721 internal/ui/chat/todos.go+192 internal/ui/chat/tool_result_content.go+60 internal/ui/chat/tool_result_content_test.go+116 internal/ui/chat/tools.go+1751 internal/ui/chat/unified_diff.go+170 internal/ui/chat/user.go+181 internal/ui/chat/version_bump_test.go+567 internal/ui/common/ansi16.go+128 internal/ui/common/ansi16_test.go+106 internal/ui/common/button.go+69 internal/ui/common/capabilities.go+131 internal/ui/common/common.go+121 internal/ui/common/diff.go+35 internal/ui/common/elements.go+242 internal/ui/common/elements_test.go+35 internal/ui/common/highlight.go+106 internal/ui/common/interface.go+20 internal/ui/common/markdown.go+139 internal/ui/common/scrollbar.go+48 internal/ui/completions/completions.go+434 internal/ui/completions/completions_test.go+108 internal/ui/completions/item.go+225 internal/ui/completions/keys.go+74 internal/ui/completions/version_bump_test.go+85 internal/ui/dialog/actions.go+187 internal/ui/dialog/api_key_input.go+367 internal/ui/dialog/arguments.go+406 internal/ui/dialog/commands.go+453 internal/ui/dialog/commands_item.go+136 internal/ui/dialog/common.go+171 internal/ui/dialog/dialog.go+296 internal/ui/dialog/filepicker.go+321 internal/ui/dialog/models.go+519 internal/ui/dialog/models_item.go+157 internal/ui/dialog/models_list.go+275 internal/ui/dialog/notifications.go+310 internal/ui/dialog/oauth.go+378 internal/ui/dialog/oauth_copilot.go+78 internal/ui/dialog/oauth_hyper.go+96 internal/ui/dialog/overlay_test.go+189 internal/ui/dialog/permissions.go+859 internal/ui/dialog/permissions_test.go+99 internal/ui/dialog/quit.go+133 internal/ui/dialog/reasoning.go+318 internal/ui/dialog/sessions.go+473 internal/ui/dialog/sessions_item.go+294 internal/ui/dialog/version_bump_test.go+219 internal/ui/difftastic/difftastic.go+60 internal/ui/diffview/Taskfile.yaml internal/ui/diffview/diffview.go+56−36 internal/ui/diffview/diffview_test.go+1−25 internal/ui/diffview/split.go internal/ui/diffview/style.go+143 internal/ui/diffview/testdata/TestDefault.after internal/ui/diffview/testdata/TestDefault.before internal/ui/diffview/testdata/TestDiffView/Split/CustomContextLines/DarkMode.golden+16 internal/ui/diffview/testdata/TestDiffView/Split/CustomContextLines/LightMode.golden+16 internal/ui/diffview/testdata/TestDiffView/Split/Default/DarkMode.golden+7 internal/ui/diffview/testdata/TestDiffView/Split/Default/LightMode.golden+7 internal/ui/diffview/testdata/TestDiffView/Split/LargeWidth/DarkMode.golden+15 internal/ui/diffview/testdata/TestDiffView/Split/LargeWidth/LightMode.golden+15 internal/ui/diffview/testdata/TestDiffView/Split/MultipleHunks/DarkMode.golden+15 internal/ui/diffview/testdata/TestDiffView/Split/MultipleHunks/LightMode.golden+15 internal/ui/diffview/testdata/TestDiffView/Split/Narrow/DarkMode.golden+4 internal/ui/diffview/testdata/TestDiffView/Split/Narrow/LightMode.golden+4 internal/ui/diffview/testdata/TestDiffView/Split/NoLineNumbers/DarkMode.golden+7 internal/ui/diffview/testdata/TestDiffView/Split/NoLineNumbers/LightMode.golden+7 internal/ui/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/DarkMode.golden+15 internal/ui/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/LightMode.golden+15 internal/ui/diffview/testdata/TestDiffView/Split/SmallWidth/DarkMode.golden+15 internal/ui/diffview/testdata/TestDiffView/Split/SmallWidth/LightMode.golden+15 internal/ui/diffview/testdata/TestDiffView/Unified/CustomContextLines/DarkMode.golden+17 internal/ui/diffview/testdata/TestDiffView/Unified/CustomContextLines/LightMode.golden+17 internal/ui/diffview/testdata/TestDiffView/Unified/Default/DarkMode.golden+8 internal/ui/diffview/testdata/TestDiffView/Unified/Default/LightMode.golden+8 internal/ui/diffview/testdata/TestDiffView/Unified/LargeWidth/DarkMode.golden+16 internal/ui/diffview/testdata/TestDiffView/Unified/LargeWidth/LightMode.golden+16 internal/ui/diffview/testdata/TestDiffView/Unified/MultipleHunks/DarkMode.golden+16 internal/ui/diffview/testdata/TestDiffView/Unified/MultipleHunks/LightMode.golden+16 internal/ui/diffview/testdata/TestDiffView/Unified/Narrow/DarkMode.golden+7 internal/ui/diffview/testdata/TestDiffView/Unified/Narrow/LightMode.golden+7 internal/ui/diffview/testdata/TestDiffView/Unified/NoLineNumbers/DarkMode.golden+8 internal/ui/diffview/testdata/TestDiffView/Unified/NoLineNumbers/LightMode.golden+8 internal/ui/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/DarkMode.golden+16 internal/ui/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/LightMode.golden+16 internal/ui/diffview/testdata/TestDiffView/Unified/SmallWidth/DarkMode.golden+16 internal/ui/diffview/testdata/TestDiffView/Unified/SmallWidth/LightMode.golden+16 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf001.golden internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf002.golden+2 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf003.golden+3 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf004.golden+4 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf005.golden+5 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf006.golden+6 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf007.golden+7 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf008.golden+8 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf009.golden+9 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf010.golden+10 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf011.golden+11 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf012.golden+12 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf013.golden+13 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf014.golden+14 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf015.golden+15 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf016.golden+15 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf017.golden+15 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf018.golden+15 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf019.golden+15 internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf020.golden+15 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf001.golden internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf002.golden+2 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf003.golden+3 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf004.golden+4 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf005.golden+5 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf006.golden+6 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf007.golden+7 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf008.golden+8 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf009.golden+9 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf010.golden+10 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf011.golden+11 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf012.golden+12 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf013.golden+13 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf014.golden+14 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf015.golden+15 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf016.golden+16 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf017.golden+16 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf018.golden+16 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf019.golden+16 internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf020.golden+16 internal/ui/diffview/testdata/TestDiffViewLineBreakIssue/Split.golden+9 internal/ui/diffview/testdata/TestDiffViewLineBreakIssue/Unified.golden+12 internal/ui/diffview/testdata/TestDiffViewTabs/Split.golden+15 internal/ui/diffview/testdata/TestDiffViewTabs/Unified.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf001.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf002.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf003.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf004.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf005.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf006.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf007.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf008.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf009.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf010.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf011.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf012.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf013.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf014.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf015.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf016.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf017.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf018.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf019.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf020.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf021.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf022.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf023.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf024.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf025.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf026.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf027.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf028.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf029.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf030.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf031.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf032.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf033.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf034.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf035.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf036.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf037.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf038.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf039.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf040.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf041.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf042.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf043.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf044.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf045.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf046.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf047.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf048.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf049.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf050.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf051.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf052.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf053.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf054.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf055.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf056.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf057.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf058.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf059.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf060.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf061.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf062.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf063.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf064.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf065.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf066.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf067.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf068.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf069.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf070.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf071.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf072.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf073.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf074.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf075.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf076.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf077.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf078.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf079.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf080.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf081.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf082.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf083.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf084.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf085.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf086.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf087.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf088.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf089.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf090.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf091.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf092.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf093.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf094.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf095.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf096.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf097.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf098.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf099.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf100.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf101.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf102.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf103.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf104.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf105.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf106.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf107.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf108.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf109.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf110.golden+15 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf001.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf002.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf003.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf004.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf005.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf006.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf007.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf008.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf009.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf010.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf011.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf012.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf013.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf014.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf015.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf016.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf017.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf018.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf019.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf020.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf021.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf022.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf023.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf024.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf025.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf026.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf027.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf028.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf029.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf030.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf031.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf032.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf033.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf034.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf035.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf036.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf037.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf038.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf039.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf040.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf041.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf042.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf043.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf044.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf045.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf046.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf047.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf048.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf049.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf050.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf051.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf052.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf053.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf054.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf055.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf056.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf057.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf058.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf059.golden+16 internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf060.golden+16 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf00.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf01.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf02.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf03.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf04.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf05.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf06.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf07.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf08.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf09.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf10.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf11.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf12.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf13.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf14.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf15.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf16.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf17.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf18.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf19.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf20.golden+7 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf00.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf01.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf02.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf03.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf04.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf05.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf06.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf07.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf08.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf09.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf10.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf11.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf12.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf13.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf14.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf15.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf16.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf17.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf18.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf19.golden+8 internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf20.golden+8 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf00.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf01.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf02.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf03.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf04.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf05.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf06.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf07.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf08.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf09.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf10.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf11.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf12.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf13.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf14.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf15.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf16.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf00.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf01.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf02.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf03.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf04.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf05.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf06.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf07.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf08.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf09.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf10.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf11.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf12.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf13.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf14.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf15.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf16.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf00.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf01.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf02.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf03.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf04.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf05.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf06.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf07.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf08.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf09.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf10.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf11.golden+4 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf12.golden+3 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf13.golden+2 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf14.golden+1 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf15.golden internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf16.golden internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf00.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf01.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf02.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf03.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf04.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf05.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf06.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf07.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf08.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf09.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf10.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf11.golden+5 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf12.golden+4 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf13.golden+3 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf14.golden+2 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf15.golden+1 internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf16.golden internal/ui/diffview/testdata/TestLineBreakIssue.after internal/ui/diffview/testdata/TestLineBreakIssue.before internal/ui/diffview/testdata/TestMultipleHunks.after internal/ui/diffview/testdata/TestMultipleHunks.before internal/ui/diffview/testdata/TestNarrow.after internal/ui/diffview/testdata/TestNarrow.before internal/ui/diffview/testdata/TestTabs.after internal/ui/diffview/testdata/TestTabs.before internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLines/Content.golden internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLines/JSON.golden internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusOne/Content.golden internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusOne/JSON.golden internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusTwo/Content.golden internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusTwo/JSON.golden internal/ui/diffview/testdata/TestUdiff/Unified.golden internal/ui/diffview/udiff_test.go+1−1 internal/ui/diffview/util.go+46 internal/ui/diffview/util_test.go internal/ui/image/image.go+288 internal/ui/image/image_test.go+46 internal/ui/list/filterable.go+157 internal/ui/list/focus.go+13 internal/ui/list/highlight.go+212 internal/ui/list/item.go+126 internal/ui/list/list.go+928 internal/ui/list/list_test.go+770 internal/ui/logo/example/main.go+49 internal/ui/logo/letterforms.go+419 internal/ui/logo/logo.go+168 internal/ui/logo/rand.go+24 internal/ui/model/chat.go+1166 internal/ui/model/chat_draw_cache_test.go+334 internal/ui/model/chat_expand_test.go+55 internal/ui/model/filter.go+108 internal/ui/model/filter_test.go+162 internal/ui/model/header.go+264 internal/ui/model/history.go+200 internal/ui/model/keys.go+285 internal/ui/model/landing.go+126 internal/ui/model/layout_test.go+228 internal/ui/model/lsp.go+147 internal/ui/model/mcp.go+114 internal/ui/model/onboarding.go+116 internal/ui/model/permission_test.go+96 internal/ui/model/pills.go+363 internal/ui/model/session.go+272 internal/ui/model/session_test.go+142 internal/ui/model/sidebar.go+369 internal/ui/model/skills.go+155 internal/ui/model/skills_test.go+81 internal/ui/model/status.go+123 internal/ui/model/ui.go+4564 internal/ui/model/ui_test.go+95 internal/ui/notification/bell.go+27 internal/ui/notification/crush-icon-solo.png internal/ui/notification/crush-icon.png internal/ui/notification/icon_darwin.go+11 internal/ui/notification/icon_other.go+10 internal/ui/notification/native.go+52 internal/ui/notification/noop.go+12 internal/ui/notification/notification.go+35 internal/ui/notification/notification_test.go+213 internal/ui/notification/osc.go+135 internal/ui/styles/grad.go+119 internal/ui/styles/quickstyle.go+989 internal/ui/styles/styles.go+649 internal/ui/styles/themes.go+235 internal/ui/util/util.go+96 internal/ui/xchroma/chroma.go+70 internal/update/update.go+118 internal/update/update_test.go+48 internal/version/version.go+39−12 internal/workspace/app_workspace.go+464 internal/workspace/client_workspace.go+964 internal/workspace/client_workspace_test.go+213 internal/workspace/export_test.go+14 internal/workspace/multiclient_integration_test.go+176 internal/workspace/workspace.go+171 main.go+11 schema.json+332−29 scripts/check_log_capitalization.sh+5 vendor/charm.land/bubbles/v2/LICENSE+21 vendor/charm.land/bubbles/v2/cursor/cursor.go+241 vendor/charm.land/bubbles/v2/filepicker/filepicker.go+529 vendor/charm.land/bubbles/v2/filepicker/hidden_unix.go+11 vendor/charm.land/bubbles/v2/filepicker/hidden_windows.go+21 vendor/charm.land/bubbles/v2/help/help.go+253 vendor/charm.land/bubbles/v2/internal/memoization/memoization.go+125 vendor/charm.land/bubbles/v2/internal/runeutil/runeutil.go+102 vendor/charm.land/bubbles/v2/key/key.go+140 vendor/charm.land/bubbles/v2/spinner/spinner.go+211 vendor/charm.land/bubbles/v2/textarea/textarea.go+1897 vendor/charm.land/bubbles/v2/textinput/styles.go+96 vendor/charm.land/bubbles/v2/textinput/textinput.go+968 vendor/charm.land/bubbles/v2/viewport/highlight.go+141 vendor/charm.land/bubbles/v2/viewport/keymap.go+58 vendor/charm.land/bubbles/v2/viewport/viewport.go+765 vendor/charm.land/bubbletea/v2/.gitattributes+1 vendor/charm.land/bubbletea/v2/.gitignore+23 vendor/charm.land/bubbletea/v2/.golangci.yml+47 vendor/charm.land/bubbletea/v2/.goreleaser.yml+5 vendor/charm.land/bubbletea/v2/LICENSE+21 vendor/charm.land/bubbletea/v2/README.md+402 vendor/charm.land/bubbletea/v2/Taskfile.yaml+38 vendor/charm.land/bubbletea/v2/UPGRADE_GUIDE_V2.md+573 vendor/charm.land/bubbletea/v2/clipboard.go+70 vendor/charm.land/bubbletea/v2/color.go+91 vendor/charm.land/bubbletea/v2/commands.go+175 vendor/charm.land/bubbletea/v2/cursed_renderer.go+860 vendor/charm.land/bubbletea/v2/cursor.go+28 vendor/charm.land/bubbletea/v2/environ.go+34 vendor/charm.land/bubbletea/v2/exec.go+129 vendor/charm.land/bubbletea/v2/focus.go+9 vendor/charm.land/bubbletea/v2/input.go+54 vendor/charm.land/bubbletea/v2/key.go+371 vendor/charm.land/bubbletea/v2/keyboard.go+59 vendor/charm.land/bubbletea/v2/logging.go+53 vendor/charm.land/bubbletea/v2/mod.go+27 vendor/charm.land/bubbletea/v2/mouse.go+144 vendor/charm.land/bubbletea/v2/nil_renderer.go+53 vendor/charm.land/bubbletea/v2/options.go+168 vendor/charm.land/bubbletea/v2/paste.go+20 vendor/charm.land/bubbletea/v2/profile.go+15 vendor/charm.land/bubbletea/v2/raw.go+37 vendor/charm.land/bubbletea/v2/renderer.go+104 vendor/charm.land/bubbletea/v2/screen.go+68 vendor/charm.land/bubbletea/v2/signals_unix.go+33 vendor/charm.land/bubbletea/v2/signals_windows.go+10 vendor/charm.land/bubbletea/v2/tea.go+1439 vendor/charm.land/bubbletea/v2/termcap.go+48 vendor/charm.land/bubbletea/v2/termios_bsd.go+13 vendor/charm.land/bubbletea/v2/termios_other.go+8 vendor/charm.land/bubbletea/v2/termios_unix.go+14 vendor/charm.land/bubbletea/v2/termios_windows.go+11 vendor/charm.land/bubbletea/v2/tty.go+136 vendor/charm.land/bubbletea/v2/tty_unix.go+47 vendor/charm.land/bubbletea/v2/tty_windows.go+64 vendor/charm.land/bubbletea/v2/xterm.go+22 vendor/charm.land/catwalk/LICENSE+21 vendor/charm.land/catwalk/internal/providers/configs/aihubmix.json+3746 vendor/charm.land/catwalk/internal/providers/configs/alibaba-singapore.json+141 vendor/charm.land/catwalk/internal/providers/configs/alibaba-united-states.json+45 vendor/charm.land/catwalk/internal/providers/configs/anthropic.json+183 vendor/charm.land/catwalk/internal/providers/configs/avian.json+125 vendor/charm.land/catwalk/internal/providers/configs/azure.json+225 vendor/charm.land/catwalk/internal/providers/configs/baseten.json+187 vendor/charm.land/catwalk/internal/providers/configs/bedrock-europe.json+115 vendor/charm.land/catwalk/internal/providers/configs/bedrock-united-states.json+143 vendor/charm.land/catwalk/internal/providers/configs/cerebras.json+42 vendor/charm.land/catwalk/internal/providers/configs/chutes.json+227 vendor/charm.land/catwalk/internal/providers/configs/copilot.json+310 vendor/charm.land/catwalk/internal/providers/configs/cortecs.json+1697 vendor/charm.land/catwalk/internal/providers/configs/deepseek.json+45 vendor/charm.land/catwalk/internal/providers/configs/fireworks.json+171 vendor/charm.land/catwalk/internal/providers/configs/gemini.json+91 vendor/charm.land/catwalk/internal/providers/configs/groq.json+36 vendor/charm.land/catwalk/internal/providers/configs/huggingface.json+267 vendor/charm.land/catwalk/internal/providers/configs/ionet.json+335 vendor/charm.land/catwalk/internal/providers/configs/kimi.json+23 vendor/charm.land/catwalk/internal/providers/configs/minimax-china.json+91 vendor/charm.land/catwalk/internal/providers/configs/minimax.json+91 vendor/charm.land/catwalk/internal/providers/configs/moonshot.json+131 vendor/charm.land/catwalk/internal/providers/configs/nebius.json+419 vendor/charm.land/catwalk/internal/providers/configs/neuralwatt.json+155 vendor/charm.land/catwalk/internal/providers/configs/openai.json+352 vendor/charm.land/catwalk/internal/providers/configs/opencode-go.json+351 vendor/charm.land/catwalk/internal/providers/configs/opencode-zen.json+908 vendor/charm.land/catwalk/internal/providers/configs/openrouter.json+3831 vendor/charm.land/catwalk/internal/providers/configs/qiniucloud.json+179 vendor/charm.land/catwalk/internal/providers/configs/scaleway.json+141 vendor/charm.land/catwalk/internal/providers/configs/synthetic.json+197 vendor/charm.land/catwalk/internal/providers/configs/venice.json+1173 vendor/charm.land/catwalk/internal/providers/configs/vercel.json+3072 vendor/charm.land/catwalk/internal/providers/configs/vertexai.json+170 vendor/charm.land/catwalk/internal/providers/configs/xai.json+59 vendor/charm.land/catwalk/internal/providers/configs/zai.json+136 vendor/charm.land/catwalk/internal/providers/configs/zhipu-coding.json+136 vendor/charm.land/catwalk/internal/providers/configs/zhipu.json+120 vendor/charm.land/catwalk/internal/providers/providers.go+349 vendor/charm.land/catwalk/pkg/catwalk/client.go+79 vendor/charm.land/catwalk/pkg/catwalk/pkg.go+2 vendor/charm.land/catwalk/pkg/catwalk/provider.go+157 vendor/charm.land/catwalk/pkg/embedded/embedded.go+13 vendor/charm.land/fang/v2/.gitignore+3 vendor/charm.land/fang/v2/.golangci.yml+47 vendor/charm.land/fang/v2/.goreleaser.yml+5 vendor/charm.land/fang/v2/LICENSE.md+21 vendor/charm.land/fang/v2/README.md+92 vendor/charm.land/fang/v2/Taskfile.yml+7 vendor/charm.land/fang/v2/UPGRADE_GUIDE_V2.md+127 vendor/charm.land/fang/v2/fang.go+208 vendor/charm.land/fang/v2/fang_other.go+10 vendor/charm.land/fang/v2/fang_windows.go+30 vendor/charm.land/fang/v2/help.go+482 vendor/charm.land/fang/v2/theme.go+222 vendor/charm.land/fantasy/.editorconfig+18 vendor/charm.land/fantasy/.gitattributes+1 vendor/charm.land/fantasy/.gitignore+42 vendor/charm.land/fantasy/.golangci.yml+44 vendor/charm.land/fantasy/.goreleaser.yml+6 vendor/charm.land/fantasy/AGENTS.md+29 vendor/charm.land/fantasy/LICENSE+177 vendor/charm.land/fantasy/NOTICE+13 vendor/charm.land/fantasy/README.md+95 vendor/charm.land/fantasy/Taskfile.yaml+45 vendor/charm.land/fantasy/agent.go+1702 vendor/charm.land/fantasy/content.go+625 vendor/charm.land/fantasy/content_json.go+1046 vendor/charm.land/fantasy/crush.json+6 vendor/charm.land/fantasy/cspell.json+1 vendor/charm.land/fantasy/doc.go+2 vendor/charm.land/fantasy/errors.go+155 vendor/charm.land/fantasy/jsonrepair/jsonrepair.go+1648 vendor/charm.land/fantasy/model.go+261 vendor/charm.land/fantasy/model_json.go+156 vendor/charm.land/fantasy/object.go+236 vendor/charm.land/fantasy/object/object.go+620 vendor/charm.land/fantasy/provider.go+11 vendor/charm.land/fantasy/provider_registry.go+106 vendor/charm.land/fantasy/providers/anthropic/anthropic.go+1707 vendor/charm.land/fantasy/providers/anthropic/bedrock.go+15 vendor/charm.land/fantasy/providers/anthropic/call_useragent.go+14 vendor/charm.land/fantasy/providers/anthropic/computer_use.go+427 vendor/charm.land/fantasy/providers/anthropic/error.go+67 vendor/charm.land/fantasy/providers/anthropic/google.go+11 vendor/charm.land/fantasy/providers/anthropic/provider_options.go+283 vendor/charm.land/fantasy/providers/anthropic/sanitize.go+33 vendor/charm.land/fantasy/providers/azure/README.md+6 vendor/charm.land/fantasy/providers/azure/azure.go+125 vendor/charm.land/fantasy/providers/bedrock/README.md+10 vendor/charm.land/fantasy/providers/bedrock/bedrock.go+87 vendor/charm.land/fantasy/providers/google/README.md+63 vendor/charm.land/fantasy/providers/google/auth.go+15 vendor/charm.land/fantasy/providers/google/call_useragent.go+53 vendor/charm.land/fantasy/providers/google/error.go+51 vendor/charm.land/fantasy/providers/google/google.go+1488 vendor/charm.land/fantasy/providers/google/provider_options.go+146 vendor/charm.land/fantasy/providers/google/slice.go+11 vendor/charm.land/fantasy/providers/internal/httpheaders/httpheaders.go+60 vendor/charm.land/fantasy/providers/openai/call_useragent.go+31 vendor/charm.land/fantasy/providers/openai/error.go+92 vendor/charm.land/fantasy/providers/openai/language_model.go+990 vendor/charm.land/fantasy/providers/openai/language_model_hooks.go+668 vendor/charm.land/fantasy/providers/openai/openai.go+220 vendor/charm.land/fantasy/providers/openai/provider_options.go+217 vendor/charm.land/fantasy/providers/openai/responses_language_model.go+1678 vendor/charm.land/fantasy/providers/openai/responses_options.go+395 vendor/charm.land/fantasy/providers/openaicompat/language_model_hooks.go+516 vendor/charm.land/fantasy/providers/openaicompat/openaicompat.go+140 vendor/charm.land/fantasy/providers/openaicompat/provider_options.go+161 vendor/charm.land/fantasy/providers/openrouter/language_model_hooks.go+1063 vendor/charm.land/fantasy/providers/openrouter/openrouter.go+121 vendor/charm.land/fantasy/providers/openrouter/provider_options.go+218 vendor/charm.land/fantasy/providers/vercel/language_model_hooks.go+1074 vendor/charm.land/fantasy/providers/vercel/provider_options.go+195 vendor/charm.land/fantasy/providers/vercel/vercel.go+122 vendor/charm.land/fantasy/retry.go+155 vendor/charm.land/fantasy/schema/schema.go+442 vendor/charm.land/fantasy/tool.go+176 vendor/charm.land/fantasy/util.go+22 vendor/charm.land/fantasy/version.go+12 vendor/charm.land/fantasy/version.txt+1 vendor/charm.land/glamour/v2/.editorconfig+18 vendor/charm.land/glamour/v2/.gitattributes+2 vendor/charm.land/glamour/v2/.gitignore+2 vendor/charm.land/glamour/v2/.golangci.yml+44 vendor/charm.land/glamour/v2/.goreleaser.yml+6 vendor/charm.land/glamour/v2/CONTRIBUTING.md+23 vendor/charm.land/glamour/v2/LICENSE+21 vendor/charm.land/glamour/v2/README.md+129 vendor/charm.land/glamour/v2/Taskfile.yml+25 vendor/charm.land/glamour/v2/UPGRADE_GUIDE_V2.md+279 vendor/charm.land/glamour/v2/ansi/ansi.go+3 vendor/charm.land/glamour/v2/ansi/baseelement.go+157 vendor/charm.land/glamour/v2/ansi/blockelement.go+66 vendor/charm.land/glamour/v2/ansi/blockstack.go+95 vendor/charm.land/glamour/v2/ansi/codeblock.go+151 vendor/charm.land/glamour/v2/ansi/codespan.go+15 vendor/charm.land/glamour/v2/ansi/context.go+38 vendor/charm.land/glamour/v2/ansi/elements.go+481 vendor/charm.land/glamour/v2/ansi/emphasis.go+47 vendor/charm.land/glamour/v2/ansi/heading.go+80 vendor/charm.land/glamour/v2/ansi/image.go+57 vendor/charm.land/glamour/v2/ansi/link.go+112 vendor/charm.land/glamour/v2/ansi/listitem.go+29 vendor/charm.land/glamour/v2/ansi/margin.go+231 vendor/charm.land/glamour/v2/ansi/paragraph.go+63 vendor/charm.land/glamour/v2/ansi/renderer.go+166 vendor/charm.land/glamour/v2/ansi/style.go+252 vendor/charm.land/glamour/v2/ansi/table.go+206 vendor/charm.land/glamour/v2/ansi/table_links.go+234 vendor/charm.land/glamour/v2/ansi/task.go+27 vendor/charm.land/glamour/v2/ansi/templatehelper.go+86 vendor/charm.land/glamour/v2/examples.sh+19 vendor/charm.land/glamour/v2/gallery.sh+23 vendor/charm.land/glamour/v2/glamour.go+294 vendor/charm.land/glamour/v2/internal/autolink/autolink.go+55 vendor/charm.land/glamour/v2/styles/README.md+565 vendor/charm.land/glamour/v2/styles/ascii.json+87 vendor/charm.land/glamour/v2/styles/dark.json+191 vendor/charm.land/glamour/v2/styles/dracula.go+216 vendor/charm.land/glamour/v2/styles/dracula.json+188 vendor/charm.land/glamour/v2/styles/light.json+190 vendor/charm.land/glamour/v2/styles/notty.json+87 vendor/charm.land/glamour/v2/styles/pink.json+90 vendor/charm.land/glamour/v2/styles/styles.go+691 vendor/charm.land/glamour/v2/styles/tokyo-night.go+209 vendor/charm.land/glamour/v2/styles/tokyo-night.json+182 vendor/charm.land/glamour/v2/styles/tokyo_night.json+182 vendor/charm.land/lipgloss/v2/.editorconfig+18 vendor/charm.land/lipgloss/v2/.gitattributes+1 vendor/charm.land/lipgloss/v2/.gitignore+3 vendor/charm.land/lipgloss/v2/.golangci.yml+50 vendor/charm.land/lipgloss/v2/.goreleaser.yml+5 vendor/charm.land/lipgloss/v2/LICENSE+21 vendor/charm.land/lipgloss/v2/README.md+996 vendor/charm.land/lipgloss/v2/Taskfile.yaml+24 vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md+504 vendor/charm.land/lipgloss/v2/align.go+82 vendor/charm.land/lipgloss/v2/ansi_unix.go+8 vendor/charm.land/lipgloss/v2/ansi_windows.go+30 vendor/charm.land/lipgloss/v2/blending.go+196 vendor/charm.land/lipgloss/v2/borders.go+587 vendor/charm.land/lipgloss/v2/canvas.go+88 vendor/charm.land/lipgloss/v2/color.go+359 vendor/charm.land/lipgloss/v2/get.go+657 vendor/charm.land/lipgloss/v2/join.go+175 vendor/charm.land/lipgloss/v2/layer.go+327 vendor/charm.land/lipgloss/v2/lipgloss.go+3 vendor/charm.land/lipgloss/v2/position.go+134 vendor/charm.land/lipgloss/v2/query.go+92 vendor/charm.land/lipgloss/v2/ranges.go+48 vendor/charm.land/lipgloss/v2/runes.go+43 vendor/charm.land/lipgloss/v2/set.go+932 vendor/charm.land/lipgloss/v2/size.go+40 vendor/charm.land/lipgloss/v2/style.go+637 vendor/charm.land/lipgloss/v2/table/resizing.go+489 vendor/charm.land/lipgloss/v2/table/rows.go+130 vendor/charm.land/lipgloss/v2/table/table.go+568 vendor/charm.land/lipgloss/v2/table/util.go+44 vendor/charm.land/lipgloss/v2/terminal.go+124 vendor/charm.land/lipgloss/v2/tree/children.go+100 vendor/charm.land/lipgloss/v2/tree/enumerator.go+74 vendor/charm.land/lipgloss/v2/tree/renderer.go+165 vendor/charm.land/lipgloss/v2/tree/tree.go+407 vendor/charm.land/lipgloss/v2/unset.go+359 vendor/charm.land/lipgloss/v2/whitespace.go+76 vendor/charm.land/lipgloss/v2/wrap.go+113 vendor/charm.land/lipgloss/v2/writer.go+160 vendor/charm.land/log/v2/.gitignore+17 vendor/charm.land/log/v2/.golangci.yml+50 vendor/charm.land/log/v2/.goreleaser.yml+6 vendor/charm.land/log/v2/LICENSE+21 vendor/charm.land/log/v2/README.md+367 vendor/charm.land/log/v2/UPGRADE_GUIDE_V2.md+320 vendor/charm.land/log/v2/context.go+23 vendor/charm.land/log/v2/doc.go+3 vendor/charm.land/log/v2/formatter.go+27 vendor/charm.land/log/v2/json.go+157 vendor/charm.land/log/v2/level.go+65 vendor/charm.land/log/v2/logfmt.go+32 vendor/charm.land/log/v2/logger.go+413 vendor/charm.land/log/v2/logger_121.go+72 vendor/charm.land/log/v2/logger_no121.go+69 vendor/charm.land/log/v2/options.go+61 vendor/charm.land/log/v2/pkg.go+248 vendor/charm.land/log/v2/stdlog.go+67 vendor/charm.land/log/v2/styles.go+83 vendor/charm.land/log/v2/text.go+272 vendor/charm.land/x/vcr/LICENSE+21 vendor/charm.land/x/vcr/doc.go+3 vendor/charm.land/x/vcr/hooks.go+33 vendor/charm.land/x/vcr/marshaler.go+19 vendor/charm.land/x/vcr/matcher.go+70 vendor/charm.land/x/vcr/recorder.go+70 vendor/cloud.google.com/go/LICENSE+202 vendor/cloud.google.com/go/auth/CHANGES.md+483 vendor/cloud.google.com/go/auth/LICENSE+202 vendor/cloud.google.com/go/auth/README.md+40 vendor/cloud.google.com/go/auth/auth.go+618 vendor/cloud.google.com/go/auth/credentials/compute.go+102 vendor/cloud.google.com/go/auth/credentials/detect.go+471 vendor/cloud.google.com/go/auth/credentials/doc.go+45 vendor/cloud.google.com/go/auth/credentials/filetypes.go+329 vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/aws_provider.go+531 vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/executable_provider.go+284 vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/externalaccount.go+431 vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/file_provider.go+78 vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/info.go+74 vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/programmatic_provider.go+30 vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/url_provider.go+93 vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/x509_provider.go+220 vendor/cloud.google.com/go/auth/credentials/internal/externalaccountuser/externalaccountuser.go+115 vendor/cloud.google.com/go/auth/credentials/internal/gdch/gdch.go+198 vendor/cloud.google.com/go/auth/credentials/internal/impersonate/idtoken.go+105 vendor/cloud.google.com/go/auth/credentials/internal/impersonate/impersonate.go+168 vendor/cloud.google.com/go/auth/credentials/internal/stsexchange/sts_exchange.go+167 vendor/cloud.google.com/go/auth/credentials/selfsignedjwt.go+89 vendor/cloud.google.com/go/auth/grpctransport/dial_socketopt.go+62 vendor/cloud.google.com/go/auth/grpctransport/directpath.go+177 vendor/cloud.google.com/go/auth/grpctransport/grpctransport.go+675 vendor/cloud.google.com/go/auth/grpctransport/pool.go+119 vendor/cloud.google.com/go/auth/httptransport/httptransport.go+254 vendor/cloud.google.com/go/auth/httptransport/transport.go+548 vendor/cloud.google.com/go/auth/internal/compute/compute.go+65 vendor/cloud.google.com/go/auth/internal/compute/manufacturer.go+22 vendor/cloud.google.com/go/auth/internal/compute/manufacturer_linux.go+23 vendor/cloud.google.com/go/auth/internal/compute/manufacturer_windows.go+46 vendor/cloud.google.com/go/auth/internal/credsfile/credsfile.go+63 vendor/cloud.google.com/go/auth/internal/credsfile/filetype.go+159 vendor/cloud.google.com/go/auth/internal/credsfile/parse.go+99 vendor/cloud.google.com/go/auth/internal/internal.go+285 vendor/cloud.google.com/go/auth/internal/jwt/jwt.go+208 vendor/cloud.google.com/go/auth/internal/retry/retry.go+117 vendor/cloud.google.com/go/auth/internal/transport/cba.go+361 vendor/cloud.google.com/go/auth/internal/transport/cert/default_cert.go+65 vendor/cloud.google.com/go/auth/internal/transport/cert/enterprise_cert.go+54 vendor/cloud.google.com/go/auth/internal/transport/cert/secureconnect_cert.go+124 vendor/cloud.google.com/go/auth/internal/transport/cert/workload_cert.go+138 vendor/cloud.google.com/go/auth/internal/transport/headers/headers.go+61 vendor/cloud.google.com/go/auth/internal/transport/s2a.go+138 vendor/cloud.google.com/go/auth/internal/transport/transport.go+137 vendor/cloud.google.com/go/auth/internal/trustboundary/external_accounts_config_providers.go+100 vendor/cloud.google.com/go/auth/internal/trustboundary/trust_boundary.go+392 vendor/cloud.google.com/go/auth/internal/version.go+20 vendor/cloud.google.com/go/auth/oauth2adapt/CHANGES.md+82 vendor/cloud.google.com/go/auth/oauth2adapt/LICENSE+202 vendor/cloud.google.com/go/auth/oauth2adapt/oauth2adapt.go+200 vendor/cloud.google.com/go/auth/threelegged.go+382 vendor/cloud.google.com/go/civil/civil.go+500 vendor/cloud.google.com/go/compute/metadata/CHANGES.md+115 vendor/cloud.google.com/go/compute/metadata/LICENSE+202 vendor/cloud.google.com/go/compute/metadata/README.md+27 vendor/cloud.google.com/go/compute/metadata/log.go+149 vendor/cloud.google.com/go/compute/metadata/metadata.go+937 vendor/cloud.google.com/go/compute/metadata/retry.go+117 vendor/cloud.google.com/go/compute/metadata/retry_linux.go+31 vendor/cloud.google.com/go/compute/metadata/syscheck.go+28 vendor/cloud.google.com/go/compute/metadata/syscheck_linux.go+30 vendor/cloud.google.com/go/compute/metadata/syscheck_windows.go+39 vendor/git.sr.ht/~jackmordaunt/go-toast/.gitignore+1 vendor/git.sr.ht/~jackmordaunt/go-toast/ARCHITECTURE.md+244 vendor/git.sr.ht/~jackmordaunt/go-toast/LICENSE+61 vendor/git.sr.ht/~jackmordaunt/go-toast/README.md+86 vendor/git.sr.ht/~jackmordaunt/go-toast/constants.go+65 vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/data/xml/dom/xmldocument.go+73 vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/ui/notifications/toastnotification.go+88 vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/ui/notifications/toastnotificationmanager.go+53 vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/ui/notifications/toastnotificationmanagerforuser.go+68 vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/ui/notifications/toastnotifier.go+64 vendor/git.sr.ht/~jackmordaunt/go-toast/tmpl/powershell.go.tmpl+14 vendor/git.sr.ht/~jackmordaunt/go-toast/tmpl/tmpl.go+28 vendor/git.sr.ht/~jackmordaunt/go-toast/tmpl/xml.go.tmpl+34 vendor/git.sr.ht/~jackmordaunt/go-toast/toast.go+225 vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/bind.go+86 vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/bind_noop.go+19 vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/bind_windows.go+174 vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/impl.go+179 vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/procs.go+37 vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/registry.go+110 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md+849 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/LICENSE.txt+21 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/README.md+39 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml+29 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud/cloud.go+44 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud/doc.go+53 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go+173 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/doc.go+264 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/errors.go+17 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/etag.go+57 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go+175 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/pipeline.go+77 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go+260 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go+201 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log/log.go+50 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go+159 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go+135 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/fake/fake.go+133 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go+123 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go+148 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/poller.go+24 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go+212 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go+44 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go+149 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/doc.go+10 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/log.go+55 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/doc.go+10 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go+198 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/doc.go+10 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/errors.go+27 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go+138 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pipeline.go+94 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go+75 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go+236 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go+72 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_header.go+40 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go+154 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_include_response.go+35 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_key_credential.go+64 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_logging.go+264 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_request_id.go+34 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go+276 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_sas_credential.go+55 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_telemetry.go+83 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go+396 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go+281 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/response.go+109 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_other.go+15 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_wasm.go+15 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_http_client.go+48 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming/doc.go+9 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming/progress.go+89 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing/constants.go+41 vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing/tracing.go+191 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/LICENSE.txt+21 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/diag/diag.go+51 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/diag/doc.go+7 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo/doc.go+7 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo/errorinfo.go+46 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/exported/exported.go+129 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/log/doc.go+7 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/log/log.go+104 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/poller/util.go+155 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/temporal/resource.go+123 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/uuid/doc.go+7 vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/uuid/uuid.go+76 vendor/github.com/JohannesKaufmann/html-to-markdown/.gitignore+14 vendor/github.com/JohannesKaufmann/html-to-markdown/CONTRIBUTING.md vendor/github.com/JohannesKaufmann/html-to-markdown/LICENSE+21 vendor/github.com/JohannesKaufmann/html-to-markdown/README.md+242 vendor/github.com/JohannesKaufmann/html-to-markdown/SECURITY.md+6 vendor/github.com/JohannesKaufmann/html-to-markdown/commonmark.go+393 vendor/github.com/JohannesKaufmann/html-to-markdown/escape/escape.go+65 vendor/github.com/JohannesKaufmann/html-to-markdown/from.go+464 vendor/github.com/JohannesKaufmann/html-to-markdown/logo_five_years.png vendor/github.com/JohannesKaufmann/html-to-markdown/markdown.go+212 vendor/github.com/JohannesKaufmann/html-to-markdown/utils.go+533 vendor/github.com/KyleBanks/depth/.gitignore+16 vendor/github.com/KyleBanks/depth/.travis.yml+9 vendor/github.com/KyleBanks/depth/LICENSE+21 vendor/github.com/KyleBanks/depth/Makefile+32 vendor/github.com/KyleBanks/depth/README.md+232 vendor/github.com/KyleBanks/depth/depth.go+129 vendor/github.com/KyleBanks/depth/pkg.go+184 vendor/github.com/MakeNowJust/heredoc/LICENSE+21 vendor/github.com/MakeNowJust/heredoc/README.md+52 vendor/github.com/MakeNowJust/heredoc/heredoc.go+105 vendor/github.com/Microsoft/go-winio/.gitattributes+1 vendor/github.com/Microsoft/go-winio/.gitignore+10 vendor/github.com/Microsoft/go-winio/.golangci.yml+147 vendor/github.com/Microsoft/go-winio/CODEOWNERS+1 vendor/github.com/Microsoft/go-winio/LICENSE+22 vendor/github.com/Microsoft/go-winio/README.md+89 vendor/github.com/Microsoft/go-winio/SECURITY.md+41 vendor/github.com/Microsoft/go-winio/backup.go+287 vendor/github.com/Microsoft/go-winio/doc.go+22 vendor/github.com/Microsoft/go-winio/ea.go+137 vendor/github.com/Microsoft/go-winio/file.go+320 vendor/github.com/Microsoft/go-winio/fileinfo.go+106 vendor/github.com/Microsoft/go-winio/hvsock.go+582 vendor/github.com/Microsoft/go-winio/internal/fs/doc.go+2 vendor/github.com/Microsoft/go-winio/internal/fs/fs.go+262 vendor/github.com/Microsoft/go-winio/internal/fs/security.go+12 vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go+61 vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go+20 vendor/github.com/Microsoft/go-winio/internal/socket/socket.go+177 vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go+69 vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go+132 vendor/github.com/Microsoft/go-winio/pipe.go+586 vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go+232 vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go+16 vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go+13 vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go+27 vendor/github.com/Microsoft/go-winio/privilege.go+196 vendor/github.com/Microsoft/go-winio/reparse.go+131 vendor/github.com/Microsoft/go-winio/sd.go+133 vendor/github.com/Microsoft/go-winio/syscall.go+5 vendor/github.com/Microsoft/go-winio/zsyscall_windows.go+378 vendor/github.com/PuerkitoBio/goquery/.gitattributes+1 vendor/github.com/PuerkitoBio/goquery/.gitignore+16 vendor/github.com/PuerkitoBio/goquery/LICENSE+12 vendor/github.com/PuerkitoBio/goquery/README.md+218 vendor/github.com/PuerkitoBio/goquery/array.go+124 vendor/github.com/PuerkitoBio/goquery/doc.go+123 vendor/github.com/PuerkitoBio/goquery/expand.go+70 vendor/github.com/PuerkitoBio/goquery/filter.go+163 vendor/github.com/PuerkitoBio/goquery/iteration.go+61 vendor/github.com/PuerkitoBio/goquery/manipulation.go+679 vendor/github.com/PuerkitoBio/goquery/property.go+275 vendor/github.com/PuerkitoBio/goquery/query.go+49 vendor/github.com/PuerkitoBio/goquery/traversal.go+704 vendor/github.com/PuerkitoBio/goquery/type.go+203 vendor/github.com/PuerkitoBio/goquery/utilities.go+177 vendor/github.com/alecthomas/chroma/v2/.editorconfig+17 vendor/github.com/alecthomas/chroma/v2/.gitignore+28 vendor/github.com/alecthomas/chroma/v2/.golangci.yml+122 vendor/github.com/alecthomas/chroma/v2/.goreleaser.yml+34 vendor/github.com/alecthomas/chroma/v2/AGENTS.md+11 vendor/github.com/alecthomas/chroma/v2/BUILD.bit+93 vendor/github.com/alecthomas/chroma/v2/COPYING+118 vendor/github.com/alecthomas/chroma/v2/Dockerfile+64 vendor/github.com/alecthomas/chroma/v2/Justfile+59 vendor/github.com/alecthomas/chroma/v2/README.md+309 vendor/github.com/alecthomas/chroma/v2/biome.json+6 vendor/github.com/alecthomas/chroma/v2/chroma.jpg vendor/github.com/alecthomas/chroma/v2/coalesce.go+35 vendor/github.com/alecthomas/chroma/v2/colour.go+192 vendor/github.com/alecthomas/chroma/v2/delegate.go+161 vendor/github.com/alecthomas/chroma/v2/doc.go+7 vendor/github.com/alecthomas/chroma/v2/emitters.go+233 vendor/github.com/alecthomas/chroma/v2/formatter.go+43 vendor/github.com/alecthomas/chroma/v2/formatters/api.go+57 vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go+692 vendor/github.com/alecthomas/chroma/v2/formatters/json.go+39 vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go+51 vendor/github.com/alecthomas/chroma/v2/formatters/svg/svg.go+222 vendor/github.com/alecthomas/chroma/v2/formatters/tokens.go+18 vendor/github.com/alecthomas/chroma/v2/formatters/tty_indexed.go+284 vendor/github.com/alecthomas/chroma/v2/formatters/tty_truecolour.go+76 vendor/github.com/alecthomas/chroma/v2/iterator.go+93 vendor/github.com/alecthomas/chroma/v2/lexer.go+179 vendor/github.com/alecthomas/chroma/v2/lexers/README.md+46 vendor/github.com/alecthomas/chroma/v2/lexers/caddyfile.go+275 vendor/github.com/alecthomas/chroma/v2/lexers/cl.go+243 vendor/github.com/alecthomas/chroma/v2/lexers/dns.go+17 vendor/github.com/alecthomas/chroma/v2/lexers/emacs.go+533 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abap.xml+154 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abnf.xml+66 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript.xml+68 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript_3.xml+163 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ada.xml+321 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/agda.xml+66 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/al.xml+75 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/alloy.xml+58 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml+98 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml+109 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/antlr.xml+317 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apacheconf.xml+74 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apl.xml+59 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml+151 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arangodb_aql.xml+174 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml+322 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml+126 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arturo.xml+119 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/atl.xml+165 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autohotkey.xml+78 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autoit.xml+70 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/awk.xml+95 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ballerina.xml+97 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash.xml+222 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash_session.xml+25 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/batchfile.xml+660 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/beef.xml+120 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bibtex.xml+152 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bicep.xml+84 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/blitzbasic.xml+141 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bnf.xml+28 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bqn.xml+83 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/brainfuck.xml+51 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c#.xml+121 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c++.xml+331 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c.xml+260 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c3.xml+374 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cap_n_proto.xml+122 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cassandra_cql.xml+137 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ceylon.xml+151 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml+197 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfstatement.xml+92 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chaiscript.xml+134 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chapel.xml+143 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cheetah.xml+55 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/clojure.xml+71 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cmake.xml+90 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cobol.xml+90 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coffeescript.xml+210 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/common_lisp.xml+184 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coq.xml+136 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/core.xml+79 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/crystal.xml+762 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml+323 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/csv.xml+53 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cue.xml+85 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cython.xml+372 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/d.xml+133 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml+213 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dax.xml+39 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/desktop_entry.xml+17 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/devicetree.xml+251 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/diff.xml+52 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/django_jinja.xml+153 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml+44 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml+68 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dtd.xml+168 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dylan.xml+176 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ebnf.xml+90 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elixir.xml+744 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elm.xml+119 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/emacslisp.xml+132 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml+37 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erlang.xml+166 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/factor.xml+412 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fennel.xml+68 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fish.xml+159 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/forth.xml+78 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml+102 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortranfixed.xml+71 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fsharp.xml+245 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml+150 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript.xml+259 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript3.xml+270 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gemfile_lock.xml+81 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml+24 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gherkin.xml+263 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gleam.xml+100 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/glsl.xml+65 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gnuplot.xml+289 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/go_template.xml+114 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml+92 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groff.xml+90 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groovy.xml+135 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/handlebars.xml+147 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hare.xml+98 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/haskell.xml+275 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hcl.xml+143 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hexdump.xml+189 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml+131 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlsl.xml+110 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/holyc.xml+252 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/html.xml+159 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hy.xml+104 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/idris.xml+216 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/igor.xml+47 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ini.xml+52 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/io.xml+71 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/iscdhcpd.xml+96 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/j.xml+157 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/janet.xml+48 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml+206 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml+160 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml+117 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jsonata.xml+83 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jsonnet.xml+138 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/julia.xml+400 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jungle.xml+98 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kakoune.xml+96 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kdl.xml+75 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml+234 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml+184 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lean.xml+56 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lighttpd_configuration_file.xml+42 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lilypond.xml+133 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/llvm.xml+73 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lox.xml+78 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml+158 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml+173 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/makefile.xml+131 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mako.xml+120 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mason.xml+89 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml+155 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mathematica.xml+60 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/matlab.xml+114 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml+138 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml+86 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/metal.xml+270 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/microcad.xml+139 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/minizinc.xml+82 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mlir.xml+73 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/modelica.xml+106 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/modula-2.xml+245 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mojo.xml+228 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/monkeyc.xml+153 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/moonbit.xml+75 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/moonscript.xml+83 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/morrowindscript.xml+90 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/myghty.xml+77 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml+121 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nasm.xml+126 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/natural.xml+143 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ndisasm.xml+123 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/newspeak.xml+121 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nginx_configuration_file.xml+101 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nim.xml+211 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nix.xml+258 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nsis.xml+59 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nu.xml+126 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objective-c.xml+510 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml+142 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ocaml.xml+153 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/octave.xml+101 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/odin.xml+127 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/onesenterprise.xml+92 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openedge_abl.xml+101 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openscad.xml+96 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/org_mode.xml+329 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pacmanconf.xml+37 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/perl.xml+400 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml+258 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pig.xml+105 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pkgconfig.xml+73 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pl_pgsql.xml+119 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plaintext.xml+21 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plutus_core.xml+105 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pony.xml+135 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postgresql_sql_dialect.xml+155 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml+93 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/povray.xml+58 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powerquery.xml+51 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powershell.xml+230 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prolog.xml+115 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promela.xml+119 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promql.xml+123 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml+45 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml+124 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prql.xml+161 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/psl.xml+213 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/puppet.xml+100 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python.xml+595 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python_2.xml+356 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qbasic.xml+173 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qml.xml+113 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/r.xml+128 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/racket.xml+260 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ragel.xml+149 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/react.xml+236 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reasonml.xml+147 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reg.xml+68 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rego.xml+94 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rexx.xml+127 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rgbasm.xml+239 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ring.xml+74 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpgle.xml+176 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpm_spec.xml+58 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml+728 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rust.xml+375 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sas.xml+191 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sass.xml+362 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scala.xml+274 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml+115 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scheme.xml+106 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scilab.xml+98 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scss.xml+373 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml+92 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sieve.xml+61 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smali.xml+73 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smalltalk.xml+294 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smarty.xml+79 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/snbt.xml+58 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/snobol.xml+95 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/solidity.xml+291 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sourcepawn.xml+59 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml+292 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sparql.xml+160 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sql.xml+90 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/squidconf.xml+63 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/standard_ml.xml+548 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stas.xml+85 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stylus.xml+132 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/swift.xml+207 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemd.xml+63 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemverilog.xml+181 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tablegen.xml+69 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tal.xml+43 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tasm.xml+135 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcl.xml+272 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcsh.xml+121 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/templ.xml+315 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/termcap.xml+75 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terminfo.xml+84 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml+149 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tex.xml+113 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/thrift.xml+154 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml+45 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tradingview.xml+81 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml+137 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turing.xml+82 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turtle.xml+170 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/twig.xml+155 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/txtpb.xml+162 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml+302 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscript.xml+178 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscriptcssdata.xml+52 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscripthtmldata.xml+52 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typst.xml+108 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ucode.xml+147 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v.xml+355 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v_shell.xml+365 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vala.xml+72 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vb_net.xml+162 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/verilog.xml+158 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhdl.xml+171 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhs.xml+48 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/viml.xml+85 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vue.xml+295 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/wat.xml+149 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/wdte.xml+43 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/webgpu_shading_language.xml+142 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/webvtt.xml+283 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/whiley.xml+57 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml+96 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xorg.xml+35 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml+132 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yang.xml+99 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/z80_assembly.xml+74 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zed.xml+51 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml+187 vendor/github.com/alecthomas/chroma/v2/lexers/erb.go+29 vendor/github.com/alecthomas/chroma/v2/lexers/gemtext.go+37 vendor/github.com/alecthomas/chroma/v2/lexers/genshi.go+118 vendor/github.com/alecthomas/chroma/v2/lexers/go.go+81 vendor/github.com/alecthomas/chroma/v2/lexers/haxe.go+647 vendor/github.com/alecthomas/chroma/v2/lexers/html.go+8 vendor/github.com/alecthomas/chroma/v2/lexers/http.go+131 vendor/github.com/alecthomas/chroma/v2/lexers/lexers.go+85 vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go+107 vendor/github.com/alecthomas/chroma/v2/lexers/markless.go+168 vendor/github.com/alecthomas/chroma/v2/lexers/mysql.go+33 vendor/github.com/alecthomas/chroma/v2/lexers/php.go+37 vendor/github.com/alecthomas/chroma/v2/lexers/raku.go+1710 vendor/github.com/alecthomas/chroma/v2/lexers/rst.go+89 vendor/github.com/alecthomas/chroma/v2/lexers/svelte.go+70 vendor/github.com/alecthomas/chroma/v2/lexers/typoscript.go+85 vendor/github.com/alecthomas/chroma/v2/lexers/yaml_jinja.go+20 vendor/github.com/alecthomas/chroma/v2/lexers/zed.go+24 vendor/github.com/alecthomas/chroma/v2/mutators.go+201 vendor/github.com/alecthomas/chroma/v2/pygments-lexers.txt+605 vendor/github.com/alecthomas/chroma/v2/quick/quick.go+44 vendor/github.com/alecthomas/chroma/v2/regexp.go+533 vendor/github.com/alecthomas/chroma/v2/registry.go+228 vendor/github.com/alecthomas/chroma/v2/remap.go+94 vendor/github.com/alecthomas/chroma/v2/renovate.json5+25 vendor/github.com/alecthomas/chroma/v2/serialise.go+483 vendor/github.com/alecthomas/chroma/v2/style.go+530 vendor/github.com/alecthomas/chroma/v2/styles/abap.xml+11 vendor/github.com/alecthomas/chroma/v2/styles/algol.xml+18 vendor/github.com/alecthomas/chroma/v2/styles/algol_nu.xml+18 vendor/github.com/alecthomas/chroma/v2/styles/api.go+95 vendor/github.com/alecthomas/chroma/v2/styles/arduino.xml+18 vendor/github.com/alecthomas/chroma/v2/styles/ashen.xml+69 vendor/github.com/alecthomas/chroma/v2/styles/aura-theme-dark-soft.xml+107 vendor/github.com/alecthomas/chroma/v2/styles/aura-theme-dark.xml+107 vendor/github.com/alecthomas/chroma/v2/styles/autumn.xml+36 vendor/github.com/alecthomas/chroma/v2/styles/average.xml+74 vendor/github.com/alecthomas/chroma/v2/styles/base16-snazzy.xml+74 vendor/github.com/alecthomas/chroma/v2/styles/borland.xml+26 vendor/github.com/alecthomas/chroma/v2/styles/bw.xml+23 vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/colorful.xml+52 vendor/github.com/alecthomas/chroma/v2/styles/compat.go+69 vendor/github.com/alecthomas/chroma/v2/styles/darcula.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/doom-one.xml+51 vendor/github.com/alecthomas/chroma/v2/styles/doom-one2.xml+64 vendor/github.com/alecthomas/chroma/v2/styles/dracula.xml+74 vendor/github.com/alecthomas/chroma/v2/styles/emacs.xml+44 vendor/github.com/alecthomas/chroma/v2/styles/evergarden.xml+33 vendor/github.com/alecthomas/chroma/v2/styles/friendly.xml+44 vendor/github.com/alecthomas/chroma/v2/styles/fruity.xml+19 vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml+46 vendor/github.com/alecthomas/chroma/v2/styles/github.xml+39 vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.xml+34 vendor/github.com/alecthomas/chroma/v2/styles/gruvbox.xml+34 vendor/github.com/alecthomas/chroma/v2/styles/hr_high_contrast.xml+12 vendor/github.com/alecthomas/chroma/v2/styles/hrdark.xml+10 vendor/github.com/alecthomas/chroma/v2/styles/igor.xml+9 vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-dragon.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/lovelace.xml+53 vendor/github.com/alecthomas/chroma/v2/styles/manni.xml+44 vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml+13 vendor/github.com/alecthomas/chroma/v2/styles/modus-vivendi.xml+13 vendor/github.com/alecthomas/chroma/v2/styles/monokai.xml+29 vendor/github.com/alecthomas/chroma/v2/styles/monokailight.xml+26 vendor/github.com/alecthomas/chroma/v2/styles/murphy.xml+52 vendor/github.com/alecthomas/chroma/v2/styles/native.xml+35 vendor/github.com/alecthomas/chroma/v2/styles/nord.xml+46 vendor/github.com/alecthomas/chroma/v2/styles/nordic.xml+46 vendor/github.com/alecthomas/chroma/v2/styles/onedark.xml+25 vendor/github.com/alecthomas/chroma/v2/styles/onesenterprise.xml+10 vendor/github.com/alecthomas/chroma/v2/styles/paraiso-dark.xml+37 vendor/github.com/alecthomas/chroma/v2/styles/paraiso-light.xml+37 vendor/github.com/alecthomas/chroma/v2/styles/pastie.xml+45 vendor/github.com/alecthomas/chroma/v2/styles/perldoc.xml+37 vendor/github.com/alecthomas/chroma/v2/styles/pygments.xml+42 vendor/github.com/alecthomas/chroma/v2/styles/rainbow_dash.xml+40 vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-dawn.xml+29 vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-moon.xml+29 vendor/github.com/alecthomas/chroma/v2/styles/rose-pine.xml+29 vendor/github.com/alecthomas/chroma/v2/styles/rpgle.xml+30 vendor/github.com/alecthomas/chroma/v2/styles/rrt.xml+19 vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark.xml+39 vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark256.xml+41 vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml+17 vendor/github.com/alecthomas/chroma/v2/styles/swapoff.xml+18 vendor/github.com/alecthomas/chroma/v2/styles/tango.xml+72 vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-day.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-moon.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-night.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-storm.xml+83 vendor/github.com/alecthomas/chroma/v2/styles/trac.xml+35 vendor/github.com/alecthomas/chroma/v2/styles/vim.xml+29 vendor/github.com/alecthomas/chroma/v2/styles/vs.xml+16 vendor/github.com/alecthomas/chroma/v2/styles/vulcan.xml+74 vendor/github.com/alecthomas/chroma/v2/styles/witchhazel.xml+31 vendor/github.com/alecthomas/chroma/v2/styles/xcode-dark.xml+31 vendor/github.com/alecthomas/chroma/v2/styles/xcode.xml+22 vendor/github.com/alecthomas/chroma/v2/table.py+31 vendor/github.com/alecthomas/chroma/v2/test.jsonl+2 vendor/github.com/alecthomas/chroma/v2/tokentype_enumer.go+588 vendor/github.com/alecthomas/chroma/v2/types.go+357 vendor/github.com/andybalholm/brotli/.gitignore+2 vendor/github.com/andybalholm/brotli/LICENSE+19 vendor/github.com/andybalholm/brotli/README.md+19 vendor/github.com/andybalholm/brotli/backward_references.go+185 vendor/github.com/andybalholm/brotli/backward_references_hq.go+796 vendor/github.com/andybalholm/brotli/bit_cost.go+436 vendor/github.com/andybalholm/brotli/bit_reader.go+266 vendor/github.com/andybalholm/brotli/bitwriter.go+56 vendor/github.com/andybalholm/brotli/block_splitter.go+144 vendor/github.com/andybalholm/brotli/block_splitter_command.go+434 vendor/github.com/andybalholm/brotli/block_splitter_distance.go+433 vendor/github.com/andybalholm/brotli/block_splitter_literal.go+433 vendor/github.com/andybalholm/brotli/brotli_bit_stream.go+1435 vendor/github.com/andybalholm/brotli/cluster.go+30 vendor/github.com/andybalholm/brotli/cluster_command.go+164 vendor/github.com/andybalholm/brotli/cluster_distance.go+326 vendor/github.com/andybalholm/brotli/cluster_literal.go+326 vendor/github.com/andybalholm/brotli/command.go+254 vendor/github.com/andybalholm/brotli/compress_fragment.go+834 vendor/github.com/andybalholm/brotli/compress_fragment_two_pass.go+775 vendor/github.com/andybalholm/brotli/constants.go+77 vendor/github.com/andybalholm/brotli/context.go+2176 vendor/github.com/andybalholm/brotli/decode.go+2581 vendor/github.com/andybalholm/brotli/dictionary.go+122890 vendor/github.com/andybalholm/brotli/dictionary_hash.go+32779 vendor/github.com/andybalholm/brotli/encode.go+1220 vendor/github.com/andybalholm/brotli/encoder.go+177 vendor/github.com/andybalholm/brotli/encoder_dict.go+22 vendor/github.com/andybalholm/brotli/encoder_fast.go+197 vendor/github.com/andybalholm/brotli/entropy_encode.go+592 vendor/github.com/andybalholm/brotli/entropy_encode_static.go+4399 vendor/github.com/andybalholm/brotli/fast_log.go+290 vendor/github.com/andybalholm/brotli/find_match_length.go+45 vendor/github.com/andybalholm/brotli/flate/LICENSE+27 vendor/github.com/andybalholm/brotli/flate/README.md+2 vendor/github.com/andybalholm/brotli/flate/gzip.go+65 vendor/github.com/andybalholm/brotli/flate/huffman_bit_writer.go+517 vendor/github.com/andybalholm/brotli/flate/huffman_code.go+346 vendor/github.com/andybalholm/brotli/flate/token.go+80 vendor/github.com/andybalholm/brotli/flate/writer.go+66 vendor/github.com/andybalholm/brotli/h10.go+287 vendor/github.com/andybalholm/brotli/h5.go+214 vendor/github.com/andybalholm/brotli/h6.go+216 vendor/github.com/andybalholm/brotli/hash.go+342 vendor/github.com/andybalholm/brotli/hash_composite.go+93 vendor/github.com/andybalholm/brotli/hash_forgetful_chain.go+252 vendor/github.com/andybalholm/brotli/hash_longest_match_quickly.go+214 vendor/github.com/andybalholm/brotli/hash_rolling.go+168 vendor/github.com/andybalholm/brotli/histogram.go+226 vendor/github.com/andybalholm/brotli/http.go+189 vendor/github.com/andybalholm/brotli/huffman.go+653 vendor/github.com/andybalholm/brotli/literal_cost.go+182 vendor/github.com/andybalholm/brotli/matchfinder/bargain1.go+212 vendor/github.com/andybalholm/brotli/matchfinder/bargain2.go+248 vendor/github.com/andybalholm/brotli/matchfinder/bargain3.go+278 vendor/github.com/andybalholm/brotli/matchfinder/emitter.go+34 vendor/github.com/andybalholm/brotli/matchfinder/m0.go+175 vendor/github.com/andybalholm/brotli/matchfinder/m4.go+339 vendor/github.com/andybalholm/brotli/matchfinder/matchfinder.go+103 vendor/github.com/andybalholm/brotli/matchfinder/pathfinder.go+328 vendor/github.com/andybalholm/brotli/matchfinder/textencoder.go+53 vendor/github.com/andybalholm/brotli/matchfinder/trio.go+326 vendor/github.com/andybalholm/brotli/matchfinder/zdfast.go+258 vendor/github.com/andybalholm/brotli/matchfinder/zfast.go+206 vendor/github.com/andybalholm/brotli/matchfinder/zm.go+301 vendor/github.com/andybalholm/brotli/memory.go+66 vendor/github.com/andybalholm/brotli/metablock.go+574 vendor/github.com/andybalholm/brotli/metablock_command.go+165 vendor/github.com/andybalholm/brotli/metablock_distance.go+165 vendor/github.com/andybalholm/brotli/metablock_literal.go+165 vendor/github.com/andybalholm/brotli/params.go+37 vendor/github.com/andybalholm/brotli/platform.go+103 vendor/github.com/andybalholm/brotli/prefix.go+30 vendor/github.com/andybalholm/brotli/prefix_dec.go+723 vendor/github.com/andybalholm/brotli/quality.go+196 vendor/github.com/andybalholm/brotli/reader.go+111 vendor/github.com/andybalholm/brotli/ringbuffer.go+134 vendor/github.com/andybalholm/brotli/state.go+294 vendor/github.com/andybalholm/brotli/static_dict.go+662 vendor/github.com/andybalholm/brotli/static_dict_lut.go+75094 vendor/github.com/andybalholm/brotli/symbol_list.go+22 vendor/github.com/andybalholm/brotli/transform.go+641 vendor/github.com/andybalholm/brotli/utf8_util.go+70 vendor/github.com/andybalholm/brotli/util.go+7 vendor/github.com/andybalholm/brotli/write_bits.go+52 vendor/github.com/andybalholm/brotli/writer.go+162 vendor/github.com/andybalholm/cascadia/.travis.yml+14 vendor/github.com/andybalholm/cascadia/LICENSE+24 vendor/github.com/andybalholm/cascadia/README.md+144 vendor/github.com/andybalholm/cascadia/parser.go+889 vendor/github.com/andybalholm/cascadia/pseudo_classes.go+458 vendor/github.com/andybalholm/cascadia/selector.go+586 vendor/github.com/andybalholm/cascadia/serialize.go+176 vendor/github.com/andybalholm/cascadia/specificity.go+26 vendor/github.com/atotto/clipboard/.travis.yml+22 vendor/github.com/atotto/clipboard/LICENSE+27 vendor/github.com/atotto/clipboard/README.md+48 vendor/github.com/atotto/clipboard/clipboard.go+20 vendor/github.com/atotto/clipboard/clipboard_darwin.go+52 vendor/github.com/atotto/clipboard/clipboard_plan9.go+42 vendor/github.com/atotto/clipboard/clipboard_unix.go+149 vendor/github.com/atotto/clipboard/clipboard_windows.go+157 vendor/github.com/aws/aws-sdk-go-v2/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/NOTICE.txt+3 vendor/github.com/aws/aws-sdk-go-v2/aws/accountid_endpoint_mode.go+18 vendor/github.com/aws/aws-sdk-go-v2/aws/checksum.go+33 vendor/github.com/aws/aws-sdk-go-v2/aws/config.go+254 vendor/github.com/aws/aws-sdk-go-v2/aws/context.go+22 vendor/github.com/aws/aws-sdk-go-v2/aws/credential_cache.go+235 vendor/github.com/aws/aws-sdk-go-v2/aws/credentials.go+234 vendor/github.com/aws/aws-sdk-go-v2/aws/defaults/auto.go+38 vendor/github.com/aws/aws-sdk-go-v2/aws/defaults/configuration.go+43 vendor/github.com/aws/aws-sdk-go-v2/aws/defaults/defaults.go+50 vendor/github.com/aws/aws-sdk-go-v2/aws/defaults/doc.go+2 vendor/github.com/aws/aws-sdk-go-v2/aws/defaultsmode.go+95 vendor/github.com/aws/aws-sdk-go-v2/aws/doc.go+62 vendor/github.com/aws/aws-sdk-go-v2/aws/endpoints.go+247 vendor/github.com/aws/aws-sdk-go-v2/aws/errors.go+9 vendor/github.com/aws/aws-sdk-go-v2/aws/from_ptr.go+365 vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/aws/logging.go+119 vendor/github.com/aws/aws-sdk-go-v2/aws/logging_generate.go+95 vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/metadata.go+213 vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/middleware.go+168 vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/osname.go+24 vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/osname_go115.go+24 vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/recursion_detection.go+94 vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/request_id.go+27 vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/request_id_retriever.go+57 vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/user_agent.go+398 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/CHANGELOG.md+203 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/debug.go+144 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/decode.go+218 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/encode.go+167 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/error.go+23 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi/headers.go+24 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi/middleware.go+71 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi/transport.go+13 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi/transport_go117.go+12 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/header.go+175 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/header_value.go+521 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/message.go+99 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/array.go+61 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/encoder.go+80 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/map.go+78 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/middleware.go+62 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/object.go+68 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/value.go+117 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/restjson/decoder_util.go+85 vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/xml/error_utils.go+48 vendor/github.com/aws/aws-sdk-go-v2/aws/ratelimit/none.go+20 vendor/github.com/aws/aws-sdk-go-v2/aws/ratelimit/token_bucket.go+96 vendor/github.com/aws/aws-sdk-go-v2/aws/ratelimit/token_rate_limit.go+83 vendor/github.com/aws/aws-sdk-go-v2/aws/request.go+25 vendor/github.com/aws/aws-sdk-go-v2/aws/restrict_file_permissions.go+21 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/adaptive.go+156 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/adaptive_ratelimit.go+158 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/adaptive_token_bucket.go+83 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/attempt_metrics.go+51 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/doc.go+80 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/errors.go+20 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/jitter_backoff.go+124 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/metadata.go+52 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/middleware.go+487 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/retry.go+103 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/retryable_error.go+228 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/standard.go+343 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/throttle_error.go+60 vendor/github.com/aws/aws-sdk-go-v2/aws/retry/timeout_error.go+52 vendor/github.com/aws/aws-sdk-go-v2/aws/retryer.go+127 vendor/github.com/aws/aws-sdk-go-v2/aws/runtime.go+14 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/cache.go+115 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/const.go+40 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/header_rules.go+82 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/headers.go+70 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/hmac.go+13 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/host.go+75 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/scope.go+13 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/time.go+36 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/util.go+80 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/v4/middleware.go+420 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/v4/presign_middleware.go+127 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/v4/stream.go+86 vendor/github.com/aws/aws-sdk-go-v2/aws/signer/v4/v4.go+564 vendor/github.com/aws/aws-sdk-go-v2/aws/to_ptr.go+297 vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/client.go+355 vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/content_type.go+42 vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/response_error.go+33 vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/response_error_middleware.go+56 vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/timeout_read_closer.go+109 vendor/github.com/aws/aws-sdk-go-v2/aws/types.go+42 vendor/github.com/aws/aws-sdk-go-v2/aws/version.go+8 vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md+1097 vendor/github.com/aws/aws-sdk-go-v2/config/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/config/auth_scheme_preference.go+19 vendor/github.com/aws/aws-sdk-go-v2/config/config.go+237 vendor/github.com/aws/aws-sdk-go-v2/config/defaultsmode.go+47 vendor/github.com/aws/aws-sdk-go-v2/config/doc.go+20 vendor/github.com/aws/aws-sdk-go-v2/config/env_config.go+966 vendor/github.com/aws/aws-sdk-go-v2/config/generate.go+4 vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/errors.go+22 vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/ini.go+56 vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/parse.go+109 vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/sections.go+157 vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/strings.go+89 vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/token.go+32 vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/tokenize.go+92 vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/value.go+93 vendor/github.com/aws/aws-sdk-go-v2/config/load_options.go+1371 vendor/github.com/aws/aws-sdk-go-v2/config/local.go+51 vendor/github.com/aws/aws-sdk-go-v2/config/provider.go+802 vendor/github.com/aws/aws-sdk-go-v2/config/resolve.go+458 vendor/github.com/aws/aws-sdk-go-v2/config/resolve_bearer_token.go+122 vendor/github.com/aws/aws-sdk-go-v2/config/resolve_credentials.go+650 vendor/github.com/aws/aws-sdk-go-v2/config/shared_config.go+1704 vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md+990 vendor/github.com/aws/aws-sdk-go-v2/credentials/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/credentials/doc.go+4 vendor/github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds/doc.go+58 vendor/github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds/provider.go+241 vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client/auth.go+48 vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client/client.go+165 vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client/endpoints.go+20 vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client/middleware.go+164 vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/provider.go+207 vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/credentials/logincreds/dpop.go+150 vendor/github.com/aws/aws-sdk-go-v2/credentials/logincreds/file.go+14 vendor/github.com/aws/aws-sdk-go-v2/credentials/logincreds/provider.go+184 vendor/github.com/aws/aws-sdk-go-v2/credentials/logincreds/token.go+110 vendor/github.com/aws/aws-sdk-go-v2/credentials/processcreds/doc.go+92 vendor/github.com/aws/aws-sdk-go-v2/credentials/processcreds/provider.go+296 vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/doc.go+81 vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_cached_token.go+232 vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_credentials_provider.go+165 vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_token_provider.go+147 vendor/github.com/aws/aws-sdk-go-v2/credentials/static_provider.go+63 vendor/github.com/aws/aws-sdk-go-v2/credentials/stscreds/assume_role_provider.go+338 vendor/github.com/aws/aws-sdk-go-v2/credentials/stscreds/web_identity_provider.go+181 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md+584 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_client.go+358 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetDynamicData.go+77 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetIAMInfo.go+103 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetInstanceIdentityDocument.go+110 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetMetadata.go+77 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetRegion.go+73 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetToken.go+119 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetUserData.go+61 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/auth.go+48 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/doc.go+12 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/endpoints.go+20 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/internal/config/resolvers.go+114 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/request_middleware.go+313 vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/token_provider.go+261 vendor/github.com/aws/aws-sdk-go-v2/internal/auth/auth.go+45 vendor/github.com/aws/aws-sdk-go-v2/internal/auth/scheme.go+191 vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/bearer_token_adapter.go+43 vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/bearer_token_signer_adapter.go+35 vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/credentials_adapter.go+46 vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/smithy.go+2 vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/v4signer_adapter.go+57 vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/v4signer_adapter_eventstream.go+51 vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md+544 vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/config.go+65 vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/endpoints.go+57 vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/internal/context/context.go+65 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/arn.go+94 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/doc.go+3 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/generate.go+7 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/host.go+51 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partition.go+76 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.go+496 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.json+267 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/endpoints.go+201 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md+519 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/endpoints.go+302 vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/internal/rand/rand.go+33 vendor/github.com/aws/aws-sdk-go-v2/internal/sdk/interfaces.go+9 vendor/github.com/aws/aws-sdk-go-v2/internal/sdk/time.go+74 vendor/github.com/aws/aws-sdk-go-v2/internal/sdkio/byte.go+12 vendor/github.com/aws/aws-sdk-go-v2/internal/shareddefaults/shared_config.go+47 vendor/github.com/aws/aws-sdk-go-v2/internal/strings/strings.go+11 vendor/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/LICENSE+28 vendor/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/docs.go+7 vendor/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/singleflight.go+210 vendor/github.com/aws/aws-sdk-go-v2/internal/timeconv/duration.go+13 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md+486 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/credentials.go+141 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/error.go+17 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/crypto/compare.go+30 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/crypto/ecc.go+113 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/const.go+36 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/header_rules.go+82 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/headers.go+68 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/hmac.go+13 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/host.go+75 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/time.go+36 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/util.go+64 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/middleware.go+118 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/presign_middleware.go+117 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/smithy.go+92 vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/v4a.go+520 vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md+220 vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/accept_encoding_gzip.go+176 vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/doc.go+22 vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md+571 vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/context.go+56 vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/doc.go+3 vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/middleware.go+110 vendor/github.com/aws/aws-sdk-go-v2/service/signin/CHANGELOG.md+85 vendor/github.com/aws/aws-sdk-go-v2/service/signin/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_client.go+945 vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_CreateOAuth2Token.go+212 vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteConsoleAuthorizationConfiguration.go+168 vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteResourcePermissionStatement.go+196 vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetConsoleAuthorizationConfiguration.go+168 vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetResourcePolicy.go+155 vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_ListResourcePermissionStatements.go+261 vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutConsoleAuthorizationConfiguration.go+168 vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutResourcePermissionStatement.go+216 vendor/github.com/aws/aws-sdk-go-v2/service/signin/auth.go+361 vendor/github.com/aws/aws-sdk-go-v2/service/signin/deserializers.go+2474 vendor/github.com/aws/aws-sdk-go-v2/service/signin/doc.go+9 vendor/github.com/aws/aws-sdk-go-v2/service/signin/endpoints.go+854 vendor/github.com/aws/aws-sdk-go-v2/service/signin/generated.json+40 vendor/github.com/aws/aws-sdk-go-v2/service/signin/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/service/signin/internal/endpoints/endpoints.go+333 vendor/github.com/aws/aws-sdk-go-v2/service/signin/options.go+242 vendor/github.com/aws/aws-sdk-go-v2/service/signin/serializers.go+724 vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/enums.go+46 vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/errors.go+247 vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/types.go+162 vendor/github.com/aws/aws-sdk-go-v2/service/signin/validators.go+111 vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md+792 vendor/github.com/aws/aws-sdk-go-v2/service/sso/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go+929 vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go+165 vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go+263 vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go+261 vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go+164 vendor/github.com/aws/aws-sdk-go-v2/service/sso/auth.go+379 vendor/github.com/aws/aws-sdk-go-v2/service/sso/deserializers.go+1171 vendor/github.com/aws/aws-sdk-go-v2/service/sso/doc.go+27 vendor/github.com/aws/aws-sdk-go-v2/service/sso/endpoints.go+570 vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json+35 vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints/endpoints.go+628 vendor/github.com/aws/aws-sdk-go-v2/service/sso/options.go+238 vendor/github.com/aws/aws-sdk-go-v2/service/sso/serializers.go+309 vendor/github.com/aws/aws-sdk-go-v2/service/sso/types/errors.go+115 vendor/github.com/aws/aws-sdk-go-v2/service/sso/types/types.go+63 vendor/github.com/aws/aws-sdk-go-v2/service/sso/validators.go+175 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md+790 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go+929 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go+235 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go+282 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go+206 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go+188 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/auth.go+373 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/deserializers.go+2244 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/doc.go+49 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/endpoints.go+570 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json+36 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/internal/endpoints/endpoints.go+628 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/options.go+238 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/serializers.go+512 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/enums.go+44 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/errors.go+430 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/types.go+25 vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/validators.go+184 vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md+832 vendor/github.com/aws/aws-sdk-go-v2/service/sts/LICENSE.txt+202 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go+1115 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go+544 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go+455 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go+472 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go+229 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go+189 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go+180 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go+192 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetDelegatedAccessToken.go+169 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go+393 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go+239 vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetWebIdentityToken.go+192 vendor/github.com/aws/aws-sdk-go-v2/service/sts/auth.go+377 vendor/github.com/aws/aws-sdk-go-v2/service/sts/deserializers.go+3456 vendor/github.com/aws/aws-sdk-go-v2/service/sts/doc.go+13 vendor/github.com/aws/aws-sdk-go-v2/service/sts/endpoints.go+683 vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json+45 vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go+6 vendor/github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints/endpoints.go+585 vendor/github.com/aws/aws-sdk-go-v2/service/sts/options.go+286 vendor/github.com/aws/aws-sdk-go-v2/service/sts/serializers.go+1198 vendor/github.com/aws/aws-sdk-go-v2/service/sts/types/errors.go+363 vendor/github.com/aws/aws-sdk-go-v2/service/sts/types/types.go+144 vendor/github.com/aws/aws-sdk-go-v2/service/sts/validators.go+433 vendor/github.com/aws/smithy-go/.gitignore+29 vendor/github.com/aws/smithy-go/.travis.yml+28 vendor/github.com/aws/smithy-go/AGENTS.md+172 vendor/github.com/aws/smithy-go/CHANGELOG.md+454 vendor/github.com/aws/smithy-go/CODE_OF_CONDUCT.md+4 vendor/github.com/aws/smithy-go/CONTRIBUTING.md+90 vendor/github.com/aws/smithy-go/LICENSE+175 vendor/github.com/aws/smithy-go/Makefile+130 vendor/github.com/aws/smithy-go/NOTICE+1 vendor/github.com/aws/smithy-go/README.md+107 vendor/github.com/aws/smithy-go/auth/auth.go+3 vendor/github.com/aws/smithy-go/auth/bearer/docs.go+3 vendor/github.com/aws/smithy-go/auth/bearer/middleware.go+104 vendor/github.com/aws/smithy-go/auth/bearer/token.go+50 vendor/github.com/aws/smithy-go/auth/bearer/token_cache.go+208 vendor/github.com/aws/smithy-go/auth/identity.go+47 vendor/github.com/aws/smithy-go/auth/option.go+25 vendor/github.com/aws/smithy-go/auth/scheme_id.go+20 vendor/github.com/aws/smithy-go/changelog-template.json+9 vendor/github.com/aws/smithy-go/context/suppress_expired.go+81 vendor/github.com/aws/smithy-go/doc.go+2 vendor/github.com/aws/smithy-go/document.go+10 vendor/github.com/aws/smithy-go/document/doc.go+12 vendor/github.com/aws/smithy-go/document/document.go+239 vendor/github.com/aws/smithy-go/document/errors.go+75 vendor/github.com/aws/smithy-go/encoding/doc.go+4 vendor/github.com/aws/smithy-go/encoding/encoding.go+40 vendor/github.com/aws/smithy-go/encoding/httpbinding/encode.go+123 vendor/github.com/aws/smithy-go/encoding/httpbinding/header.go+122 vendor/github.com/aws/smithy-go/encoding/httpbinding/path_replace.go+108 vendor/github.com/aws/smithy-go/encoding/httpbinding/query.go+107 vendor/github.com/aws/smithy-go/encoding/httpbinding/uri.go+111 vendor/github.com/aws/smithy-go/encoding/json/array.go+35 vendor/github.com/aws/smithy-go/encoding/json/constants.go+15 vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go+139 vendor/github.com/aws/smithy-go/encoding/json/encoder.go+30 vendor/github.com/aws/smithy-go/encoding/json/escape.go+198 vendor/github.com/aws/smithy-go/encoding/json/object.go+40 vendor/github.com/aws/smithy-go/encoding/json/value.go+154 vendor/github.com/aws/smithy-go/encoding/xml/array.go+49 vendor/github.com/aws/smithy-go/encoding/xml/constants.go+10 vendor/github.com/aws/smithy-go/encoding/xml/doc.go+49 vendor/github.com/aws/smithy-go/encoding/xml/element.go+91 vendor/github.com/aws/smithy-go/encoding/xml/encoder.go+51 vendor/github.com/aws/smithy-go/encoding/xml/error_utils.go+51 vendor/github.com/aws/smithy-go/encoding/xml/escape.go+137 vendor/github.com/aws/smithy-go/encoding/xml/map.go+53 vendor/github.com/aws/smithy-go/encoding/xml/value.go+302 vendor/github.com/aws/smithy-go/encoding/xml/xml_decoder.go+154 vendor/github.com/aws/smithy-go/endpoints/endpoint.go+23 vendor/github.com/aws/smithy-go/endpoints/private/bdd/evaluate.go+35 vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/doc.go+4 vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/split.go+16 vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/string_slice.go+18 vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/strings.go+25 vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/uri.go+133 vendor/github.com/aws/smithy-go/errors.go+137 vendor/github.com/aws/smithy-go/eventstream/const.go+24 vendor/github.com/aws/smithy-go/eventstream/debug.go+144 vendor/github.com/aws/smithy-go/eventstream/decode.go+218 vendor/github.com/aws/smithy-go/eventstream/deserializer.go+294 vendor/github.com/aws/smithy-go/eventstream/encode.go+167 vendor/github.com/aws/smithy-go/eventstream/error.go+23 vendor/github.com/aws/smithy-go/eventstream/header.go+175 vendor/github.com/aws/smithy-go/eventstream/header_value.go+521 vendor/github.com/aws/smithy-go/eventstream/message.go+99 vendor/github.com/aws/smithy-go/eventstream/serializer.go+228 vendor/github.com/aws/smithy-go/eventstream/signer.go+82 vendor/github.com/aws/smithy-go/eventstream/types.go+26 vendor/github.com/aws/smithy-go/go_module_metadata.go+6 vendor/github.com/aws/smithy-go/internal/sync/singleflight/LICENSE+28 vendor/github.com/aws/smithy-go/internal/sync/singleflight/docs.go+8 vendor/github.com/aws/smithy-go/internal/sync/singleflight/singleflight.go+210 vendor/github.com/aws/smithy-go/io/byte.go+12 vendor/github.com/aws/smithy-go/io/doc.go+2 vendor/github.com/aws/smithy-go/io/reader.go+16 vendor/github.com/aws/smithy-go/io/ringbuffer.go+94 vendor/github.com/aws/smithy-go/local-mod-replace.sh+39 vendor/github.com/aws/smithy-go/logging/logger.go+82 vendor/github.com/aws/smithy-go/metrics/metrics.go+136 vendor/github.com/aws/smithy-go/metrics/nop.go+98 vendor/github.com/aws/smithy-go/middleware/context.go+41 vendor/github.com/aws/smithy-go/middleware/doc.go+67 vendor/github.com/aws/smithy-go/middleware/eventstream_middleware.go+21 vendor/github.com/aws/smithy-go/middleware/logging.go+46 vendor/github.com/aws/smithy-go/middleware/metadata.go+65 vendor/github.com/aws/smithy-go/middleware/middleware.go+71 vendor/github.com/aws/smithy-go/middleware/ordered_group.go+270 vendor/github.com/aws/smithy-go/middleware/stack.go+209 vendor/github.com/aws/smithy-go/middleware/stack_values.go+100 vendor/github.com/aws/smithy-go/middleware/step_build.go+298 vendor/github.com/aws/smithy-go/middleware/step_deserialize.go+300 vendor/github.com/aws/smithy-go/middleware/step_finalize.go+298 vendor/github.com/aws/smithy-go/middleware/step_initialize.go+299 vendor/github.com/aws/smithy-go/middleware/step_serialize.go+305 vendor/github.com/aws/smithy-go/modman.toml+9 vendor/github.com/aws/smithy-go/private/requestcompression/gzip.go+30 vendor/github.com/aws/smithy-go/private/requestcompression/middleware_capture_request_compression.go+52 vendor/github.com/aws/smithy-go/private/requestcompression/request_compression.go+103 vendor/github.com/aws/smithy-go/properties.go+69 vendor/github.com/aws/smithy-go/ptr/doc.go+5 vendor/github.com/aws/smithy-go/ptr/from_ptr.go+601 vendor/github.com/aws/smithy-go/ptr/gen_scalars.go+83 vendor/github.com/aws/smithy-go/ptr/to_ptr.go+499 vendor/github.com/aws/smithy-go/rand/doc.go+3 vendor/github.com/aws/smithy-go/rand/rand.go+31 vendor/github.com/aws/smithy-go/rand/uuid.go+87 vendor/github.com/aws/smithy-go/schema.go+328 vendor/github.com/aws/smithy-go/schema_ext.go+37 vendor/github.com/aws/smithy-go/serde.go+229 vendor/github.com/aws/smithy-go/sync/error.go+53 vendor/github.com/aws/smithy-go/time/time.go+134 vendor/github.com/aws/smithy-go/tracing/context.go+96 vendor/github.com/aws/smithy-go/tracing/nop.go+32 vendor/github.com/aws/smithy-go/tracing/tracing.go+95 vendor/github.com/aws/smithy-go/trait.go+21 vendor/github.com/aws/smithy-go/traits/http.go+69 vendor/github.com/aws/smithy-go/traits/index.go+107 vendor/github.com/aws/smithy-go/traits/serde.go+56 vendor/github.com/aws/smithy-go/traits/traits.go+72 vendor/github.com/aws/smithy-go/transport/http/auth.go+30 vendor/github.com/aws/smithy-go/transport/http/auth_schemes.go+45 vendor/github.com/aws/smithy-go/transport/http/checksum_middleware.go+70 vendor/github.com/aws/smithy-go/transport/http/client.go+161 vendor/github.com/aws/smithy-go/transport/http/doc.go+5 vendor/github.com/aws/smithy-go/transport/http/eventstream.go+209 vendor/github.com/aws/smithy-go/transport/http/eventstream_middleware.go+69 vendor/github.com/aws/smithy-go/transport/http/headerlist.go+163 vendor/github.com/aws/smithy-go/transport/http/host.go+89 vendor/github.com/aws/smithy-go/transport/http/interceptor.go+321 vendor/github.com/aws/smithy-go/transport/http/interceptor_middleware.go+325 vendor/github.com/aws/smithy-go/transport/http/internal/io/safe.go+75 vendor/github.com/aws/smithy-go/transport/http/md5_checksum.go+25 vendor/github.com/aws/smithy-go/transport/http/metrics.go+204 vendor/github.com/aws/smithy-go/transport/http/middleware_close_response_body.go+79 vendor/github.com/aws/smithy-go/transport/http/middleware_content_length.go+84 vendor/github.com/aws/smithy-go/transport/http/middleware_header_comment.go+81 vendor/github.com/aws/smithy-go/transport/http/middleware_headers.go+167 vendor/github.com/aws/smithy-go/transport/http/middleware_http_logging.go+75 vendor/github.com/aws/smithy-go/transport/http/middleware_metadata.go+51 vendor/github.com/aws/smithy-go/transport/http/middleware_min_proto.go+79 vendor/github.com/aws/smithy-go/transport/http/properties.go+80 vendor/github.com/aws/smithy-go/transport/http/protocol.go+27 vendor/github.com/aws/smithy-go/transport/http/request.go+188 vendor/github.com/aws/smithy-go/transport/http/response.go+34 vendor/github.com/aws/smithy-go/transport/http/time.go+13 vendor/github.com/aws/smithy-go/transport/http/url.go+44 vendor/github.com/aws/smithy-go/transport/http/user_agent.go+37 vendor/github.com/aws/smithy-go/type_registry.go+70 vendor/github.com/aws/smithy-go/validation.go+140 vendor/github.com/aymanbagabas/go-udiff/LICENSE-BSD+27 vendor/github.com/aymanbagabas/go-udiff/LICENSE-MIT+21 vendor/github.com/aymanbagabas/go-udiff/Makefile+4 vendor/github.com/aymanbagabas/go-udiff/README.md+142 vendor/github.com/aymanbagabas/go-udiff/diff.go+177 vendor/github.com/aymanbagabas/go-udiff/export.go+16 vendor/github.com/aymanbagabas/go-udiff/lcs/common.go+179 vendor/github.com/aymanbagabas/go-udiff/lcs/doc.go+156 vendor/github.com/aymanbagabas/go-udiff/lcs/export.go+11 vendor/github.com/aymanbagabas/go-udiff/lcs/git.sh+33 vendor/github.com/aymanbagabas/go-udiff/lcs/labels.go+55 vendor/github.com/aymanbagabas/go-udiff/lcs/old.go+475 vendor/github.com/aymanbagabas/go-udiff/lcs/sequence.go+70 vendor/github.com/aymanbagabas/go-udiff/merge.go+81 vendor/github.com/aymanbagabas/go-udiff/ndiff.go+118 vendor/github.com/aymanbagabas/go-udiff/unified.go+314 vendor/github.com/aymerick/douceur/LICENSE+22 vendor/github.com/aymerick/douceur/css/declaration.go+60

5775 more files changed are not listed.

.agents/skills/builtin-skills/SKILL.mdnew file+42
@@ -0,0 +1,42 @@
1+---
2+name: builtin-skills
3+description:
4+ Use when creating a new builtin skill for Crush, editing an existing builtin
5+ skill (internal/skills/builtin/), or when the user needs to understand how the
6+ embedded skill system works.
7+---
8+
9+# Builtin Skills
10+
11+Crush embeds skills directly into the binary via `internal/skills/builtin/`.
12+These are always available without user configuration.
13+
14+## How It Works
15+
16+- Each skill lives in `internal/skills/builtin/<skill-name>/SKILL.md`.
17+- The tree is embedded at compile time via `//go:embed builtin/*` in
18+ `internal/skills/embed.go`.
19+- `DiscoverBuiltin()` walks the embedded FS, parses each `SKILL.md`, and sets
20+ paths with the `crush://skills/` prefix (e.g., `crush://skills/jq/SKILL.md`).
21+- The View tool resolves `crush://` paths from the embedded FS, not disk.
22+- User skills with the same name override builtins (last occurrence wins in
23+ `Deduplicate()`).
24+
25+## Adding a New Builtin Skill
26+
27+1. Create `internal/skills/builtin/<skill-name>/SKILL.md` with YAML frontmatter
28+ (`name`, `description`) and markdown instructions. The directory name must
29+ match the `name` field.
30+2. No extra wiring needed — `//go:embed builtin/*` picks up new directories
31+ automatically.
32+3. Add a test assertion in `TestDiscoverBuiltin` in
33+ `internal/skills/skills_test.go` to verify discovery.
34+4. Build and test: `go build . && go test ./internal/skills/...`
35+
36+## Existing Builtin Skills
37+
38+| Skill | Directory | Description |
39+| -------------- | ----------------------- | ------------------------------------------ |
40+| `crush-config` | `builtin/crush-config/` | Crush configuration help |
41+| `crush-hooks` | `builtin/crush-hooks/` | Authoring, configuring and debugging hooks |
42+| `jq` | `builtin/jq/` | jq JSON processor usage guide |
.agents/skills/shell-builtins/SKILL.mdnew file+72
@@ -0,0 +1,72 @@
1+---
2+name: shell-builtins
3+description: Use when creating a new shell builtin command for Crush (internal/shell/), editing an existing one, or when the user needs to understand how commands are intercepted in Crush's embedded shell.
4+---
5+
6+# Shell Builtins
7+
8+Crush's shell (`internal/shell/`) uses `mvdan.cc/sh/v3` for POSIX shell
9+emulation. Commands can be intercepted before they reach the OS by adding
10+**builtins** — functions handled in-process.
11+
12+## How Builtins Work
13+
14+Builtins live in `builtinHandler()` in `internal/shell/run.go`. This is an
15+`interp.ExecHandlerFunc` middleware registered in `standardHandlers()`
16+**before** the block handler, so builtins run even for commands that would
17+otherwise be blocked. The same handler chain is shared by the stateful
18+`Shell` type and the stateless `Run` entrypoint used by the hook runner,
19+so builtins are available identically in the `bash` tool and in hooks.
20+
21+The handler is a switch on `args[0]`. Each case either handles the command
22+inline or delegates to a helper function.
23+
24+## Adding a New Builtin
25+
26+1. **Add the case** to the switch in `builtinHandler()` in `run.go`.
27+2. **Get I/O from the handler context**, not from `os.Stdin`/`os.Stdout`.
28+ This ensures the builtin works with pipes and redirections:
29+ ```go
30+ case "mycommand":
31+ hc := interp.HandlerCtx(ctx)
32+ return handleMyCommand(ctx, args, hc.Stdin, hc.Stdout, hc.Stderr)
33+ ```
34+3. **Implement the handler** in its own file (e.g.,
35+ `internal/shell/mycommand.go`). The function signature must accept a
36+ `context.Context` as the first parameter, plus args, stdin, stdout, and
37+ stderr:
38+ ```go
39+ func handleMyCommand(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) error {
40+ // args[0] is the command name ("mycommand"), args[1:] are arguments.
41+ // Write output to stdout, errors to stderr.
42+ // Return nil on success, or interp.ExitStatus(n) for non-zero exit codes.
43+ }
44+ ```
45+4. **Poll `ctx` in every unbounded loop.** Builtins that iterate over
46+ input, emit values in a generator-style loop, or do any other work
47+ that can exceed a few milliseconds MUST check `ctx.Err()` on each
48+ iteration and return it verbatim when non-nil. Hook timeouts rely on
49+ this: an unbounded builtin that never polls ctx cannot be interrupted
50+ by a hook's `timeout_sec`, and the hook runner will have to abandon
51+ the goroutine (see `internal/hooks/runner.go`). Returning `ctx.Err()`
52+ (not `interp.ExitStatus(n)`) lets callers distinguish "command exited
53+ non-zero" from "we ran out of time".
54+ ```go
55+ for _, item := range items {
56+ if err := ctx.Err(); err != nil {
57+ return err
58+ }
59+ // ... process item
60+ }
61+ ```
62+5. **Return values**: return `nil` for success, `interp.ExitStatus(n)` for
63+ non-zero exit codes, or `ctx.Err()` on cancellation. Write error
64+ messages to `stderr` before returning.
65+6. **No extra wiring needed** — `builtinHandler()` is already registered
66+ in `standardHandlers()`.
67+
68+## Existing Builtins
69+
70+| Command | File | Description |
71+|---------|------|-------------|
72+| `jq` | `jq.go` | JSON processor using `github.com/itchyny/gojq` |
.envrcnew file+1
@@ -0,0 +1 @@
1+use flake
.gitattributes+2
@@ -1,2 +1,4 @@
11*.golden linguist-generated=true -text
22.github/crush-schema.json linguist-generated=true
3+internal/agent/hyper/provider.json linguist-generated=true
4+internal/agent/testdata/**/*.yaml -diff linguist-generated=true
.github/CODEOWNERSdeleted−1
@@ -1 +0,0 @@
1−*.go @charmbracelet/everyone
.github/cla-signatures.json+1368
@@ -727,6 +727,1374 @@
727727 "created_at": "2025-10-18T19:24:00Z",
728728 "repoId": 987670088,
729729 "pullRequestNo": 1254
730+ },
731+ {
732+ "name": "Jesssullivan",
733+ "id": 37297218,
734+ "comment_id": 3439361465,
735+ "created_at": "2025-10-23T21:50:17Z",
736+ "repoId": 987670088,
737+ "pullRequestNo": 1292
738+ },
739+ {
740+ "name": "mmangkad",
741+ "id": 176301910,
742+ "comment_id": 3440286180,
743+ "created_at": "2025-10-24T01:32:47Z",
744+ "repoId": 987670088,
745+ "pullRequestNo": 1294
746+ },
747+ {
748+ "name": "blouflab",
749+ "id": 227565774,
750+ "comment_id": 3444483981,
751+ "created_at": "2025-10-24T18:59:01Z",
752+ "repoId": 987670088,
753+ "pullRequestNo": 1296
754+ },
755+ {
756+ "name": "Supratim69",
757+ "id": 128067781,
758+ "comment_id": 3444891894,
759+ "created_at": "2025-10-24T20:58:01Z",
760+ "repoId": 987670088,
761+ "pullRequestNo": 1299
762+ },
763+ {
764+ "name": "plandem",
765+ "id": 1381366,
766+ "comment_id": 3446669312,
767+ "created_at": "2025-10-25T12:52:04Z",
768+ "repoId": 987670088,
769+ "pullRequestNo": 1302
770+ },
771+ {
772+ "name": "dawndiy",
773+ "id": 1512740,
774+ "comment_id": 3456210693,
775+ "created_at": "2025-10-28T12:24:21Z",
776+ "repoId": 987670088,
777+ "pullRequestNo": 1312
778+ },
779+ {
780+ "name": "bradflaugher",
781+ "id": 16511019,
782+ "comment_id": 3458922489,
783+ "created_at": "2025-10-28T23:13:15Z",
784+ "repoId": 987670088,
785+ "pullRequestNo": 1324
786+ },
787+ {
788+ "name": "teras",
789+ "id": 592568,
790+ "comment_id": 3465825058,
791+ "created_at": "2025-10-30T02:04:26Z",
792+ "repoId": 987670088,
793+ "pullRequestNo": 1335
794+ },
795+ {
796+ "name": "heynemann",
797+ "id": 60965,
798+ "comment_id": 3475594747,
799+ "created_at": "2025-11-01T03:21:03Z",
800+ "repoId": 987670088,
801+ "pullRequestNo": 1357
802+ },
803+ {
804+ "name": "niklasschaeffer",
805+ "id": 1948226,
806+ "comment_id": 3476119118,
807+ "created_at": "2025-11-01T10:06:05Z",
808+ "repoId": 987670088,
809+ "pullRequestNo": 1358
810+ },
811+ {
812+ "name": "LarsArtmann",
813+ "id": 23587853,
814+ "comment_id": 3488527230,
815+ "created_at": "2025-11-05T00:18:02Z",
816+ "repoId": 987670088,
817+ "pullRequestNo": 1384
818+ },
819+ {
820+ "name": "danielmerja",
821+ "id": 30878766,
822+ "comment_id": 3492618827,
823+ "created_at": "2025-11-05T17:59:51Z",
824+ "repoId": 987670088,
825+ "pullRequestNo": 1387
826+ },
827+ {
828+ "name": "nanvenomous",
829+ "id": 43622197,
830+ "comment_id": 3497693075,
831+ "created_at": "2025-11-06T15:05:00Z",
832+ "repoId": 987670088,
833+ "pullRequestNo": 1392
834+ },
835+ {
836+ "name": "novalis78",
837+ "id": 190390,
838+ "comment_id": 3506836115,
839+ "created_at": "2025-11-08T19:53:10Z",
840+ "repoId": 987670088,
841+ "pullRequestNo": 1408
842+ },
843+ {
844+ "name": "alewtschuk",
845+ "id": 19924911,
846+ "comment_id": 3520127241,
847+ "created_at": "2025-11-12T05:44:54Z",
848+ "repoId": 987670088,
849+ "pullRequestNo": 1429
850+ },
851+ {
852+ "name": "Iflgit",
853+ "id": 24231648,
854+ "comment_id": 3536325469,
855+ "created_at": "2025-11-15T10:46:24Z",
856+ "repoId": 987670088,
857+ "pullRequestNo": 1450
858+ },
859+ {
860+ "name": "iainlane",
861+ "id": 321014,
862+ "comment_id": 3539345738,
863+ "created_at": "2025-11-16T20:55:47Z",
864+ "repoId": 987670088,
865+ "pullRequestNo": 1457
866+ },
867+ {
868+ "name": "micahwalter",
869+ "id": 47419,
870+ "comment_id": 3553482361,
871+ "created_at": "2025-11-19T15:59:07Z",
872+ "repoId": 987670088,
873+ "pullRequestNo": 1478
874+ },
875+ {
876+ "name": "heimoshuiyu",
877+ "id": 22657774,
878+ "comment_id": 3565689668,
879+ "created_at": "2025-11-22T05:23:17Z",
880+ "repoId": 987670088,
881+ "pullRequestNo": 1496
882+ },
883+ {
884+ "name": "masroor-ahmad",
885+ "id": 75073229,
886+ "comment_id": 3592527587,
887+ "created_at": "2025-11-30T12:55:09Z",
888+ "repoId": 987670088,
889+ "pullRequestNo": 1532
890+ },
891+ {
892+ "name": "thezbm",
893+ "id": 24851999,
894+ "comment_id": 3595049411,
895+ "created_at": "2025-12-01T07:39:02Z",
896+ "repoId": 987670088,
897+ "pullRequestNo": 1534
898+ },
899+ {
900+ "name": "marifcelik",
901+ "id": 46600975,
902+ "comment_id": 3610641638,
903+ "created_at": "2025-12-04T07:17:10Z",
904+ "repoId": 987670088,
905+ "pullRequestNo": 1546
906+ },
907+ {
908+ "name": "mike1858",
909+ "id": 223734115,
910+ "comment_id": 3615055552,
911+ "created_at": "2025-12-05T02:26:29Z",
912+ "repoId": 987670088,
913+ "pullRequestNo": 1553
914+ },
915+ {
916+ "name": "Guxinpei",
917+ "id": 20122411,
918+ "comment_id": 3617461839,
919+ "created_at": "2025-12-05T15:51:04Z",
920+ "repoId": 987670088,
921+ "pullRequestNo": 1555
922+ },
923+ {
924+ "name": "mikluko",
925+ "id": 42915,
926+ "comment_id": 3620605876,
927+ "created_at": "2025-12-06T15:43:45Z",
928+ "repoId": 987670088,
929+ "pullRequestNo": 1558
930+ },
931+ {
932+ "name": "Gustave-241021",
933+ "id": 185743951,
934+ "comment_id": 3620851967,
935+ "created_at": "2025-12-06T18:13:11Z",
936+ "repoId": 987670088,
937+ "pullRequestNo": 1560
938+ },
939+ {
940+ "name": "mengwong",
941+ "id": 1480631,
942+ "comment_id": 3636765109,
943+ "created_at": "2025-12-10T12:04:50Z",
944+ "repoId": 987670088,
945+ "pullRequestNo": 1592
946+ },
947+ {
948+ "name": "nonsleepr",
949+ "id": 2337602,
950+ "comment_id": 3644171671,
951+ "created_at": "2025-12-11T23:09:21Z",
952+ "repoId": 987670088,
953+ "pullRequestNo": 1611
954+ },
955+ {
956+ "name": "strawberry-code",
957+ "id": 18684103,
958+ "comment_id": 3650628850,
959+ "created_at": "2025-12-14T09:41:12Z",
960+ "repoId": 987670088,
961+ "pullRequestNo": 1628
962+ },
963+ {
964+ "name": "flatsponge",
965+ "id": 104839509,
966+ "comment_id": 3673002560,
967+ "created_at": "2025-12-19T01:11:45Z",
968+ "repoId": 987670088,
969+ "pullRequestNo": 1668
970+ },
971+ {
972+ "name": "jonhoo",
973+ "id": 176295,
974+ "comment_id": 3674853134,
975+ "created_at": "2025-12-19T12:14:08Z",
976+ "repoId": 987670088,
977+ "pullRequestNo": 1675
978+ },
979+ {
980+ "name": "Mr777x-enf",
981+ "id": 248610315,
982+ "comment_id": 3682737876,
983+ "created_at": "2025-12-22T16:07:47Z",
984+ "repoId": 987670088,
985+ "pullRequestNo": 1694
986+ },
987+ {
988+ "name": "yuguorui",
989+ "id": 6182414,
990+ "comment_id": 3687495909,
991+ "created_at": "2025-12-23T17:59:11Z",
992+ "repoId": 987670088,
993+ "pullRequestNo": 1709
994+ },
995+ {
996+ "name": "aeroxy",
997+ "id": 2761307,
998+ "comment_id": 3693734613,
999+ "created_at": "2025-12-27T06:01:58Z",
1000+ "repoId": 987670088,
1001+ "pullRequestNo": 1723
1002+ },
1003+ {
1004+ "name": "nikolayk812",
1005+ "id": 23297850,
1006+ "comment_id": 3704102069,
1007+ "created_at": "2026-01-01T21:00:07Z",
1008+ "repoId": 987670088,
1009+ "pullRequestNo": 1748
1010+ },
1011+ {
1012+ "name": "mohaanymo",
1013+ "id": 244024658,
1014+ "comment_id": 3725028621,
1015+ "created_at": "2026-01-08T18:01:11Z",
1016+ "repoId": 987670088,
1017+ "pullRequestNo": 1799
1018+ },
1019+ {
1020+ "name": "zyriab",
1021+ "id": 2111910,
1022+ "comment_id": 3725966281,
1023+ "created_at": "2026-01-08T21:44:05Z",
1024+ "repoId": 987670088,
1025+ "pullRequestNo": 1801
1026+ },
1027+ {
1028+ "name": "aleksclark",
1029+ "id": 607132,
1030+ "comment_id": 3729687747,
1031+ "created_at": "2026-01-09T16:28:21Z",
1032+ "repoId": 987670088,
1033+ "pullRequestNo": 1811
1034+ },
1035+ {
1036+ "name": "jeis4wpi",
1037+ "id": 42679190,
1038+ "comment_id": 3735501265,
1039+ "created_at": "2026-01-11T19:19:03Z",
1040+ "repoId": 987670088,
1041+ "pullRequestNo": 1827
1042+ },
1043+ {
1044+ "name": "uppet",
1045+ "id": 110209,
1046+ "comment_id": 3738688581,
1047+ "created_at": "2026-01-12T13:58:05Z",
1048+ "repoId": 987670088,
1049+ "pullRequestNo": 1830
1050+ },
1051+ {
1052+ "name": "andreasdotorg",
1053+ "id": 153248,
1054+ "comment_id": 3740767910,
1055+ "created_at": "2026-01-12T22:16:05Z",
1056+ "repoId": 987670088,
1057+ "pullRequestNo": 1841
1058+ },
1059+ {
1060+ "name": "kuxoapp",
1061+ "id": 254052994,
1062+ "comment_id": 3747622477,
1063+ "created_at": "2026-01-14T04:18:44Z",
1064+ "repoId": 987670088,
1065+ "pullRequestNo": 1864
1066+ },
1067+ {
1068+ "name": "mhpenta",
1069+ "id": 183146177,
1070+ "comment_id": 3749703014,
1071+ "created_at": "2026-01-14T14:02:04Z",
1072+ "repoId": 987670088,
1073+ "pullRequestNo": 1870
1074+ },
1075+ {
1076+ "name": "huaiyuWangh",
1077+ "id": 34158348,
1078+ "comment_id": 3785195950,
1079+ "created_at": "2026-01-22T15:58:33Z",
1080+ "repoId": 987670088,
1081+ "pullRequestNo": 1943
1082+ },
1083+ {
1084+ "name": "akitaonrails",
1085+ "id": 2840,
1086+ "comment_id": 3786408984,
1087+ "created_at": "2026-01-22T19:57:59Z",
1088+ "repoId": 987670088,
1089+ "pullRequestNo": 1945
1090+ },
1091+ {
1092+ "name": "mcowger",
1093+ "id": 1929548,
1094+ "comment_id": 3787591535,
1095+ "created_at": "2026-01-23T00:44:49Z",
1096+ "repoId": 987670088,
1097+ "pullRequestNo": 1950
1098+ },
1099+ {
1100+ "name": "jerilynzheng",
1101+ "id": 15837981,
1102+ "comment_id": 3788071777,
1103+ "created_at": "2026-01-23T04:00:52Z",
1104+ "repoId": 987670088,
1105+ "pullRequestNo": 1951
1106+ },
1107+ {
1108+ "name": "AnyCPU",
1109+ "id": 2059051,
1110+ "comment_id": 3791901071,
1111+ "created_at": "2026-01-23T19:14:55Z",
1112+ "repoId": 987670088,
1113+ "pullRequestNo": 1967
1114+ },
1115+ {
1116+ "name": "billycao",
1117+ "id": 543122,
1118+ "comment_id": 3793624061,
1119+ "created_at": "2026-01-24T03:06:50Z",
1120+ "repoId": 987670088,
1121+ "pullRequestNo": 1971
1122+ },
1123+ {
1124+ "name": "gdamjan",
1125+ "id": 81654,
1126+ "comment_id": 3795660594,
1127+ "created_at": "2026-01-24T22:42:46Z",
1128+ "repoId": 987670088,
1129+ "pullRequestNo": 1978
1130+ },
1131+ {
1132+ "name": "oug-t",
1133+ "id": 252025851,
1134+ "comment_id": 3811704206,
1135+ "created_at": "2026-01-28T14:42:29Z",
1136+ "repoId": 987670088,
1137+ "pullRequestNo": 2022
1138+ },
1139+ {
1140+ "name": "liannnix",
1141+ "id": 779758,
1142+ "comment_id": 3815867093,
1143+ "created_at": "2026-01-29T07:05:12Z",
1144+ "repoId": 987670088,
1145+ "pullRequestNo": 2043
1146+ },
1147+ {
1148+ "name": "bittoby",
1149+ "id": 218712309,
1150+ "comment_id": 3824931235,
1151+ "created_at": "2026-01-30T17:52:15Z",
1152+ "repoId": 987670088,
1153+ "pullRequestNo": 2065
1154+ },
1155+ {
1156+ "name": "ijt",
1157+ "id": 15530,
1158+ "comment_id": 3832667774,
1159+ "created_at": "2026-02-02T03:06:23Z",
1160+ "repoId": 987670088,
1161+ "pullRequestNo": 2080
1162+ },
1163+ {
1164+ "name": "khalilgharbaoui",
1165+ "id": 8024057,
1166+ "comment_id": 3832796060,
1167+ "created_at": "2026-02-02T04:04:04Z",
1168+ "repoId": 987670088,
1169+ "pullRequestNo": 2081
1170+ },
1171+ {
1172+ "name": "acmacalister",
1173+ "id": 1024755,
1174+ "comment_id": 3837172797,
1175+ "created_at": "2026-02-02T19:27:08Z",
1176+ "repoId": 987670088,
1177+ "pullRequestNo": 2095
1178+ },
1179+ {
1180+ "name": "zhiquanchi",
1181+ "id": 29973289,
1182+ "comment_id": 3845838711,
1183+ "created_at": "2026-02-04T07:39:06Z",
1184+ "repoId": 987670088,
1185+ "pullRequestNo": 2112
1186+ },
1187+ {
1188+ "name": "inquam",
1189+ "id": 1265038,
1190+ "comment_id": 3849304908,
1191+ "created_at": "2026-02-04T19:22:33Z",
1192+ "repoId": 987670088,
1193+ "pullRequestNo": 2124
1194+ },
1195+ {
1196+ "name": "nickgrim",
1197+ "id": 8376,
1198+ "comment_id": 3852565144,
1199+ "created_at": "2026-02-05T10:17:46Z",
1200+ "repoId": 987670088,
1201+ "pullRequestNo": 2131
1202+ },
1203+ {
1204+ "name": "francescoalemanno",
1205+ "id": 50984334,
1206+ "comment_id": 3858464719,
1207+ "created_at": "2026-02-06T07:16:50Z",
1208+ "repoId": 987670088,
1209+ "pullRequestNo": 2142
1210+ },
1211+ {
1212+ "name": "biisal",
1213+ "id": 153633053,
1214+ "comment_id": 3866503536,
1215+ "created_at": "2026-02-08T08:15:11Z",
1216+ "repoId": 987670088,
1217+ "pullRequestNo": 2164
1218+ },
1219+ {
1220+ "name": "mishudark",
1221+ "id": 211144,
1222+ "comment_id": 3866939317,
1223+ "created_at": "2026-02-08T10:27:09Z",
1224+ "repoId": 987670088,
1225+ "pullRequestNo": 2165
1226+ },
1227+ {
1228+ "name": "portertech",
1229+ "id": 149630,
1230+ "comment_id": 3878650318,
1231+ "created_at": "2026-02-10T15:39:14Z",
1232+ "repoId": 987670088,
1233+ "pullRequestNo": 2183
1234+ },
1235+ {
1236+ "name": "wallacegibbon",
1237+ "id": 22029486,
1238+ "comment_id": 3890517245,
1239+ "created_at": "2026-02-12T11:58:04Z",
1240+ "repoId": 987670088,
1241+ "pullRequestNo": 2203
1242+ },
1243+ {
1244+ "name": "PHPCraftdream",
1245+ "id": 14233546,
1246+ "comment_id": 3893502046,
1247+ "created_at": "2026-02-12T21:34:20Z",
1248+ "repoId": 987670088,
1249+ "pullRequestNo": 2212
1250+ },
1251+ {
1252+ "name": "maxbrunet",
1253+ "id": 32458727,
1254+ "comment_id": 3905030983,
1255+ "created_at": "2026-02-15T19:14:26Z",
1256+ "repoId": 987670088,
1257+ "pullRequestNo": 2229
1258+ },
1259+ {
1260+ "name": "0xarcher",
1261+ "id": 18182408,
1262+ "comment_id": 3907297580,
1263+ "created_at": "2026-02-16T09:16:57Z",
1264+ "repoId": 987670088,
1265+ "pullRequestNo": 2236
1266+ },
1267+ {
1268+ "name": "julienrbrt",
1269+ "id": 29894366,
1270+ "comment_id": 3920039276,
1271+ "created_at": "2026-02-18T10:37:53Z",
1272+ "repoId": 987670088,
1273+ "pullRequestNo": 2246
1274+ },
1275+ {
1276+ "name": "erikstmartin",
1277+ "id": 50041,
1278+ "comment_id": 3937646631,
1279+ "created_at": "2026-02-20T23:35:55Z",
1280+ "repoId": 987670088,
1281+ "pullRequestNo": 2274
1282+ },
1283+ {
1284+ "name": "Jaylonnet",
1285+ "id": 101283545,
1286+ "comment_id": 3944717192,
1287+ "created_at": "2026-02-23T13:12:50Z",
1288+ "repoId": 987670088,
1289+ "pullRequestNo": 2293
1290+ },
1291+ {
1292+ "name": "mavaa",
1293+ "id": 1224973,
1294+ "comment_id": 3966463081,
1295+ "created_at": "2026-02-26T12:56:51Z",
1296+ "repoId": 987670088,
1297+ "pullRequestNo": 2314
1298+ },
1299+ {
1300+ "name": "aisk",
1301+ "id": 699636,
1302+ "comment_id": 3968065934,
1303+ "created_at": "2026-02-26T17:23:44Z",
1304+ "repoId": 987670088,
1305+ "pullRequestNo": 2315
1306+ },
1307+ {
1308+ "name": "detro",
1309+ "id": 114508,
1310+ "comment_id": 3976601253,
1311+ "created_at": "2026-02-28T07:36:40Z",
1312+ "repoId": 987670088,
1313+ "pullRequestNo": 2326
1314+ },
1315+ {
1316+ "name": "taoeffect",
1317+ "id": 138706,
1318+ "comment_id": 3979067985,
1319+ "created_at": "2026-03-01T04:22:00Z",
1320+ "repoId": 987670088,
1321+ "pullRequestNo": 2333
1322+ },
1323+ {
1324+ "name": "vmfu",
1325+ "id": 80844805,
1326+ "comment_id": 3980616480,
1327+ "created_at": "2026-03-01T17:51:04Z",
1328+ "repoId": 987670088,
1329+ "pullRequestNo": 2337
1330+ },
1331+ {
1332+ "name": "ZeitbyteRepo",
1333+ "id": 187110998,
1334+ "comment_id": 4025287397,
1335+ "created_at": "2026-03-09T17:00:06Z",
1336+ "repoId": 987670088,
1337+ "pullRequestNo": 2390
1338+ },
1339+ {
1340+ "name": "seroperson",
1341+ "id": 3791221,
1342+ "comment_id": 4047392328,
1343+ "created_at": "2026-03-12T14:53:20Z",
1344+ "repoId": 987670088,
1345+ "pullRequestNo": 2401
1346+ },
1347+ {
1348+ "name": "xulongwu4",
1349+ "id": 16892446,
1350+ "comment_id": 4062024320,
1351+ "created_at": "2026-03-15T02:30:55Z",
1352+ "repoId": 987670088,
1353+ "pullRequestNo": 2410
1354+ },
1355+ {
1356+ "name": "nghiant03",
1357+ "id": 102637959,
1358+ "comment_id": 4077213520,
1359+ "created_at": "2026-03-17T18:41:50Z",
1360+ "repoId": 987670088,
1361+ "pullRequestNo": 2421
1362+ },
1363+ {
1364+ "name": "whatnick",
1365+ "id": 491396,
1366+ "comment_id": 4102155868,
1367+ "created_at": "2026-03-21T03:49:12Z",
1368+ "repoId": 987670088,
1369+ "pullRequestNo": 2449
1370+ },
1371+ {
1372+ "name": "Alex-wuhu",
1373+ "id": 57132813,
1374+ "comment_id": 4106451941,
1375+ "created_at": "2026-03-22T15:26:05Z",
1376+ "repoId": 987670088,
1377+ "pullRequestNo": 2454
1378+ },
1379+ {
1380+ "name": "hongquan",
1381+ "id": 314607,
1382+ "comment_id": 4112122644,
1383+ "created_at": "2026-03-23T16:51:09Z",
1384+ "repoId": 987670088,
1385+ "pullRequestNo": 2462
1386+ },
1387+ {
1388+ "name": "faelis",
1389+ "id": 91593249,
1390+ "comment_id": 4113326932,
1391+ "created_at": "2026-03-23T19:57:54Z",
1392+ "repoId": 987670088,
1393+ "pullRequestNo": 2465
1394+ },
1395+ {
1396+ "name": "UnderLotus",
1397+ "id": 84985759,
1398+ "comment_id": 4118727062,
1399+ "created_at": "2026-03-24T14:25:40Z",
1400+ "repoId": 987670088,
1401+ "pullRequestNo": 2475
1402+ },
1403+ {
1404+ "name": "malikwirin",
1405+ "id": 117918464,
1406+ "comment_id": 4119816035,
1407+ "created_at": "2026-03-24T16:51:44Z",
1408+ "repoId": 987670088,
1409+ "pullRequestNo": 2476
1410+ },
1411+ {
1412+ "name": "fuleinist",
1413+ "id": 1163738,
1414+ "comment_id": 4133146531,
1415+ "created_at": "2026-03-26T09:45:48Z",
1416+ "repoId": 987670088,
1417+ "pullRequestNo": 2492
1418+ },
1419+ {
1420+ "name": "iceymoss",
1421+ "id": 114280774,
1422+ "comment_id": 4134659508,
1423+ "created_at": "2026-03-26T13:13:25Z",
1424+ "repoId": 987670088,
1425+ "pullRequestNo": 2493
1426+ },
1427+ {
1428+ "name": "srivilliamsai",
1429+ "id": 191893106,
1430+ "comment_id": 4144200398,
1431+ "created_at": "2026-03-27T17:37:29Z",
1432+ "repoId": 987670088,
1433+ "pullRequestNo": 2511
1434+ },
1435+ {
1436+ "name": "Dexterity104",
1437+ "id": 173429049,
1438+ "comment_id": 4153067126,
1439+ "created_at": "2026-03-30T08:05:56Z",
1440+ "repoId": 987670088,
1441+ "pullRequestNo": 2525
1442+ },
1443+ {
1444+ "name": "majiayu000",
1445+ "id": 19658300,
1446+ "comment_id": 4160074332,
1447+ "created_at": "2026-03-31T05:44:38Z",
1448+ "repoId": 987670088,
1449+ "pullRequestNo": 2534
1450+ },
1451+ {
1452+ "name": "afsuyadi",
1453+ "id": 104284194,
1454+ "comment_id": 4160431726,
1455+ "created_at": "2026-03-31T07:10:20Z",
1456+ "repoId": 987670088,
1457+ "pullRequestNo": 2532
1458+ },
1459+ {
1460+ "name": "owldev127",
1461+ "id": 175169034,
1462+ "comment_id": 4161299761,
1463+ "created_at": "2026-03-31T09:44:52Z",
1464+ "repoId": 987670088,
1465+ "pullRequestNo": 2538
1466+ },
1467+ {
1468+ "name": "MrRolie",
1469+ "id": 80284543,
1470+ "comment_id": 4168509138,
1471+ "created_at": "2026-04-01T08:44:22Z",
1472+ "repoId": 987670088,
1473+ "pullRequestNo": 2544
1474+ },
1475+ {
1476+ "name": "Kartik33",
1477+ "id": 8198703,
1478+ "comment_id": 4181386196,
1479+ "created_at": "2026-04-03T02:02:31Z",
1480+ "repoId": 987670088,
1481+ "pullRequestNo": 2554
1482+ },
1483+ {
1484+ "name": "talha7k",
1485+ "id": 51679353,
1486+ "comment_id": 4182808517,
1487+ "created_at": "2026-04-03T09:56:29Z",
1488+ "repoId": 987670088,
1489+ "pullRequestNo": 2555
1490+ },
1491+ {
1492+ "name": "avianion",
1493+ "id": 37309215,
1494+ "comment_id": 4186934644,
1495+ "created_at": "2026-04-04T10:54:16Z",
1496+ "repoId": 987670088,
1497+ "pullRequestNo": 2557
1498+ },
1499+ {
1500+ "name": "shahidshabbir-se",
1501+ "id": 140221016,
1502+ "comment_id": 4191066791,
1503+ "created_at": "2026-04-06T08:11:08Z",
1504+ "repoId": 987670088,
1505+ "pullRequestNo": 2563
1506+ },
1507+ {
1508+ "name": "smlx",
1509+ "id": 861778,
1510+ "comment_id": 4200126763,
1511+ "created_at": "2026-04-07T15:22:15Z",
1512+ "repoId": 987670088,
1513+ "pullRequestNo": 2575
1514+ },
1515+ {
1516+ "name": "gurnben",
1517+ "id": 14117802,
1518+ "comment_id": 4216941498,
1519+ "created_at": "2026-04-09T19:22:39Z",
1520+ "repoId": 987670088,
1521+ "pullRequestNo": 2593
1522+ },
1523+ {
1524+ "name": "dshumphr",
1525+ "id": 9056521,
1526+ "comment_id": 4229412078,
1527+ "created_at": "2026-04-11T12:20:44Z",
1528+ "repoId": 987670088,
1529+ "pullRequestNo": 2601
1530+ },
1531+ {
1532+ "name": "bensantora",
1533+ "id": 274462811,
1534+ "comment_id": 4229507403,
1535+ "created_at": "2026-04-11T13:31:32Z",
1536+ "repoId": 987670088,
1537+ "pullRequestNo": 2602
1538+ },
1539+ {
1540+ "name": "ahostbr",
1541+ "id": 7461677,
1542+ "comment_id": 4231674482,
1543+ "created_at": "2026-04-12T14:14:41Z",
1544+ "repoId": 987670088,
1545+ "pullRequestNo": 2606
1546+ },
1547+ {
1548+ "name": "KimBioInfoStudio",
1549+ "id": 22641519,
1550+ "comment_id": 4244355652,
1551+ "created_at": "2026-04-14T13:43:55Z",
1552+ "repoId": 987670088,
1553+ "pullRequestNo": 2622
1554+ },
1555+ {
1556+ "name": "taigong12",
1557+ "id": 276221439,
1558+ "comment_id": 4259818851,
1559+ "created_at": "2026-04-16T11:50:25Z",
1560+ "repoId": 987670088,
1561+ "pullRequestNo": 2634
1562+ },
1563+ {
1564+ "name": "pi128",
1565+ "id": 77074839,
1566+ "comment_id": 4271523344,
1567+ "created_at": "2026-04-17T21:52:43Z",
1568+ "repoId": 987670088,
1569+ "pullRequestNo": 2643
1570+ },
1571+ {
1572+ "name": "enrell",
1573+ "id": 60587839,
1574+ "comment_id": 4272340887,
1575+ "created_at": "2026-04-18T01:47:04Z",
1576+ "repoId": 987670088,
1577+ "pullRequestNo": 2646
1578+ },
1579+ {
1580+ "name": "gavmor",
1581+ "id": 606529,
1582+ "comment_id": 4285449550,
1583+ "created_at": "2026-04-21T02:02:06Z",
1584+ "repoId": 987670088,
1585+ "pullRequestNo": 2612
1586+ },
1587+ {
1588+ "name": "axeprpr",
1589+ "id": 8937600,
1590+ "comment_id": 4293455788,
1591+ "created_at": "2026-04-22T04:15:18Z",
1592+ "repoId": 987670088,
1593+ "pullRequestNo": 2674
1594+ },
1595+ {
1596+ "name": "iuga",
1597+ "id": 1430179,
1598+ "comment_id": 4298985284,
1599+ "created_at": "2026-04-22T18:33:08Z",
1600+ "repoId": 987670088,
1601+ "pullRequestNo": 2681
1602+ },
1603+ {
1604+ "name": "ne275",
1605+ "id": 174412782,
1606+ "comment_id": 4303280163,
1607+ "created_at": "2026-04-23T09:29:30Z",
1608+ "repoId": 987670088,
1609+ "pullRequestNo": 2686
1610+ },
1611+ {
1612+ "name": "flynn-eye",
1613+ "id": 23251324,
1614+ "comment_id": 4304378619,
1615+ "created_at": "2026-04-23T12:33:57Z",
1616+ "repoId": 987670088,
1617+ "pullRequestNo": 2688
1618+ },
1619+ {
1620+ "name": "georgeglarson",
1621+ "id": 744063,
1622+ "comment_id": 4341592963,
1623+ "created_at": "2026-04-29T07:08:48Z",
1624+ "repoId": 987670088,
1625+ "pullRequestNo": 2749
1626+ },
1627+ {
1628+ "name": "vorticalbox",
1629+ "id": 10886065,
1630+ "comment_id": 4344669740,
1631+ "created_at": "2026-04-29T14:29:35Z",
1632+ "repoId": 987670088,
1633+ "pullRequestNo": 2751
1634+ },
1635+ {
1636+ "name": "lloydzhou",
1637+ "id": 1826685,
1638+ "comment_id": 4346011097,
1639+ "created_at": "2026-04-29T17:27:37Z",
1640+ "repoId": 987670088,
1641+ "pullRequestNo": 2752
1642+ },
1643+ {
1644+ "name": "carlosgrillet",
1645+ "id": 13719979,
1646+ "comment_id": 4351020450,
1647+ "created_at": "2026-04-30T08:48:52Z",
1648+ "repoId": 987670088,
1649+ "pullRequestNo": 2759
1650+ },
1651+ {
1652+ "name": "SAY-5",
1653+ "id": 240962040,
1654+ "comment_id": 4357189565,
1655+ "created_at": "2026-05-01T01:00:00Z",
1656+ "repoId": 987670088,
1657+ "pullRequestNo": 2691
1658+ },
1659+ {
1660+ "name": "mkaaad",
1661+ "id": 119158371,
1662+ "comment_id": 4358493210,
1663+ "created_at": "2026-05-01T08:25:06Z",
1664+ "repoId": 987670088,
1665+ "pullRequestNo": 2772
1666+ },
1667+ {
1668+ "name": "pragneshbagary",
1669+ "id": 41118746,
1670+ "comment_id": 4359152162,
1671+ "created_at": "2026-05-01T11:54:16Z",
1672+ "repoId": 987670088,
1673+ "pullRequestNo": 2773
1674+ },
1675+ {
1676+ "name": "somjik-api",
1677+ "id": 47082582,
1678+ "comment_id": 4364741275,
1679+ "created_at": "2026-05-02T21:17:55Z",
1680+ "repoId": 987670088,
1681+ "pullRequestNo": 2783
1682+ },
1683+ {
1684+ "name": "ilgax",
1685+ "id": 79969769,
1686+ "comment_id": 4367211073,
1687+ "created_at": "2026-05-03T21:25:46Z",
1688+ "repoId": 987670088,
1689+ "pullRequestNo": 2790
1690+ },
1691+ {
1692+ "name": "ardevd",
1693+ "id": 366855,
1694+ "comment_id": 4377260996,
1695+ "created_at": "2026-05-05T07:22:31Z",
1696+ "repoId": 987670088,
1697+ "pullRequestNo": 2801
1698+ },
1699+ {
1700+ "name": "yeonuk-hwang",
1701+ "id": 54208214,
1702+ "comment_id": 4407666773,
1703+ "created_at": "2026-05-08T15:33:03Z",
1704+ "repoId": 987670088,
1705+ "pullRequestNo": 2836
1706+ },
1707+ {
1708+ "name": "sven2718",
1709+ "id": 4741888,
1710+ "comment_id": 4410098922,
1711+ "created_at": "2026-05-08T21:47:18Z",
1712+ "repoId": 987670088,
1713+ "pullRequestNo": 2840
1714+ },
1715+ {
1716+ "name": "acheong08",
1717+ "id": 36258159,
1718+ "comment_id": 4410600427,
1719+ "created_at": "2026-05-08T23:37:33Z",
1720+ "repoId": 987670088,
1721+ "pullRequestNo": 2842
1722+ },
1723+ {
1724+ "name": "smeinecke",
1725+ "id": 7316652,
1726+ "comment_id": 4411012852,
1727+ "created_at": "2026-05-09T01:47:08Z",
1728+ "repoId": 987670088,
1729+ "pullRequestNo": 2844
1730+ },
1731+ {
1732+ "name": "jan-xyz",
1733+ "id": 5249233,
1734+ "comment_id": 4432309551,
1735+ "created_at": "2026-05-12T15:48:38Z",
1736+ "repoId": 987670088,
1737+ "pullRequestNo": 2886
1738+ },
1739+ {
1740+ "name": "johnjansen",
1741+ "id": 105938,
1742+ "comment_id": 4434007350,
1743+ "created_at": "2026-05-12T19:28:01Z",
1744+ "repoId": 987670088,
1745+ "pullRequestNo": 2887
1746+ },
1747+ {
1748+ "name": "pablodz",
1749+ "id": 28235457,
1750+ "comment_id": 4435307961,
1751+ "created_at": "2026-05-12T22:25:09Z",
1752+ "repoId": 987670088,
1753+ "pullRequestNo": 2892
1754+ },
1755+ {
1756+ "name": "akhenakh",
1757+ "id": 218430,
1758+ "comment_id": 4446905473,
1759+ "created_at": "2026-05-14T02:28:13Z",
1760+ "repoId": 987670088,
1761+ "pullRequestNo": 2912
1762+ },
1763+ {
1764+ "name": "leonardoaraujosantos",
1765+ "id": 898383,
1766+ "comment_id": 3166308642,
1767+ "created_at": "2025-08-08T01:40:17Z",
1768+ "repoId": 987670088,
1769+ "pullRequestNo": 644
1770+ },
1771+ {
1772+ "name": "yookibooki",
1773+ "id": 61198899,
1774+ "comment_id": 4459665029,
1775+ "created_at": "2026-05-15T12:16:26Z",
1776+ "repoId": 987670088,
1777+ "pullRequestNo": 2922
1778+ },
1779+ {
1780+ "name": "CatMe0w",
1781+ "id": 7774491,
1782+ "comment_id": 4461676513,
1783+ "created_at": "2026-05-15T16:58:04Z",
1784+ "repoId": 987670088,
1785+ "pullRequestNo": 2925
1786+ },
1787+ {
1788+ "name": "Broderick-Westrope",
1789+ "id": 55474351,
1790+ "comment_id": 4469173328,
1791+ "created_at": "2026-05-17T03:35:13Z",
1792+ "repoId": 987670088,
1793+ "pullRequestNo": 2937
1794+ },
1795+ {
1796+ "name": "processtrader",
1797+ "id": 232431073,
1798+ "comment_id": 4480941961,
1799+ "created_at": "2026-05-18T18:58:31Z",
1800+ "repoId": 987670088,
1801+ "pullRequestNo": 2950
1802+ },
1803+ {
1804+ "name": "dcu",
1805+ "id": 73729,
1806+ "comment_id": 4484181213,
1807+ "created_at": "2026-05-19T03:37:32Z",
1808+ "repoId": 987670088,
1809+ "pullRequestNo": 2954
1810+ },
1811+ {
1812+ "name": "mei2jun1",
1813+ "id": 285962643,
1814+ "comment_id": 4495440988,
1815+ "created_at": "2026-05-20T06:53:43Z",
1816+ "repoId": 987670088,
1817+ "pullRequestNo": 2964
1818+ },
1819+ {
1820+ "name": "g2mt",
1821+ "id": 166577174,
1822+ "comment_id": 4513096006,
1823+ "created_at": "2026-05-21T21:56:14Z",
1824+ "repoId": 987670088,
1825+ "pullRequestNo": 2979
1826+ },
1827+ {
1828+ "name": "Ricardo-M-L",
1829+ "id": 69202550,
1830+ "comment_id": 4514494248,
1831+ "created_at": "2026-05-22T02:37:08Z",
1832+ "repoId": 987670088,
1833+ "pullRequestNo": 2847
1834+ },
1835+ {
1836+ "name": "Muttaqin86",
1837+ "id": 69788027,
1838+ "comment_id": 4520181780,
1839+ "created_at": "2026-05-22T15:46:32Z",
1840+ "repoId": 987670088,
1841+ "pullRequestNo": 2984
1842+ },
1843+ {
1844+ "name": "officialasishkumar",
1845+ "id": 87874775,
1846+ "comment_id": 4527874300,
1847+ "created_at": "2026-05-24T08:44:14Z",
1848+ "repoId": 987670088,
1849+ "pullRequestNo": 2995
1850+ },
1851+ {
1852+ "name": "yhyu13",
1853+ "id": 19365678,
1854+ "comment_id": 4528076561,
1855+ "created_at": "2026-05-24T10:19:27Z",
1856+ "repoId": 987670088,
1857+ "pullRequestNo": 2996
1858+ },
1859+ {
1860+ "name": "xulongzhe",
1861+ "id": 10559793,
1862+ "comment_id": 4569454380,
1863+ "created_at": "2026-05-29T00:39:36Z",
1864+ "repoId": 987670088,
1865+ "pullRequestNo": 3036
1866+ },
1867+ {
1868+ "name": "ardi1s",
1869+ "id": 200318875,
1870+ "comment_id": 4589172224,
1871+ "created_at": "2026-06-01T02:48:53Z",
1872+ "repoId": 987670088,
1873+ "pullRequestNo": 3049
1874+ },
1875+ {
1876+ "name": "cak3ninja",
1877+ "id": 4338875,
1878+ "comment_id": 4596570813,
1879+ "created_at": "2026-06-01T21:14:16Z",
1880+ "repoId": 987670088,
1881+ "pullRequestNo": 3059
1882+ },
1883+ {
1884+ "name": "GroovyCarrot",
1885+ "id": 5589906,
1886+ "comment_id": 4623915928,
1887+ "created_at": "2026-06-04T16:01:30Z",
1888+ "repoId": 987670088,
1889+ "pullRequestNo": 3076
1890+ },
1891+ {
1892+ "name": "CnsMaple",
1893+ "id": 92523839,
1894+ "comment_id": 4628808493,
1895+ "created_at": "2026-06-05T06:24:00Z",
1896+ "repoId": 987670088,
1897+ "pullRequestNo": 3080
1898+ },
1899+ {
1900+ "name": "yuseferi",
1901+ "id": 1736832,
1902+ "comment_id": 4548802420,
1903+ "created_at": "2026-05-26T21:00:36Z",
1904+ "repoId": 987670088,
1905+ "pullRequestNo": 3019
1906+ },
1907+ {
1908+ "name": "gmit3",
1909+ "id": 26192089,
1910+ "comment_id": 4651029942,
1911+ "created_at": "2026-06-08T16:18:06Z",
1912+ "repoId": 987670088,
1913+ "pullRequestNo": 3096
1914+ },
1915+ {
1916+ "name": "brianjlandau",
1917+ "id": 3122,
1918+ "comment_id": 4654867087,
1919+ "created_at": "2026-06-09T00:37:02Z",
1920+ "repoId": 987670088,
1921+ "pullRequestNo": 3098
1922+ },
1923+ {
1924+ "name": "kypkk",
1925+ "id": 68454243,
1926+ "comment_id": 4687904764,
1927+ "created_at": "2026-06-12T05:55:06Z",
1928+ "repoId": 987670088,
1929+ "pullRequestNo": 3111
1930+ },
1931+ {
1932+ "name": "warmjademe",
1933+ "id": 257661268,
1934+ "comment_id": 4720070206,
1935+ "created_at": "2026-06-16T14:48:33Z",
1936+ "repoId": 987670088,
1937+ "pullRequestNo": 3131
1938+ },
1939+ {
1940+ "name": "warmjademe",
1941+ "id": 257661268,
1942+ "comment_id": 4720177856,
1943+ "created_at": "2026-06-16T14:58:33Z",
1944+ "repoId": 987670088,
1945+ "pullRequestNo": 3131
1946+ },
1947+ {
1948+ "name": "jialudev",
1949+ "id": 39230796,
1950+ "comment_id": 4725593255,
1951+ "created_at": "2026-06-17T03:26:00Z",
1952+ "repoId": 987670088,
1953+ "pullRequestNo": 3137
1954+ },
1955+ {
1956+ "name": "knight110001",
1957+ "id": 21118983,
1958+ "comment_id": 4741392218,
1959+ "created_at": "2026-06-18T11:16:02Z",
1960+ "repoId": 987670088,
1961+ "pullRequestNo": 3140
1962+ },
1963+ {
1964+ "name": "ken-jo",
1965+ "id": 42824840,
1966+ "comment_id": 4755333253,
1967+ "created_at": "2026-06-19T22:56:55Z",
1968+ "repoId": 987670088,
1969+ "pullRequestNo": 3158
1970+ },
1971+ {
1972+ "name": "xorangekiller",
1973+ "id": 5561926,
1974+ "comment_id": 4758885426,
1975+ "created_at": "2026-06-20T16:00:01Z",
1976+ "repoId": 987670088,
1977+ "pullRequestNo": 3163
1978+ },
1979+ {
1980+ "name": "sithglan",
1981+ "id": 1595655,
1982+ "comment_id": 4761251782,
1983+ "created_at": "2026-06-21T07:28:19Z",
1984+ "repoId": 987670088,
1985+ "pullRequestNo": 3168
1986+ },
1987+ {
1988+ "name": "macro-ss",
1989+ "id": 59944291,
1990+ "comment_id": 4729268228,
1991+ "created_at": "2026-06-17T11:09:03Z",
1992+ "repoId": 987670088,
1993+ "pullRequestNo": 3140
1994+ },
1995+ {
1996+ "name": "andrinoff",
1997+ "id": 175145001,
1998+ "comment_id": 4772633817,
1999+ "created_at": "2026-06-22T20:13:54Z",
2000+ "repoId": 987670088,
2001+ "pullRequestNo": 3184
2002+ },
2003+ {
2004+ "name": "calyptobai",
2005+ "id": 111788964,
2006+ "comment_id": 4774213287,
2007+ "created_at": "2026-06-22T23:56:09Z",
2008+ "repoId": 987670088,
2009+ "pullRequestNo": 3189
2010+ },
2011+ {
2012+ "name": "truffle-dev",
2013+ "id": 260125384,
2014+ "comment_id": 4783906418,
2015+ "created_at": "2026-06-23T22:07:28Z",
2016+ "repoId": 987670088,
2017+ "pullRequestNo": 3195
2018+ },
2019+ {
2020+ "name": "chardoncs",
2021+ "id": 44740171,
2022+ "comment_id": 4786221902,
2023+ "created_at": "2026-06-24T05:36:39Z",
2024+ "repoId": 987670088,
2025+ "pullRequestNo": 3197
2026+ },
2027+ {
2028+ "name": "notno",
2029+ "id": 3149184,
2030+ "comment_id": 4793889316,
2031+ "created_at": "2026-06-24T21:37:51Z",
2032+ "repoId": 987670088,
2033+ "pullRequestNo": 3202
2034+ },
2035+ {
2036+ "name": "vismaytiwari",
2037+ "id": 89745751,
2038+ "comment_id": 4797847556,
2039+ "created_at": "2026-06-25T09:38:55Z",
2040+ "repoId": 987670088,
2041+ "pullRequestNo": 3205
2042+ },
2043+ {
2044+ "name": "feizhuzheng",
2045+ "id": 130743669,
2046+ "comment_id": 4809880810,
2047+ "created_at": "2026-06-26T13:09:43Z",
2048+ "repoId": 987670088,
2049+ "pullRequestNo": 3211
2050+ },
2051+ {
2052+ "name": "syf2211",
2053+ "id": 132282304,
2054+ "comment_id": 4817246953,
2055+ "created_at": "2026-06-27T11:44:54Z",
2056+ "repoId": 987670088,
2057+ "pullRequestNo": 3221
2058+ },
2059+ {
2060+ "name": "EduardF1",
2061+ "id": 50618110,
2062+ "comment_id": 4818319813,
2063+ "created_at": "2026-06-27T14:15:50Z",
2064+ "repoId": 987670088,
2065+ "pullRequestNo": 3133
2066+ },
2067+ {
2068+ "name": "sablea",
2069+ "id": 52388727,
2070+ "comment_id": 4851979164,
2071+ "created_at": "2026-07-01T08:13:03Z",
2072+ "repoId": 987670088,
2073+ "pullRequestNo": 3235
2074+ },
2075+ {
2076+ "name": "Osamaali313",
2077+ "id": 86572800,
2078+ "comment_id": 4870561813,
2079+ "created_at": "2026-07-02T21:19:15Z",
2080+ "repoId": 987670088,
2081+ "pullRequestNo": 3244
2082+ },
2083+ {
2084+ "name": "lockp111",
2085+ "id": 28383475,
2086+ "comment_id": 4878248994,
2087+ "created_at": "2026-07-03T17:12:26Z",
2088+ "repoId": 987670088,
2089+ "pullRequestNo": 3247
2090+ },
2091+ {
2092+ "name": "TheRAWagent",
2093+ "id": 77039476,
2094+ "comment_id": 4879276761,
2095+ "created_at": "2026-07-03T20:52:00Z",
2096+ "repoId": 987670088,
2097+ "pullRequestNo": 3251
7302098 }
7312099 ]
7322100}
.github/dependabot.yml+1
@@ -24,6 +24,7 @@ updates:
2424 - dependency-name: github.com/charmbracelet/lipgloss/v2
2525 versions:
2626 - v2.0.0-beta1
27+ - dependency-name: mvdan.cc/sh/moreinterp
2728
2829 - package-ecosystem: "github-actions"
2930 directory: "/"
.github/labeler.yml+14
@@ -3,6 +3,10 @@
33
44"area: ci":
55 - "/^ci: /i"
6+"area: crush run":
7+ - "/crush run/i"
8+ - "/headless/i"
9+ - "/non-interactive/i"
610"area: diff":
711 - "/diff/i"
812"area: docs":
@@ -41,16 +45,24 @@
4145 - "/(panic|crash|segfault)/i"
4246"provider: anthropic claude":
4347 - "/(anthropic|claude)/i"
48+"provider: avian":
49+ - "/avian/i"
4450"provider: aws bedrock":
4551 - "/(aws|bedrock)/i"
4652"provider: azure":
4753 - "/azure/i"
54+"provider: github copilot":
55+ - "/copilot/i"
4856"provider: google gemini":
4957 - "/gemini/i"
5058"provider: google vertex":
5159 - "/vertex/i"
60+"provider: hyper":
61+ - "/hyper/i"
5262"provider: kimi":
5363 - "/kimi/i"
64+"provider: minimax":
65+ - "/minimax/i"
5466"provider: ollama":
5567 - "/llama/i"
5668"provider: openai chatgpt":
@@ -59,6 +71,8 @@
5971 - "/openrouter/i"
6072"provider: qwen":
6173 - "/qwen/i"
74+"provider: vercel":
75+ - "/vercel/i"
6276"provider: xai grok":
6377 - "/(xai|x\\.ai|grok)/i"
6478"security":
.github/workflows/build.yml+26−7
@@ -1,11 +1,30 @@
11name: build
2−on: [push, pull_request]
2+on:
3+ push:
4+ branches: [main]
5+ pull_request:
6+
7+permissions:
8+ contents: read
9+
10+concurrency:
11+ group: build-${{ github.event.pull_request.number || github.ref }}
12+ cancel-in-progress: true
313
414jobs:
515 build:
6− uses: charmbracelet/meta/.github/workflows/build.yml@main
7− with:
8− go-version: ""
9− go-version-file: ./go.mod
10− secrets:
11− gh_pat: "${{ secrets.PERSONAL_ACCESS_TOKEN }}"
16+ strategy:
17+ matrix:
18+ os: [ubuntu-latest, macos-latest, windows-latest]
19+ runs-on: ${{ matrix.os }}
20+ steps:
21+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
22+ with:
23+ persist-credentials: false
24+ - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
25+ with:
26+ go-version-file: go.mod
27+ - run: go mod tidy
28+ - run: git diff --exit-code
29+ - run: go build -race ./...
30+ - run: go test -race -failfast ./...
.github/workflows/cla.yml+2−2
@@ -22,14 +22,14 @@ jobs:
2222 github.event.comment.body == 'recheck' ||
2323 github.event.comment.body == 'I have read the Contributor License Agreement (CLA) and hereby sign the CLA.' ||
2424 github.event_name == 'pull_request_target'
25− uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1
25+ uses: contributor-assistant/github-action@58daaf842ac3e26d08c2bdf26770d6e9c5b965a9
2626 env:
2727 GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
2828 with:
2929 path-to-signatures: ".github/cla-signatures.json"
3030 path-to-document: "https://github.com/charmbracelet/crush/blob/main/CLA.md"
3131 branch: "main"
32− allowlist: charmcli,charmcrush,dependabot[bot]
32+ allowlist: charmcli,charmcrush,dependabot[bot],Copilot
3333 custom-pr-sign-comment: "I have read the Contributor License Agreement (CLA) and hereby sign the CLA."
3434 custom-notsigned-prcomment: "Thank you for your submission. We really appreciate it! Like many open-source projects, we ask that you sign our [Contributor License Agreement](https://github.com/charmbracelet/crush/blob/main/CLA.md) before we can accept your contribution. You can sign the CLA by just posting a Pull Request comment same as the below format."
3535 lock-pullrequest-aftermerge: false
.github/workflows/labeler.yml+1−1
@@ -14,6 +14,7 @@ on:
1414
1515permissions:
1616 issues: write
17+ pull-requests: write
1718 contents: read
1819
1920jobs:
@@ -26,5 +27,4 @@ jobs:
2627 enable-versioned-regex: 0
2728 include-title: 1
2829 include-body: 0
29− repo-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
3030 issue-number: ${{ github.event.inputs.issue-number || github.event.issue.number || github.event.pull_request.number }}
.github/workflows/lint.yml+2−1
@@ -1,6 +1,7 @@
11name: lint
22on:
33 push:
4+ branches: [main]
45 pull_request:
56
67jobs:
@@ -8,5 +9,5 @@ jobs:
89 uses: charmbracelet/meta/.github/workflows/lint.yml@main
910 with:
1011 golangci_path: .golangci.yml
11− golangci_version: v2.4
12+ golangci_version: v2.11
1213 timeout: 10m
.github/workflows/nightly.yml+1−1
@@ -11,7 +11,7 @@ jobs:
1111 outputs:
1212 should_run: ${{ steps.check.outputs.should_run }}
1313 steps:
14− - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
14+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1515 with:
1616 fetch-depth: 1
1717 - id: check
.github/workflows/release.yml+1−3
@@ -15,7 +15,7 @@ jobs:
1515 goreleaser:
1616 uses: charmbracelet/meta/.github/workflows/goreleaser.yml@main
1717 with:
18− go_version: "1.25"
18+ go_version: "1.26"
1919 macos_sign_entitlements: "./.github/entitlements.plist"
2020 secrets:
2121 docker_username: ${{ secrets.DOCKERHUB_USERNAME }}
@@ -25,8 +25,6 @@ jobs:
2525 fury_token: ${{ secrets.FURY_TOKEN }}
2626 nfpm_gpg_key: ${{ secrets.NFPM_GPG_KEY }}
2727 nfpm_passphrase: ${{ secrets.NFPM_PASSPHRASE }}
28− npm_token: ${{ secrets.NPM_TOKEN }}
29− snapcraft_token: ${{ secrets.SNAPCRAFT_TOKEN }}
3028 aur_key: ${{ secrets.AUR_KEY }}
3129 macos_sign_p12: ${{ secrets.MACOS_SIGN_P12 }}
3230 macos_sign_password: ${{ secrets.MACOS_SIGN_PASSWORD }}
.github/workflows/schema-update.yml+11−8
@@ -1,26 +1,29 @@
1−name: Update Schema
1+name: Update files
22
33on:
44 push:
55 branches: [main]
66 paths:
77 - "internal/config/**"
8+ - "internal/agent/hyper/**"
9+ workflow_dispatch:
810
911jobs:
1012 update-schema:
1113 runs-on: ubuntu-latest
1214 steps:
13− - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
15+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1416 with:
1517 token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
16− - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
18+ - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
1719 with:
1820 go-version-file: go.mod
1921 - run: go run . schema > ./schema.json
20− - uses: stefanzweifel/git-auto-commit-action@28e16e81777b558cc906c8750092100bbb34c5e3 # v5
22+ - run: go generate ./internal/agent/hyper/...
23+ - uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v5
2124 with:
22− commit_message: "chore: auto-update generated files"
25+ commit_message: "chore: auto-update files"
2326 branch: main
24− commit_user_name: actions-user
25− commit_user_email: actions@github.com
26− commit_author: actions-user <actions@github.com>
27+ commit_user_name: Charm
28+ commit_user_email: 124303983+charmcli@users.noreply.github.com
29+ commit_author: Charm <124303983+charmcli@users.noreply.github.com>
.github/workflows/security.ymlnew file+92
@@ -0,0 +1,92 @@
1+name: "security"
2+
3+on:
4+ pull_request:
5+ push:
6+ branches: [main]
7+ schedule:
8+ - cron: "0 2 * * *"
9+
10+permissions:
11+ contents: read
12+
13+concurrency:
14+ group: security-${{ github.event.pull_request.number || github.ref }}
15+ cancel-in-progress: true
16+
17+jobs:
18+ codeql:
19+ runs-on: ubuntu-latest
20+ strategy:
21+ fail-fast: false
22+ matrix:
23+ language: ["go", "actions"]
24+ permissions:
25+ actions: read
26+ contents: read
27+ pull-requests: read
28+ security-events: write
29+ steps:
30+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
31+ with:
32+ persist-credentials: false
33+ - uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
34+ with:
35+ languages: ${{ matrix.language }}
36+ - uses: github/codeql-action/autobuild@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
37+ - uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
38+
39+ grype:
40+ runs-on: ubuntu-latest
41+ permissions:
42+ security-events: write
43+ actions: read
44+ contents: read
45+ steps:
46+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
47+ with:
48+ persist-credentials: false
49+ - uses: anchore/scan-action@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2 # v7.4.0
50+ id: scan
51+ with:
52+ path: "."
53+ fail-build: true
54+ severity-cutoff: critical
55+ - uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
56+ with:
57+ sarif_file: ${{ steps.scan.outputs.sarif }}
58+
59+ govulncheck:
60+ runs-on: ubuntu-latest
61+ permissions:
62+ security-events: write
63+ contents: read
64+ steps:
65+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
66+ with:
67+ persist-credentials: false
68+ - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
69+ with:
70+ go-version: stable
71+ - name: Install govulncheck
72+ run: go install golang.org/x/vuln/cmd/govulncheck@latest
73+ - name: Run govulncheck
74+ run: |
75+ govulncheck -C . -format sarif ./... > results.sarif
76+ - uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
77+ with:
78+ sarif_file: results.sarif
79+
80+ dependency-review:
81+ runs-on: ubuntu-latest
82+ if: github.event_name == 'pull_request'
83+ permissions:
84+ contents: read
85+ steps:
86+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
87+ with:
88+ persist-credentials: false
89+ - uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
90+ with:
91+ fail-on-severity: critical
92+ allow-licenses: BSD-2-Clause, BSD-3-Clause, MIT, MIT-0, Apache-2.0, MPL-2.0, ISC, LicenseRef-scancode-google-patent-license-golang, Unlicense
.github/workflows/snapshot.ymlnew file+34
@@ -0,0 +1,34 @@
1+name: snapshot
2+
3+on:
4+ push:
5+ branches:
6+ - main
7+
8+permissions:
9+ contents: read
10+
11+concurrency:
12+ group: snapshot-${{ github.ref }}
13+ cancel-in-progress: true
14+
15+jobs:
16+ snapshot:
17+ runs-on:
18+ # Use our own large runners with more CPU and RAM for faster builds
19+ group: releasers
20+ steps:
21+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
22+ with:
23+ fetch-depth: 0
24+ persist-credentials: false
25+ - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
26+ with:
27+ go-version-file: go.mod
28+ - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
29+ with:
30+ version: "nightly"
31+ distribution: goreleaser-pro
32+ args: build --snapshot --clean
33+ env:
34+ GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
.gitignore+7−2
@@ -42,11 +42,16 @@ Thumbs.db
4242.env
4343.env.local
4444
45+# Nix/direnv
46+.direnv/
47+/result
48+
4549**/.crush/**
4650
4751/crush
52+/tmp/
4853
4954manpages/
50−completions/
51−!internal/tui/components/completions/
55+completions/crush.*sh
5256.prettierignore
57+.task
.golangci.yml+16−4
@@ -2,6 +2,7 @@ version: "2"
22linters:
33 enable:
44 - bodyclose
5+ - errcheck
56 # - exhaustive
67 # - goconst
78 # - godot
@@ -9,6 +10,7 @@ linters:
910 # - gomoddirectives
1011 - goprintffuncname
1112 # - gosec
13+ - ineffassign
1214 - misspell
1315 # - nakedret
1416 # - nestif
@@ -23,20 +25,30 @@ linters:
2325 - tparallel
2426 # - unconvert
2527 # - unparam
28+ - unused
2629 - whitespace
2730 # - wrapcheck
28− disable:
29− - errcheck
30− - ineffassign
31− - unused
3231 exclusions:
3332 generated: lax
3433 presets:
3534 - common-false-positives
35+ # Ignores the idiomatic-to-drop error family (*Close, *Flush,
36+ # Fprint*, os.Remove/RemoveAll, os.Setenv, stdout/stderr writes) so
37+ # errcheck only flags genuinely meaningful dropped errors.
38+ - std-error-handling
3639 rules:
40+ # Dropped errors in tests (setup writes, httptest encoders) are
41+ # low-signal — test failures surface them anyway.
42+ - path: _test\.go
43+ linters:
44+ - errcheck
3745 - text: '(slog|log)\.\w+'
3846 linters:
3947 - noctx
48+ - path: internal/shell/run.go
49+ text: "SA1019.*interp.ExecHandler"
50+ linters:
51+ - staticcheck
4052issues:
4153 max-issues-per-linter: 0
4254 max-same-issues: 0
.goreleaser.yml+22−6
@@ -98,6 +98,7 @@ checksum:
9898
9999aur_sources:
100100 - private_key: "{{ .Env.AUR_KEY }}"
101+ disable: "{{ with .Prerelease }}true{{ end }}"
101102 git_url: "ssh://aur@aur.archlinux.org/crush.git"
102103 commit_author:
103104 name: "Charm"
@@ -115,7 +116,7 @@ aur_sources:
115116 export CGO_CXXFLAGS="${CXXFLAGS}"
116117 export CGO_LDFLAGS="${LDFLAGS}"
117118 export GOFLAGS="-buildmode=pie -trimpath -mod=readonly -modcacherw"
118− go build -ldflags="-w -s -buildid='' -linkmode=external -X main.version=v${pkgver}" .
119+ go build -ldflags="-w -s -buildid='' -linkmode=external -X github.com/charmbracelet/crush/internal/version.Version=v${pkgver}" .
119120 ./crush completion bash >./completions/crush.bash
120121 ./crush completion zsh >./completions/crush.zsh
121122 ./crush completion fish >./completions/crush.fish
@@ -141,6 +142,7 @@ aur_sources:
141142
142143aurs:
143144 - private_key: "{{ .Env.AUR_KEY }}"
145+ disable: "{{ with .Prerelease }}true{{ end }}"
144146 git_url: "ssh://aur@aur.archlinux.org/crush-bin.git"
145147 commit_author:
146148 name: "Charm"
@@ -150,7 +152,14 @@ aurs:
150152 conflicts:
151153 - crush
152154 package: |-
153− cd "${srcdir}/crush_${pkgver}_Linux_${CARCH}"
155+ case "$CARCH" in
156+ aarch64)
157+ cd "${srcdir}/crush_${pkgver}_Linux_arm64"
158+ ;;
159+ *)
160+ cd "${srcdir}/crush_${pkgver}_Linux_${CARCH}"
161+ ;;
162+ esac
154163 # bin
155164 install -Dm755 "./crush" "${pkgdir}/usr/bin/crush"
156165 # license
@@ -170,7 +179,7 @@ aurs:
170179 install -Dm644 README* "${pkgdir}/usr/share/doc/crush/"
171180
172181furies:
173− - disable: "{{ .IsNightly }}"
182+ - disable: "{{ if (or .Prerelease .IsNightly) }}true{{ end }}"
174183 account: "{{ with .Env.FURY_TOKEN }}charmcli{{ else }}{{ end }}"
175184 secret_name: FURY_TOKEN
176185
@@ -179,6 +188,7 @@ brews:
179188 owner: charmbracelet
180189 name: homebrew-tap
181190 token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
191+ skip_upload: "{{ with .Prerelease }}true{{ end }}"
182192 commit_author:
183193 name: "Charm"
184194 email: "charmcli@users.noreply.github.com"
@@ -194,6 +204,7 @@ scoops:
194204 owner: charmbracelet
195205 name: scoop-bucket
196206 token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
207+ skip_upload: "{{ with .Prerelease }}true{{ end }}"
197208 commit_author:
198209 name: "Charm"
199210 email: "charmcli@users.noreply.github.com"
@@ -203,6 +214,7 @@ npms:
203214 repository: "git+https://github.com/charmbracelet/crush.git"
204215 bugs: https://github.com/charmbracelet/crush/issues
205216 access: public
217+ disable: "{{ with .Prerelease }}true{{ end }}"
206218
207219nfpms:
208220 - formats:
@@ -230,11 +242,10 @@ nfpms:
230242
231243signs:
232244 - cmd: cosign
233− certificate: "${artifact}.pem"
245+ signature: "${artifact}.sigstore.json"
234246 args:
235247 - sign-blob
236− - "--output-certificate=${certificate}"
237− - "--output-signature=${signature}"
248+ - "--bundle=${signature}"
238249 - "${artifact}"
239250 - "--yes"
240251 artifacts: checksum
@@ -257,6 +268,8 @@ nix:
257268 name: "Charm"
258269 email: "charmcli@users.noreply.github.com"
259270 license: fsl11Mit
271+ formatter: nixfmt
272+ skip_upload: "{{ with .Prerelease }}true{{ end }}"
260273 extra_install: |-
261274 installManPage ./manpages/crush.1.gz
262275 installShellCompletion ./completions/*
@@ -267,6 +280,7 @@ winget:
267280 publisher_url: https://charm.land
268281 release_notes_url: "https://github.com/charmbracelet/crush/releases/tag/{{.Tag}}"
269282 license_url: https://github.com/charmbracelet/crush/blob/main/LICENSE.md
283+ skip_upload: "{{ with .Prerelease }}true{{ end }}"
270284 commit_author:
271285 name: "Charm"
272286 email: "charmcli@users.noreply.github.com"
@@ -283,6 +297,8 @@ winget:
283297 owner: microsoft
284298 name: winget-pkgs
285299 branch: master
300+ body: |
301+ /cc @andreynering
286302
287303changelog:
288304 sort: asc
AGENTS.mdnew file+223
@@ -0,0 +1,223 @@
1+# Crush Development Guide
2+
3+## Project Overview
4+
5+Crush is a terminal-based AI coding assistant built in Go by
6+[Charm](https://charm.land). It connects to LLMs and gives them tools to read,
7+write, and execute code. It supports multiple providers (Anthropic, OpenAI,
8+Gemini, Bedrock, Copilot, Hyper, MiniMax, Vercel, and more), integrates with
9+LSPs for code intelligence, and supports extensibility via MCP servers and
10+agent skills.
11+
12+The module path is `github.com/charmbracelet/crush`.
13+
14+## Architecture
15+
16+```
17+main.go CLI entry point (cobra via internal/cmd)
18+internal/
19+ app/app.go Top-level wiring: DB, config, agents, LSP, MCP, events
20+ cmd/ CLI commands (root, run, login, models, stats, sessions)
21+ config/
22+ config.go Config struct, context file paths, agent definitions
23+ load.go crush.json loading and validation
24+ provider.go Provider configuration and model resolution
25+ agent/
26+ agent.go SessionAgent: runs LLM conversations per session
27+ coordinator.go Coordinator: manages named agents ("coder", "task")
28+ hooked_tool.go Decorator that runs PreToolUse hooks before tool execution
29+ prompts.go Loads Go-template system prompts
30+ templates/ System prompt templates (coder.md.tpl, task.md.tpl, etc.)
31+ tools/ All built-in tools (bash, edit, view, grep, glob, etc.)
32+ mcp/ MCP client integration
33+ hooks/ Hook engine: runs user shell commands on hook events
34+ hooks.go Decision types, aggregation logic, event constants
35+ runner.go Parallel hook execution, timeout, dedup
36+ input.go Stdin payload builder, env vars, stdout parsing (Crush + Claude Code compat)
37+ session/session.go Session CRUD backed by SQLite
38+ message/ Message model and content types
39+ db/ SQLite via sqlc, with migrations
40+ sql/ Raw SQL queries (consumed by sqlc)
41+ migrations/ Schema migrations
42+ lsp/ LSP client manager, auto-discovery, on-demand startup
43+ ui/ Bubble Tea v2 TUI (see internal/ui/AGENTS.md)
44+ permission/ Tool permission checking and allow-lists
45+ skills/ Skill file discovery and loading
46+ shell/ Bash command execution with background job support
47+ event/ Telemetry (PostHog)
48+ pubsub/ Internal pub/sub for cross-component messaging
49+ filetracker/ Tracks files touched per session
50+ history/ Prompt history
51+```
52+
53+### Key Dependency Roles
54+
55+- **`charm.land/fantasy`**: LLM provider abstraction layer. Handles protocol
56+ differences between Anthropic, OpenAI, Gemini, etc. Used in `internal/app`
57+ and `internal/agent`.
58+- **`charm.land/bubbletea/v2`**: TUI framework powering the interactive UI.
59+- **`charm.land/lipgloss/v2`**: Terminal styling.
60+- **`charm.land/glamour/v2`**: Markdown rendering in the terminal.
61+- **`charm.land/catwalk`**: Snapshot/golden-file testing for TUI components.
62+- **`sqlc`**: Generates Go code from SQL queries in `internal/db/sql/`.
63+
64+### Key Patterns
65+
66+- **Config is a Service**: accessed via `config.Service`, not global state.
67+- **Tools are self-documenting**: each tool has a `.go` implementation and a
68+ `.md` description file in `internal/agent/tools/`.
69+- **System prompts are Go templates**: `internal/agent/templates/*.md.tpl`
70+ with runtime data injected.
71+- **Context files**: Crush reads AGENTS.md, CRUSH.md, CLAUDE.md, GEMINI.md
72+ (and `.local` variants) from the working directory for project-specific
73+ instructions.
74+- **Persistence**: SQLite + sqlc. All queries live in `internal/db/sql/`,
75+ generated code in `internal/db/`. Migrations in `internal/db/migrations/`.
76+- **Pub/sub**: `internal/pubsub` for decoupled communication between agent,
77+ UI, and services.
78+- **Hooks**: User-defined shell commands in `crush.json` that fire before
79+ tool execution. The engine (`internal/hooks/`) is independent of fantasy
80+ and agent — it takes inputs, runs commands, returns decisions. The
81+ `hookedTool` decorator in `internal/agent/hooked_tool.go` wraps tools at
82+ the coordinator level. Hooks run before permission checks. See
83+ `HOOKS.md` for the user-facing protocol.
84+- **CGO disabled**: builds with `CGO_ENABLED=0` and
85+ `GOEXPERIMENT=greenteagc`.
86+
87+## Build/Test/Lint Commands
88+
89+- **Build**: `go build .` or `go run .`
90+- **Test**: `task test` or `go test ./...` (run single test:
91+ `go test ./internal/llm/prompt -run TestGetContextFromPaths`)
92+- **Update Golden Files**: `go test ./... -update` (regenerates `.golden`
93+ files when test output changes)
94+ - Update specific package:
95+ `go test ./internal/tui/components/core -update` (in this case,
96+ we're updating "core")
97+- **Lint**: `task lint:fix`
98+- **Format**: `task fmt` (`gofumpt -w .`)
99+- **Modernize**: `task modernize` (runs `modernize` which makes code
100+ simplifications)
101+- **Dev**: `task dev` (runs with profiling enabled)
102+
103+## Code Style Guidelines
104+
105+- **Imports**: Use `goimports` formatting, group stdlib, external, internal
106+ packages.
107+- **Formatting**: Use gofumpt (stricter than gofmt), enabled in
108+ golangci-lint.
109+- **Naming**: Standard Go conventions — PascalCase for exported, camelCase
110+ for unexported.
111+- **Types**: Prefer explicit types, use type aliases for clarity (e.g.,
112+ `type AgentName string`).
113+- **Error handling**: Return errors explicitly, use `fmt.Errorf` for
114+ wrapping.
115+- **Context**: Always pass `context.Context` as first parameter for
116+ operations.
117+- **Interfaces**: Define interfaces in consuming packages, keep them small
118+ and focused.
119+- **Structs**: Use struct embedding for composition, group related fields.
120+- **Constants**: Use typed constants with iota for enums, group in const
121+ blocks.
122+- **Testing**: Use testify's `require` package, parallel tests with
123+ `t.Parallel()`, `t.SetEnv()` to set environment variables. Always use
124+ `t.Tempdir()` when in need of a temporary directory. This directory does
125+ not need to be removed.
126+- **JSON tags**: Use snake_case for JSON field names.
127+- **File permissions**: Use octal notation (0o755, 0o644) for file
128+ permissions.
129+- **Log messages**: Log messages must start with a capital letter (e.g.,
130+ "Failed to save session" not "failed to save session").
131+ - This is enforced by `task lint:log` which runs as part of `task lint`.
132+- **Comments**: End comments in periods unless comments are at the end of the
133+ line.
134+
135+## Testing with Mock Providers
136+
137+When writing tests that involve provider configurations, use the mock
138+providers to avoid API calls:
139+
140+```go
141+func TestYourFunction(t *testing.T) {
142+ // Enable mock providers for testing
143+ originalUseMock := config.UseMockProviders
144+ config.UseMockProviders = true
145+ defer func() {
146+ config.UseMockProviders = originalUseMock
147+ config.ResetProviders()
148+ }()
149+
150+ // Reset providers to ensure fresh mock data
151+ config.ResetProviders()
152+
153+ // Your test code here - providers will now return mock data
154+ providers := config.Providers()
155+ // ... test logic
156+}
157+```
158+
159+## Formatting
160+
161+- ALWAYS format any Go code you write.
162+ - First, try `gofumpt -w .`.
163+ - If `gofumpt` is not available, use `goimports`.
164+ - If `goimports` is not available, use `gofmt`.
165+ - You can also use `task fmt` to run `gofumpt -w .` on the entire project,
166+ as long as `gofumpt` is on the `PATH`.
167+
168+## Comments
169+
170+- Comments that live on their own lines should start with capital letters and
171+ end with periods. Wrap comments at 78 columns.
172+
173+## Committing
174+
175+- ALWAYS use semantic commits (`fix:`, `feat:`, `chore:`, `refactor:`,
176+ `docs:`, `sec:`, etc).
177+- Try to keep commits to one line, not including your attribution. Only use
178+ multi-line commits when additional context is truly necessary.
179+
180+## Working on the TUI (UI)
181+
182+Anytime you need to work on the TUI, read `internal/ui/AGENTS.md` before
183+starting work.
184+
185+## Styling System
186+
187+The styling system lives in `internal/ui/styles/` and is organized into
188+three layers:
189+
190+- **`quickstyle.go`**: The stable base theme builder. `quickStyle(opts)`
191+ constructs a `Styles` struct from `quickStyleOpts` — a palette of
192+ design tokens (primary, secondary, fgBase, bgBase, success, error, etc.).
193+ `quickStyle` must be fully token-driven: never hardcode specific
194+ `charmtone.*` colors here (except Chroma syntax highlighting, which is
195+ pending tokenization). This lets any theme reuse the base without
196+ inheriting Charmtone-specific colors.
197+- **`themes.go`**: Defines concrete themes. Each theme function (e.g.
198+ `CharmtonePantera`) calls `quickStyle` with its palette, then applies
199+ theme-specific overrides as needed.
200+- **`styles.go`**: Defines the `Styles` struct and its documentation —
201+ the shape of what `quickStyle` produces.
202+
203+**Adding theme-specific overrides**: When a style genuinely needs a
204+color that doesn't fit the token model (e.g. the bang prompt uses
205+Salt/Hazy/Larple), keep `quickStyle` on the closest semantic token and
206+override only the differing colors in the theme function:
207+
208+```go
209+func CharmtonePantera() Styles {
210+ s := quickStyle(quickStyleOpts{ /* palette */ })
211+
212+ // Override only the colors that differ from the token defaults.
213+ s.Editor.PromptBangIconFocused = s.Editor.PromptBangIconFocused.
214+ Foreground(charmtone.Salt).
215+ Background(charmtone.Hazy)
216+
217+ return s
218+}
219+```
220+
221+**Adding a new theme**: Add a function in `themes.go` that returns the
222+result of `quickStyle` with a `quickStyleOpts` palette (plus any needed
223+overrides), then wire it into `ThemeForProvider`.
CRUSH.mddeleted−65
@@ -1,65 +0,0 @@
1−# Crush Development Guide
2−
3−## Build/Test/Lint Commands
4−
5−- **Build**: `go build .` or `go run .`
6−- **Test**: `task test` or `go test ./...` (run single test: `go test ./internal/llm/prompt -run TestGetContextFromPaths`)
7−- **Update Golden Files**: `go test ./... -update` (regenerates .golden files when test output changes)
8− - Update specific package: `go test ./internal/tui/components/core -update` (in this case, we're updating "core")
9−- **Lint**: `task lint:fix`
10−- **Format**: `task fmt` (gofumpt -w .)
11−- **Dev**: `task dev` (runs with profiling enabled)
12−
13−## Code Style Guidelines
14−
15−- **Imports**: Use goimports formatting, group stdlib, external, internal packages
16−- **Formatting**: Use gofumpt (stricter than gofmt), enabled in golangci-lint
17−- **Naming**: Standard Go conventions - PascalCase for exported, camelCase for unexported
18−- **Types**: Prefer explicit types, use type aliases for clarity (e.g., `type AgentName string`)
19−- **Error handling**: Return errors explicitly, use `fmt.Errorf` for wrapping
20−- **Context**: Always pass context.Context as first parameter for operations
21−- **Interfaces**: Define interfaces in consuming packages, keep them small and focused
22−- **Structs**: Use struct embedding for composition, group related fields
23−- **Constants**: Use typed constants with iota for enums, group in const blocks
24−- **Testing**: Use testify's `require` package, parallel tests with `t.Parallel()`,
25− `t.SetEnv()` to set environment variables. Always use `t.Tempdir()` when in
26− need of a temporary directory. This directory does not need to be removed.
27−- **JSON tags**: Use snake_case for JSON field names
28−- **File permissions**: Use octal notation (0o755, 0o644) for file permissions
29−- **Comments**: End comments in periods unless comments are at the end of the line.
30−
31−## Testing with Mock Providers
32−
33−When writing tests that involve provider configurations, use the mock providers to avoid API calls:
34−
35−```go
36−func TestYourFunction(t *testing.T) {
37− // Enable mock providers for testing
38− originalUseMock := config.UseMockProviders
39− config.UseMockProviders = true
40− defer func() {
41− config.UseMockProviders = originalUseMock
42− config.ResetProviders()
43− }()
44−
45− // Reset providers to ensure fresh mock data
46− config.ResetProviders()
47−
48− // Your test code here - providers will now return mock data
49− providers := config.Providers()
50− // ... test logic
51−}
52−```
53−
54−## Formatting
55−
56−- ALWAYS format any Go code you write.
57− - First, try `gofumpt -w .`.
58− - If `gofumpt` is not available, use `goimports`.
59− - If `goimports` is not available, use `gofmt`.
60− - You can also use `task fmt` to run `gofumpt -w .` on the entire project,
61− as long as `gofumpt` is on the `PATH`.
62−
63−## Committing
64−
65−- ALWAYS use semantic commits (`fix:`, `feat:`, `chore:`, `refactor:`, `docs:`, `sec:`, etc).
LICENSE.md+1−1
@@ -6,7 +6,7 @@ FSL-1.1-MIT
66
77## Notice
88
9−Copyright 2025 Charmbracelet, Inc
9+Copyright 2025-2026 Charmbracelet, Inc.
1010
1111## Terms and Conditions
1212
README.md+399−76
@@ -1,13 +1,16 @@
11# Crush
22
3+> [!NOTE]
4+> This is a personal fork of [charmbracelet/crush](https://github.com/charmbracelet/crush) with UI/UX tweaks and performance improvements.
5+
36<p align="center">
4− <a href="https://stuff.charm.sh/crush/charm-crush.png"><img width="450" alt="Charm Crush Logo" src="https://github.com/user-attachments/assets/adc1a6f4-b284-4603-836c-59038caa2e8b" /></a><br />
7+ <a href="https://stuff.charm.sh/crush/charm-crush.png"><img width="450" alt="Charm Crush Logo" src="https://github.com/user-attachments/assets/cf8ca3ce-8b02-43f0-9d0f-5a331488da4b" /></a><br />
58 <a href="https://github.com/charmbracelet/crush/releases"><img src="https://img.shields.io/github/release/charmbracelet/crush" alt="Latest Release"></a>
69 <a href="https://github.com/charmbracelet/crush/actions"><img src="https://github.com/charmbracelet/crush/actions/workflows/build.yml/badge.svg" alt="Build Status"></a>
710</p>
811
912<p align="center">Your new coding bestie, now available in your favourite terminal.<br />Your tools, your code, and your workflows, wired into your LLM of choice.</p>
10−<p align="center">你的新编程伙伴,现在就在你最爱的终端中。<br />你的工具、代码和工作流,都与您选择的 LLM 模型紧密相连。</p>
13+<p align="center">终端里的编程新搭档,<br />无缝接入你的工具、代码与工作流,全面兼容主流 LLM 模型。</p>
1114
1215<p align="center"><img width="800" alt="Crush Demo" src="https://github.com/user-attachments/assets/58280caf-851b-470a-b6f7-d5c4ea8a1968" /></p>
1316
@@ -18,7 +21,8 @@
1821- **Session-Based:** maintain multiple work sessions and contexts per project
1922- **LSP-Enhanced:** Crush uses LSPs for additional context, just like you do
2023- **Extensible:** add capabilities via MCPs (`http`, `stdio`, and `sse`)
21−- **Works Everywhere:** first-class support in every terminal on macOS, Linux, Windows (PowerShell and WSL), FreeBSD, OpenBSD, and NetBSD
24+- **Works Everywhere:** first-class support in every terminal on macOS, Linux, Windows (PowerShell and WSL), Android, FreeBSD, OpenBSD, and NetBSD
25+- **Industrial Grade:** built on the Charm ecosystem, powering 25k+ applications, from leading open source projects to business-critical infrastructure
2226
2327## Installation
2428
@@ -36,6 +40,9 @@ yay -S crush-bin
3640
3741# Nix
3842nix run github:numtide/nix-ai-tools#crush
43+
44+# FreeBSD
45+pkg install crush
3946```
4047
4148Windows users:
@@ -52,9 +59,9 @@ scoop install crush
5259<details>
5360<summary><strong>Nix (NUR)</strong></summary>
5461
55−Crush is available via [NUR](https://github.com/nix-community/NUR) in `nur.repos.charmbracelet.crush`.
62+Crush is available via the official Charm [NUR](https://github.com/nix-community/NUR) in `nur.repos.charmbracelet.crush`, which is the most up-to-date way to get Crush in Nix.
5663
57−You can also try out Crush via `nix-shell`:
64+You can also try out Crush via the NUR with `nix-shell`:
5865
5966```bash
6067# Add the NUR channel.
@@ -165,35 +172,56 @@ go install github.com/charmbracelet/crush@latest
165172> [!WARNING]
166173> Productivity may increase when using Crush and you may find yourself nerd
167174> sniped when first using the application. If the symptoms persist, join the
168−> [Discord][discord] and nerd snipe the rest of us.
175+> [Slack][slack] or [Discord][discord] and nerd snipe the rest of us.
169176
170177## Getting Started
171178
172179The quickest way to get started is to grab an API key for your preferred
173−provider such as Anthropic, OpenAI, Groq, or OpenRouter and just start
180+provider such as Anthropic, OpenAI, Groq, OpenRouter, or Vercel AI Gateway and just start
174181Crush. You'll be prompted to enter your API key.
175182
176183That said, you can also set environment variables for preferred providers.
177184
178185| Environment Variable | Provider |
179186| --------------------------- | -------------------------------------------------- |
187+| `HYPER_API_KEY` | Charm Hyper |
180188| `ANTHROPIC_API_KEY` | Anthropic |
181189| `OPENAI_API_KEY` | OpenAI |
182−| `OPENROUTER_API_KEY` | OpenRouter |
190+| `VERCEL_API_KEY` | Vercel AI Gateway |
183191| `GEMINI_API_KEY` | Google Gemini |
192+| `SYNTHETIC_API_KEY` | Synthetic |
193+| `ZAI_API_KEY` | Z.ai |
194+| `MINIMAX_API_KEY` | MiniMax |
195+| `HF_TOKEN` | Hugging Face Inference |
184196| `CEREBRAS_API_KEY` | Cerebras |
185−| `HF_TOKEN` | Huggingface Inference |
197+| `OPENROUTER_API_KEY` | OpenRouter |
198+| `IONET_API_KEY` | io.net |
199+| `ALIBABA_SINGAPORE_API_KEY` | Alibaba (Singapore) |
200+| `ALIBABA_US_API_KEY` | Alibaba (United States) |
201+| `GROQ_API_KEY` | Groq |
202+| `AVIAN_API_KEY` | Avian |
203+| `OPENCODE_API_KEY` | OpenCode Zen & Go |
186204| `VERTEXAI_PROJECT` | Google Cloud VertexAI (Gemini) |
187205| `VERTEXAI_LOCATION` | Google Cloud VertexAI (Gemini) |
188−| `GROQ_API_KEY` | Groq |
189−| `AWS_ACCESS_KEY_ID` | AWS Bedrock (Claude) |
190−| `AWS_SECRET_ACCESS_KEY` | AWS Bedrock (Claude) |
191−| `AWS_REGION` | AWS Bedrock (Claude) |
192−| `AWS_PROFILE` | AWS Bedrock (Custom Profile) |
193−| `AWS_BEARER_TOKEN_BEDROCK` | AWS Bedrock |
206+| `AWS_ACCESS_KEY_ID` | Amazon Bedrock (Claude) |
207+| `AWS_SECRET_ACCESS_KEY` | Amazon Bedrock (Claude) |
208+| `AWS_REGION` | Amazon Bedrock (Claude) |
209+| `AWS_PROFILE` | Amazon Bedrock (Custom Profile) |
210+| `AWS_BEARER_TOKEN_BEDROCK` | Amazon Bedrock |
194211| `AZURE_OPENAI_API_ENDPOINT` | Azure OpenAI models |
195212| `AZURE_OPENAI_API_KEY` | Azure OpenAI models (optional when using Entra ID) |
196213| `AZURE_OPENAI_API_VERSION` | Azure OpenAI models |
214+| `MOONSHOT_API_KEY` | Moonshot |
215+
216+### Subscriptions
217+
218+If you prefer subscription-based usage, here are some plans that work well in
219+Crush:
220+
221+- [Synthetic](https://synthetic.new/pricing)
222+- [GLM Coding Plan](https://z.ai/subscribe)
223+- [Kimi Code](https://www.kimi.com/membership/pricing)
224+- [MiniMax Coding Plan](https://platform.minimax.io/subscribe/coding-plan)
197225
198226### By the Way
199227
@@ -205,13 +233,17 @@ Crush’s default model listing is managed in [Catwalk](https://github.com/charm
205233
206234## Configuration
207235
236+> [!TIP]
237+> Crush ships with a builtin `crush-config` skill for configuring itself. In
238+> many cases you can simply ask Crush to configure itself.
239+
208240Crush runs great with no configuration. That said, if you do need or want to
209241customize Crush, configuration can be added either local to the project itself,
210242or globally, with the following priority:
211243
2122441. `.crush.json`
2132452. `crush.json`
214−3. `$HOME/.config/crush/crush.json` (Windows: `%USERPROFILE%\AppData\Local\crush\crush.json`)
246+3. `$HOME/.config/crush/crush.json`
215247
216248Configuration itself is stored as a JSON object:
217249
@@ -222,7 +254,8 @@ Configuration itself is stored as a JSON object:
222254}
223255```
224256
225−As an additional note, Crush also stores ephemeral data, such as application state, in one additional location:
257+As an additional note, Crush also stores ephemeral data, such as application
258+state, in one additional location:
226259
227260```bash
228261# Unix
@@ -232,6 +265,12 @@ $HOME/.local/share/crush/crush.json
232265%LOCALAPPDATA%\crush\crush.json
233266```
234267
268+> [!TIP]
269+> You can override the user and data config locations by setting:
270+>
271+> - `CRUSH_GLOBAL_CONFIG`
272+> - `CRUSH_GLOBAL_DATA`
273+
235274### LSPs
236275
237276Crush can use LSPs for additional context to help inform its decisions, just
@@ -260,10 +299,36 @@ like you would. LSPs can be added manually like so:
260299
261300### MCPs
262301
263−Crush also supports Model Context Protocol (MCP) servers through three
264−transport types: `stdio` for command-line servers, `http` for HTTP endpoints,
265−and `sse` for Server-Sent Events. Environment variable expansion is supported
266−using `$(echo $VAR)` syntax.
302+Crush also supports Model Context Protocol (MCP) servers through three transport
303+types: `stdio` for command-line servers, `http` for HTTP endpoints, and `sse`
304+for Server-Sent Events.
305+
306+Shell-style value expansion (`$VAR`, `${VAR:-default}`, `$(command)`, quoting,
307+nesting) works in `command`, `args`, `env`, `headers`, and `url`, so
308+file-based secrets work out of the box. You can use values like `"$TOKEN"`
309+or `"$(cat /path/to/secret/token)"`. Expansion runs through Crush's embedded
310+shell, so the same syntax works on every supported system, Windows included.
311+
312+Unset variables expand to the empty string by default, matching bash. For
313+required credentials, use `${VAR:?message}` so an unset variable fails loudly
314+at load time with `message` instead of silently resolving to empty:
315+
316+```json
317+{ "api_key": "${CODEBERG_TOKEN:?set CODEBERG_TOKEN}" }
318+```
319+
320+Headers (both MCP `headers` and provider `extra_headers`) whose value
321+resolves to the empty string are dropped from the outgoing request rather
322+than sent as `Header:`. That keeps optional env-gated headers like
323+`"OpenAI-Organization": "$OPENAI_ORG_ID"` clean when the variable is unset.
324+
325+Provider `extra_body` is a non-expanding JSON passthrough; put env-driven
326+values in `extra_headers` or the provider's `api_key` / `base_url`, all of
327+which do expand.
328+
329+> **Security note:** `crush.json` is trusted code. Any `$(...)` in it runs at
330+> load time with your shell's privileges, before the UI appears. Don't launch
331+> Crush in a directory whose `crush.json` you haven't reviewed.
267332
268333```json
269334{
@@ -275,17 +340,19 @@ using `$(echo $VAR)` syntax.
275340 "args": ["/path/to/mcp-server.js"],
276341 "timeout": 120,
277342 "disabled": false,
343+ "disabled_tools": ["some-tool-name"],
278344 "env": {
279345 "NODE_ENV": "production"
280346 }
281347 },
282348 "github": {
283349 "type": "http",
284− "url": "https://example.com/mcp/",
350+ "url": "https://api.githubcopilot.com/mcp/",
285351 "timeout": 120,
286352 "disabled": false,
353+ "disabled_tools": ["create_issue", "create_pull_request"],
287354 "headers": {
288− "Authorization": "$(echo Bearer $EXAMPLE_MCP_TOKEN)"
355+ "Authorization": "Bearer $GH_PAT"
289356 }
290357 },
291358 "streaming-service": {
@@ -301,6 +368,72 @@ using `$(echo $VAR)` syntax.
301368}
302369```
303370
371+### Hooks
372+
373+Crush has preliminary support for hooks. For details, see
374+[the hook guide](./docs/hooks/).
375+
376+### Sharing a workspace across clients
377+
378+When Crush is run against a shared backend (for example two TUIs talking to
379+the same `crush serve`), clients are grouped into **workspaces** keyed by
380+their resolved `--cwd`. Two clients with the same `--cwd` join the same
381+underlying workspace, so they share the session list, message history,
382+permission queue, LSP, and MCP state.
383+
384+Joining is implicit: pointing a second client at the same working directory
385+attaches it to the existing workspace. Each new invocation, however, starts
386+in its own fresh session by default. To pick up the conversation another
387+client already has open, use the session manager (the session picker) and
388+select it. Sessions surface two signals there:
389+
390+- `IsBusy` is set while an agent turn is in flight for that session.
391+- `AttachedClients` reports how many clients are currently viewing it.
392+
393+A non-zero `AttachedClients` (often combined with `IsBusy`) is the cue that a
394+session is "in progress" on another client and joining it will mirror that
395+view live.
396+
397+The first client to create a workspace fixes its process-wide flags. In
398+particular, `--yolo` and `--debug` follow a **first-wins** rule: later
399+clients that arrive at the same `--cwd` with different values for those
400+flags do not change the running workspace. A debug log line is emitted
401+recording the mismatch, and the workspace keeps the flags it was created
402+with.
403+
404+A workspace lives as long as at least one client has an SSE event stream
405+open against it. When the last stream disconnects, the workspace is torn
406+down. There is a short grace window right after `POST /v1/workspaces` so a
407+client that has created the workspace but not yet opened its event stream
408+does not get reaped before it can attach.
409+
410+### Global context files
411+
412+Crush automatically includes two files for cross-project instructions.
413+
414+- `~/.config/crush/CRUSH.md`: Crush-specific rules that would confuse other
415+ agentic coding tools. If you only use Crush, this is the only one you need to
416+ edit.
417+- `~/.config/AGENTS.md`: generic instructions that other coding tools might
418+ read. Avoid referring to Crush-specific features or workflows here. You
419+ probably only care about this if you use multiple agentic coding tools and
420+ want to share instructions between them.
421+
422+You can customize these paths using the `global_context_paths` option in your
423+configuration:
424+
425+```jsonc
426+{
427+ "$schema": "https://charm.land/crush.json",
428+ "options": {
429+ "global_context_paths": [
430+ "~/path/to/custom/context/file.md",
431+ "/full/path/to/folder/of/files/" // recursively load all .md files in folder
432+ ]
433+ }
434+}
435+```
436+
304437### Ignoring Files
305438
306439Crush respects `.gitignore` files by default, but you can also create a
@@ -335,79 +468,204 @@ permissions. Use this with care.
335468You can also skip all permission prompts entirely by running Crush with the
336469`--yolo` flag. Be very, very careful with this feature.
337470
338−### Attribution Settings
471+### Disabling Built-In Tools
339472
340−By default, Crush adds attribution information to Git commits and pull requests
341−it creates. You can customize this behavior with the `attribution` option:
473+If you'd like to prevent Crush from using certain built-in tools entirely, you
474+can disable them via the `options.disabled_tools` list. Disabled tools are
475+completely hidden from the agent.
342476
343477```json
344478{
345479 "$schema": "https://charm.land/crush.json",
346480 "options": {
347− "attribution": {
348− "co_authored_by": true,
349− "generated_with": true
350− }
481+ "disabled_tools": ["bash", "sourcegraph"]
351482 }
352483}
353484```
354485
355−- `co_authored_by`: When true (default), adds `Co-Authored-By: Crush <crush@charm.land>` to commit messages
356−- `generated_with`: When true (default), adds `💘 Generated with Crush` line to commit messages and PR descriptions
486+To disable tools from MCP servers, see the [MCP config section](#mcps).
357487
358−### Local Models
488+### Disabling Skills
489+
490+If you'd like to prevent Crush from using certain skills entirely, you can
491+disable them via the `options.disabled_skills` list. Disabled skills are hidden
492+from the agent, including builtin skills and skills discovered from disk.
493+
494+```json
495+{
496+ "$schema": "https://charm.land/crush.json",
497+ "options": {
498+ "disabled_skills": ["crush-config"]
499+ }
500+}
501+```
502+
503+### Agent Skills
504+
505+Crush supports the [Agent Skills](https://agentskills.io) open standard for
506+extending agent capabilities with reusable skill packages. Skills are folders
507+containing a `SKILL.md` file with instructions that Crush can discover and
508+activate on demand.
509+
510+The global paths we looks for skills are:
511+
512+* `$CRUSH_SKILLS_DIR`
513+* `$XDG_CONFIG_HOME/agents/skills` or `~/.config/agents/skills/`
514+* `$XDG_CONFIG_HOME/crush/skills` or `~/.config/crush/skills/`
515+* `~/.agents/skills/`
516+* `~/.claude/skills/`
517+* On Windows, we _also_ look at
518+ * `%LOCALAPPDATA%\agents\skills\` or `%USERPROFILE%\AppData\Local\agents\skills\`
519+ * `%LOCALAPPDATA%\crush\skills\` or `%USERPROFILE%\AppData\Local\crush\skills\`
520+* Additional paths configured via `options.skills_paths`
521+
522+On top of that, we _also_ load skills in your project from the following
523+relative paths:
524+
525+* `.agents/skills`
526+* `.crush/skills`
527+* `.claude/skills`
528+* `.cursor/skills`
529+
530+```jsonc
531+{
532+ "$schema": "https://charm.land/crush.json",
533+ "options": {
534+ "skills_paths": [
535+ "~/.config/crush/skills", // Windows: "%LOCALAPPDATA%\\crush\\skills",
536+ "./project-skills",
537+ ],
538+ },
539+}
540+```
541+
542+You can get started with example skills from [anthropics/skills](https://github.com/anthropics/skills):
543+
544+```bash
545+# Unix
546+mkdir -p ~/.config/crush/skills
547+cd ~/.config/crush/skills
548+git clone https://github.com/anthropics/skills.git _temp
549+mv _temp/skills/* . && rm -rf _temp
550+```
551+
552+```powershell
553+# Windows (PowerShell)
554+mkdir -Force "$env:LOCALAPPDATA\crush\skills"
555+cd "$env:LOCALAPPDATA\crush\skills"
556+git clone https://github.com/anthropics/skills.git _temp
557+mv _temp/skills/* . ; rm -r -force _temp
558+```
559+
560+#### User-Invocable Skills
561+
562+Skills can be made invocable as commands from the commands palette (Ctrl+P). Add `user-invocable: true` to the skill's YAML frontmatter:
563+
564+```yaml
565+---
566+name: my-skill
567+description: A skill that can be invoked as a command.
568+user-invocable: true
569+---
570+```
571+
572+User-invocable skills appear in the commands palette with a `user:` or `project:` prefix:
573+- Skills from global directories show as `user:skill-name`
574+- Skills from project directories show as `project:skill-name`
575+
576+When invoked, the skill's instructions are loaded into the conversation context.
577+
578+To prevent the model from auto-triggering a skill (while still allowing user invocation), add `disable-model-invocation: true`:
579+
580+```yaml
581+---
582+name: my-skill
583+description: Only invocable by users, not the model.
584+user-invocable: true
585+disable-model-invocation: true
586+---
587+```
359588
360−Local models can also be configured via OpenAI-compatible API. Here are two common examples:
589+Skills with `disable-model-invocation` won't appear in the model's available skills list but can still be invoked manually by users.
361590
362−#### Ollama
591+### Desktop notifications
592+
593+Crush sends desktop notifications when a tool call requires permission and when
594+the agent finishes its turn. They're only sent when the terminal window isn't
595+focused _and_ your terminal supports reporting the focus state.
596+
597+```jsonc
598+{
599+ "$schema": "https://charm.land/crush.json",
600+ "options": {
601+ "disable_notifications": false, // default
602+ },
603+}
604+```
605+
606+To disable desktop notifications, set `disable_notifications` to `true` in your
607+configuration. On macOS, notifications currently lack icons due to platform
608+limitations.
609+
610+### Initialization
611+
612+When you initialize a project, Crush analyzes your codebase and creates
613+a context file that helps it work more effectively in future sessions.
614+By default, this file is named `AGENTS.md`, but you can customize the
615+name and location with the `initialize_as` option:
363616
364617```json
365618{
366− "providers": {
367− "ollama": {
368− "name": "Ollama",
369− "base_url": "http://localhost:11434/v1/",
370− "type": "openai",
371− "models": [
372− {
373− "name": "Qwen 3 30B",
374− "id": "qwen3:30b",
375− "context_window": 256000,
376− "default_max_tokens": 20000
377− }
378− ]
379− }
619+ "$schema": "https://charm.land/crush.json",
620+ "options": {
621+ "initialize_as": "AGENTS.md"
380622 }
381623}
382624```
383625
384−#### LM Studio
626+This is useful if you prefer a different naming convention or want to
627+place the file in a specific directory (e.g., `CRUSH.md` or
628+`docs/LLMs.md`). Crush will fill the file with project-specific context
629+like build commands, code patterns, and conventions it discovered during
630+initialization.
631+
632+### Attribution Settings
633+
634+By default, Crush adds attribution information to Git commits and pull requests
635+it creates. You can customize this behavior with the `attribution` option:
385636
386637```json
387638{
388− "providers": {
389− "lmstudio": {
390− "name": "LM Studio",
391− "base_url": "http://localhost:1234/v1/",
392− "type": "openai",
393− "models": [
394− {
395− "name": "Qwen 3 30B",
396− "id": "qwen/qwen3-30b-a3b-2507",
397− "context_window": 256000,
398− "default_max_tokens": 20000
399− }
400− ]
639+ "$schema": "https://charm.land/crush.json",
640+ "options": {
641+ "attribution": {
642+ "trailer_style": "co-authored-by",
643+ "generated_with": true
401644 }
402645 }
403646}
404647```
405648
649+- `trailer_style`: Controls the attribution trailer added to commit messages
650+ (default: `assisted-by`)
651+ - `assisted-by`: Adds `Assisted-by: Crush:[ModelID]` as specified in [the convention](https://docs.kernel.org/process/coding-assistants.html#attribution)
652+ - `co-authored-by`: Adds `Co-Authored-By: Crush <crush@charm.land>`
653+ - `none`: No attribution trailer
654+- `generated_with`: When true (default), adds `💘 Generated with Crush` line to
655+ commit messages and PR descriptions
656+
406657### Custom Providers
407658
408659Crush supports custom provider configurations for both OpenAI-compatible and
409660Anthropic-compatible APIs.
410661
662+> [!NOTE]
663+> Note that we support two "types" for OpenAI. Make sure to choose the right one
664+> to ensure the best experience!
665+>
666+> - `openai` should be used when proxying or routing requests through OpenAI.
667+> - `openai-compat` should be used when using non-OpenAI providers that have OpenAI-compatible APIs.
668+
411669#### OpenAI-Compatible APIs
412670
413671Here’s an example configuration for Deepseek, which uses an OpenAI-compatible
@@ -418,7 +676,7 @@ API. Don't forget to set `DEEPSEEK_API_KEY` in your environment.
418676 "$schema": "https://charm.land/crush.json",
419677 "providers": {
420678 "deepseek": {
421− "type": "openai",
679+ "type": "openai-compat",
422680 "base_url": "https://api.deepseek.com/v1",
423681 "api_key": "$DEEPSEEK_API_KEY",
424682 "models": [
@@ -515,6 +773,68 @@ To add specific models to the configuration, configure as such:
515773}
516774```
517775
776+### Local Models
777+
778+Crush can auto-discovers models from local providers. Add a custom provider
779+with `type` set to `llamacpp`, `omlx`, `lmstudio`, `litellm`, or `ollama`
780+and leave out the models list. Crush will populate the model list
781+automatically.
782+
783+```json
784+{
785+ "providers": {
786+ "ollama": {
787+ "name": "Ollama",
788+ "base_url": "http://localhost:11434/v1/",
789+ "type": "ollama"
790+ }
791+ }
792+}
793+```
794+
795+For llama.cpp (`llama-server`), point at the server's base URL:
796+
797+```json
798+{
799+ "providers": {
800+ "llamacpp": {
801+ "name": "llama.cpp",
802+ "base_url": "http://localhost:2222",
803+ "type": "llamacpp"
804+ }
805+ }
806+}
807+```
808+
809+#### Manual Model Configuration
810+
811+You can still list models explicitly. User-defined models always take
812+precedence over discovered ones, and any fields you set won't be overwritten
813+by auto-discovery. Auto discovery will run if the model list is empty for any
814+`openai-compat` provider or if you pass `"discover_models": true` it will merge
815+ the found models with your hand configured ones.
816+
817+```json
818+{
819+ "providers": {
820+ "ollama": {
821+ "name": "Ollama",
822+ "base_url": "http://localhost:11434/v1/",
823+ "type": "ollama",
824+ "models": [
825+ {
826+ "name": "Qwen 3 30B",
827+ "id": "qwen3:30b",
828+ "context_window": 256000,
829+ "default_max_tokens": 20000
830+ }
831+ ],
832+ "discover_models": true
833+ }
834+ }
835+}
836+```
837+
518838## Logging
519839
520840Sometimes you need to look at logs. Luckily, Crush logs all sorts of
@@ -627,19 +947,21 @@ Or by setting the following in your config:
627947}
628948```
629949
630−Crush also respects the [`DO_NOT_TRACK`](https://consoledonottrack.com)
631−convention which can be enabled via `export DO_NOT_TRACK=1`.
950+Crush also respects the [`DO_NOT_TRACK`](https://donottrack.sh/) convention
951+which can be enabled via `export DO_NOT_TRACK=1`.
952+
953+## Q&A
632954
633−## A Note on Claude Max and GitHub Copilot
955+### Why is clipboard copy and paste not working?
634956
635−Crush only supports model providers through official, compliant APIs. We do not
636−support or endorse any methods that rely on personal Claude Max and GitHub
637−Copilot accounts or OAuth workarounds, which violate Anthropic and
638−Microsoft’s Terms of Service.
957+Installing an extra tool might be needed on Unix-like environments.
639958
640−We’re committed to building sustainable, trusted integrations with model
641−providers. If you’re a provider interested in working with us,
642−[reach out](mailto:vt100@charm.sh).
959+| Environment | Tool |
960+| ------------------- | ------------------------ |
961+| Windows | Native support |
962+| macOS | Native support |
963+| Linux/BSD + Wayland | `wl-copy` and `wl-paste` |
964+| Linux/BSD + X11 | `xclip` or `xsel` |
643965
644966## Contributing
645967
@@ -650,11 +972,12 @@ See the [contributing guide](https://github.com/charmbracelet/crush?tab=contribu
650972We’d love to hear your thoughts on this project. Need help? We gotchu. You can find us on:
651973
652974- [Twitter](https://twitter.com/charmcli)
653−- [Slack](https://charm.land/slack)
975+- [Slack][slack]
654976- [Discord][discord]
655977- [The Fediverse](https://mastodon.social/@charmcli)
656978- [Bluesky](https://bsky.app/profile/charm.land)
657979
980+[slack]: https://charm.land/slack
658981[discord]: https://charm.land/discord
659982
660983## License
@@ -665,7 +988,7 @@ We’d love to hear your thoughts on this project. Need help? We gotchu. You can
665988
666989Part of [Charm](https://charm.land).
667990
668−<a href="https://charm.land/"><img alt="The Charm logo" width="400" src="https://stuff.charm.sh/charm-banner-next.jpg" /></a>
991+<a href="https://charm.land/"><img alt="The Charm logo" width="400" src="https://stuff.charm.sh/charm-banner-softy.jpg" /></a>
669992
670993<!--prettier-ignore-->
671994Charm热爱开源 • Charm loves open source
Taskfile.yaml+102−4
@@ -5,6 +5,8 @@ version: "3"
55vars:
66 VERSION:
77 sh: git describe --long 2>/dev/null || echo ""
8+ RACE:
9+ sh: test -f race.log && echo "1" || echo ""
810
911env:
1012 CGO_ENABLED: 0
@@ -21,10 +23,16 @@ tasks:
2123 lint:
2224 desc: Run base linters
2325 cmds:
26+ - task: lint:log
2427 - golangci-lint run --path-mode=abs --config=".golangci.yml" --timeout=5m
2528 env:
2629 GOEXPERIMENT: null
2730
31+ lint:log:
32+ desc: Check that log messages start with capital letters
33+ cmds:
34+ - ./scripts/check_log_capitalization.sh
35+
2836 lint:fix:
2937 desc: Run base linters and fix issues
3038 cmds:
@@ -37,25 +45,67 @@ tasks:
3745 vars:
3846 LDFLAGS: '{{if .VERSION}}-ldflags="-X github.com/charmbracelet/crush/internal/version.Version={{.VERSION}}"{{end}}'
3947 cmds:
40− - go build {{.LDFLAGS}} .
48+ - "go build -v {{if .RACE}}-race{{end}} {{.LDFLAGS}} ."
49+ sources:
50+ - ./**/*.go
51+ - go.mod
52+ - internal/agent/**/*.md
53+ - internal/agent/**/*.md.tpl
54+ - internal/agent/hyper/provider.json
4155 generates:
42− - crush
56+ - crush{{exeExt}}
4357
4458 run:
4559 desc: Run build
4660 cmds:
47− - go run . {{.CLI_ARGS}}
61+ - task: build
62+ - "./crush{{exeExt}} {{.CLI_ARGS}} {{if .RACE}}2>race.log{{end}}"
63+
64+ run:catwalk:
65+ desc: Run build with local Catwalk
66+ env:
67+ CATWALK_URL: http://localhost:8080
68+ cmds:
69+ - task: build
70+ - ./crush{{exeExt}} {{.CLI_ARGS}}
71+
72+ run:onboarding:
73+ desc: Run build with custom config to test onboarding
74+ env:
75+ CRUSH_GLOBAL_DATA: tmp/onboarding/data
76+ CRUSH_GLOBAL_CONFIG: tmp/onboarding/config
77+ cmds:
78+ - task: build
79+ - rm -rf tmp/onboarding
80+ - ./crush{{exeExt}} {{.CLI_ARGS}}
4881
4982 test:
5083 desc: Run tests
5184 cmds:
52− - go test ./... {{.CLI_ARGS}}
85+ - go test -race -failfast ./... {{.CLI_ARGS}}
86+
87+ test:record:
88+ desc: Run tests and record all VCR cassettes again
89+ aliases: [record]
90+ cmds:
91+ - rm -r internal/agent/testdata
92+ - go test -v -count=1 -timeout=1h ./internal/agent
5393
5494 fmt:
5595 desc: Run gofumpt
5696 cmds:
5797 - gofumpt -w .
5898
99+ fmt:html:
100+ desc: Run prettier on HTML/CSS/JS files
101+ cmds:
102+ - prettier --write internal/cmd/stats/index.html internal/cmd/stats/index.css internal/cmd/stats/index.js
103+
104+ modernize:
105+ desc: Run modernize
106+ cmds:
107+ - go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix -test ./...
108+
59109 dev:
60110 desc: Run with profiling enabled
61111 env:
@@ -68,7 +118,14 @@ tasks:
68118 vars:
69119 LDFLAGS: '{{if .VERSION}}-ldflags="-X github.com/charmbracelet/crush/internal/version.Version={{.VERSION}}"{{end}}'
70120 cmds:
121+ - task: fetch-tags
71122 - go install {{.LDFLAGS}} -v .
123+ sources:
124+ - ./**/*.go
125+ - go.mod
126+ - internal/agent/**/*.md
127+ - internal/agent/**/*.md.tpl
128+ - internal/agent/hyper/provider.json
72129
73130 profile:cpu:
74131 desc: 10s CPU profile
@@ -93,6 +150,13 @@ tasks:
93150 generates:
94151 - schema.json
95152
153+ hyper:
154+ desc: Update Hyper embedded provider.json
155+ cmds:
156+ - go generate ./internal/agent/hyper/...
157+ generates:
158+ - ./internal/agent/hyper/provider.json
159+
96160 release:
97161 desc: Create and push a new tag following semver
98162 vars:
@@ -104,6 +168,10 @@ tasks:
104168 msg: Not on main branch
105169 - sh: "[ $(git status --porcelain=2 | wc -l) = 0 ]"
106170 msg: "Git is dirty"
171+ - sh: 'gh run list --workflow build.yml --commit $(git rev-parse HEAD) --status success --json conclusion -q ".[0].conclusion" | grep -q success'
172+ msg: "Test build for this commit failed or not present"
173+ - sh: 'gh run list --workflow snapshot.yml --commit $(git rev-parse HEAD) --status success --json conclusion -q ".[0].conclusion" | grep -q success'
174+ msg: "Snapshot build for this commit failed or not present"
107175 cmds:
108176 - task: fetch-tags
109177 - git commit --allow-empty -m "{{.NEXT}}"
@@ -115,3 +183,33 @@ tasks:
115183 cmds:
116184 - git tag -d nightly || true
117185 - git fetch --tags
186+
187+ deps:
188+ desc: Update Fantasy and Catwalk
189+ env:
190+ # The Go proxy takes a bit of time to see the latest release. Setting
191+ # these bypass it to ensure we can update to a release from a minute ago.
192+ GOPROXY: direct
193+ GONOSUMDB: charm.land/*
194+ cmds:
195+ - go get charm.land/fantasy@latest
196+ - go get charm.land/catwalk@latest
197+ - go mod tidy
198+
199+ swag:
200+ desc: Generate OpenAPI spec from swag annotations
201+ cmds:
202+ - go run github.com/swaggo/swag/cmd/swag@v1.16.6 init --generalInfo main.go --dir . --output internal/swagger --packageName swagger --parseDependency --parseInternal --parseDepth 5
203+ sources:
204+ - internal/server/*.go
205+ - internal/proto/*.go
206+ - main.go
207+ generates:
208+ - internal/swagger/docs.go
209+ - internal/swagger/swagger.json
210+ - internal/swagger/swagger.yaml
211+
212+ sqlc:
213+ desc: Generate code using SQLC
214+ cmds:
215+ - sqlc generate
crush.json+35−1
@@ -1,6 +1,40 @@
11{
22 "$schema": "https://charm.land/crush.json",
33 "lsp": {
4− "gopls": {}
4+ "gopls": {
5+ "options": {
6+ "gofumpt": true,
7+ "codelenses": {
8+ "gc_details": true,
9+ "generate": true,
10+ "run_govulncheck": true,
11+ "test": true,
12+ "tidy": true,
13+ "upgrade_dependency": true
14+ },
15+ "hints": {
16+ "assignVariableTypes": true,
17+ "compositeLiteralFields": true,
18+ "compositeLiteralTypes": true,
19+ "constantValues": true,
20+ "functionTypeParameters": true,
21+ "parameterNames": true,
22+ "rangeVariableTypes": true
23+ },
24+ "analyses": {
25+ "nilness": true,
26+ "unusedparams": true,
27+ "unusedvariable": true,
28+ "unusedwrite": true,
29+ "useany": true
30+ },
31+ "staticcheck": true,
32+ "directoryFilters": [
33+ "-.git",
34+ "-node_modules"
35+ ],
36+ "semanticTokens": true
37+ }
38+ }
539 }
640}
cspell.jsondeleted−1
@@ -1 +0,0 @@
1−{"flagWords":[],"version":"0.2","language":"en","words":["afero","agentic","alecthomas","anthropics","aymanbagabas","azidentity","bmatcuk","bubbletea","charlievieth","charmbracelet","charmtone","Charple","chkconfig","crush","curlie","cursorrules","diffview","doas","Dockerfiles","doublestar","dpkg","Emph","fastwalk","fdisk","filepicker","Focusable","fseventsd","fsext","genai","goquery","GROQ","Guac","imageorient","Inex","jetta","jsons","jsonschema","jspm","Kaufmann","killall","Lanczos","lipgloss","LOCALAPPDATA","lsps","lucasb","makepkg","mcps","MSYS","mvdan","natefinch","nfnt","noctx","nohup","nolint","nslookup","oksvg","Oneshot","openrouter","opkg","pacman","paru","pfctl","postamble","postambles","preconfigured","Preproc","Proactiveness","Puerkito","pycache","pytest","qjebbs","rasterx","rivo","sabhiram","sess","shortlog","sjson","Sourcegraph","srwiley","SSEMCP","Streamable","stretchr","Strikethrough","substrs","Suscriber","systeminfo","tasklist","termenv","textinput","tidwall","timedout","trashhalo","udiff","uniseg","Unticked","urllib","USERPROFILE","VERTEXAI","webp","whatis","whereis","sahilm","csync"]}
docs/hooks/FUTURE.mdnew file+260
@@ -0,0 +1,260 @@
1+# Hooks: Future Work
2+
3+This document tracks planned features and design notes for hooks that are not
4+yet implemented. Nothing here is part of the current contract. Treat it as a
5+scratchpad for what's next, not as documentation of current behavior.
6+
7+> [!NOTE]
8+> This document was largely LLM-generated.
9+
10+## `context_files`
11+
12+**Status:** planned, not implemented.
13+
14+### Motivation
15+
16+Today, a hook that wants to inject reference material into the agent's context
17+has exactly one knob: `context` (string or array of strings). Whatever the hook
18+puts there is concatenated into what the model sees. That's fine for short notes
19+("current branch: main", "scrubbed secrets") but it scales badly:
20+
21+- Dumping a whole `README.md` or `package.json` into `context` burns tokens on
22+ every tool call where the hook fires.
23+- The model sees the file contents even if it doesn't need them.
24+- Large files can push the turn past the context window.
25+
26+`context_files` is the lazy alternative: the hook returns **paths**, not
27+contents. Crush tells the agent the files exist and are relevant, and the agent
28+decides whether to open them with its existing `view` tool.
29+
30+### Proposed shape
31+
32+Additive envelope field. Accepts a list of strings:
33+
34+```jsonc
35+{
36+ "decision": "allow",
37+ "context": "Scrubbed one secret",
38+ "context_files": ["README.md", "docs/ARCHITECTURE.md"],
39+}
40+```
41+
42+Paths are resolved relative to `CRUSH_CWD`. Non-existent paths are dropped with
43+a debug log (don't fail the hook over a missing file).
44+
45+### How the agent sees it
46+
47+Crush appends a short note to the turn's context along the lines of:
48+
49+```
50+## Referenced files
51+- README.md
52+- docs/ARCHITECTURE.md
53+```
54+
55+No file contents are inlined. The agent opens them with `view` if it decides
56+they're relevant. This keeps cost proportional to need.
57+
58+### Aggregation
59+
60+Matches the existing rules for lists:
61+
62+- Concatenates across matching hooks in config order.
63+- Deduplicates paths (same file referenced by two hooks → listed once).
64+- Dropped entirely if the final decision is `deny` or `halt`.
65+
66+### Backwards compatibility
67+
68+Purely additive. Hooks that don't emit `context_files` are unaffected. Existing
69+envelopes keep working unchanged. No version bump required.
70+
71+### Open questions
72+
73+- Should `context_files` paths be constrained to `CRUSH_PROJECT_DIR`? Probably
74+ yes, to avoid hooks smuggling in arbitrary filesystem reads.
75+- Do we want a per-file line range (`"README.md:1-40"`) or keep it dead simple
76+ (whole-file references only)? Start simple; add ranges only if asked for.
77+- Should we annotate "why this file is relevant" per entry? An object form
78+ (`{"path": "...", "reason": "..."}`) would allow that but complicates the
79+ schema. Defer until there's a real user need.
80+
81+## Sub-agent opt-in
82+
83+**Status:** not implemented.
84+
85+### Background
86+
87+Today hooks fire **only** on the top-level agent's tool calls. Sub-agents
88+(`agent` task tool, `agentic_fetch`, future delegated loops) run without hook
89+interception so a single delegated turn doesn't trigger the user's hook N times.
90+
91+The outer sub-agent tool call itself is hooked, so blanket policy like "never
92+spawn sub-agents" or "rewrite prompts sent to the task agent" still works from
93+the coder's side. The sub-agent's inner loop is the part that's exempt.
94+
95+### Why users might want the escape hatch
96+
97+- Audit logging of every tool call, including delegated ones.
98+- Redaction hooks that want to apply uniformly regardless of who called the
99+ tool.
100+- Policy that cares about the _tool_ not the _caller_: "never fetch from this
101+ domain, even in `agentic_fetch`."
102+
103+Until someone actually asks, don't ship this. YAGNI.
104+
105+### Proposed shape
106+
107+Additive, per-hook. Zero-value matches current default (skip sub-agents):
108+
109+```jsonc
110+{
111+ "hooks": {
112+ "PreToolUse": [
113+ {
114+ "matcher": "^bash$",
115+ "command": "./hooks/audit.sh",
116+ "include_sub_agents": true, // default false
117+ },
118+ ],
119+ },
120+}
121+```
122+
123+Implementation changes where `wrapToolsWithHooks` decides to skip. Instead of a
124+single `isSubAgent` bailout, the runner filters per-hook matches by the hook's
125+`include_sub_agents` flag. Hooks that opt in get wrapped into sub-agent tool
126+slices too; everything else stays skipped.
127+
128+### Backwards Compatibility
129+
130+Purely additive. Hooks that don't set `include_sub_agents` get the default
131+(`false` = skip sub-agents). No wire format change, no version bump. The initial
132+transition from "hooks fire everywhere" to "hooks skip sub-agents by default"
133+was a one-time behavior change; adding the opt-in is pure addition.
134+
135+### Side benefit: payload awareness
136+
137+Extend the stdin payload with `"is_sub_agent": true|false` so hook scripts that
138+opt in can branch on caller type ("audit top-level and sub-agent calls
139+differently"). Also purely additive — hooks that don't read the field are
140+unaffected.
141+
142+### Open questions
143+
144+- Per-hook flag (above) vs a global `hooks.include_sub_agents` default? A global
145+ toggle is simpler but coarse-grained; per-hook is more flexible and
146+ composable. Start per-hook; a global default can be layered on later with
147+ explicit precedence ("per-hook overrides global").
148+- Does an opt-in hook see hooks from _nested_ sub-agents too (a sub-agent that
149+ itself calls a sub-agent)? Probably yes — once you've opted in you want the
150+ full tree. But call it out explicitly in docs so users aren't surprised by N²
151+ explosions on pathological configs.
152+
153+## `UserPromptSubmit` event
154+
155+**Status:** not implemented.
156+
157+### Motivation
158+
159+Today Crush supports exactly one hook event, `PreToolUse`. That's enough to gate
160+and rewrite tool calls but nothing else. The next-most-useful event is
161+`UserPromptSubmit`: fires after the user hits Enter but before the turn hits the
162+LLM. Lets hooks inject context, rewrite prompts, or gate on content without the
163+mutation complexity of `PostToolUse` (output scrubbing, error coercion, size
164+limits — all rabbit holes).
165+
166+### Use cases
167+
168+- Prepend project context the user didn't think to include ("current branch:
169+ `feat/x`; last commit: `<sha> <title>`").
170+- Point at reference files via `context_files` (when that lands) so the agent
171+ knows where to look without being force-fed contents.
172+- Redact secrets out of the prompt before it leaves the machine.
173+- Refuse prompts matching a policy ("don't send anything mentioning
174+ `production.env`") — with `deny` and a reason the user sees.
175+- Expand shorthand (`@TODO` → "please address the TODO in …").
176+
177+### Proposed shape
178+
179+Stdin payload extends the common envelope with the prompt:
180+
181+```jsonc
182+{
183+ "event": "UserPromptSubmit",
184+ "session_id": "…",
185+ "cwd": "/home/user/project",
186+ "prompt": "fix the login flow",
187+ "attachments": ["screenshot.png"],
188+}
189+```
190+
191+Output envelope reuses common fields plus one new per-event field,
192+`updated_prompt`:
193+
194+```jsonc
195+{
196+ "decision": "allow", // optional; deny blocks the submission entirely
197+ "reason": "includes a production secret", // shown to the user when denying
198+ "context": "Current branch: feat/login",
199+ "updated_prompt": "fix the login flow\n\n(from @TODO on line 42)",
200+}
201+```
202+
203+`updated_prompt` is a **full replacement** — not a merge patch — because a
204+prompt is a single string with no natural key structure. If multiple hooks emit
205+`updated_prompt`, later hooks in config order win.
206+
207+### Aggregation
208+
209+Reuses the universal rules:
210+
211+- `halt` is sticky. Halts the whole turn before the LLM is called.
212+- `context` concatenates in config order.
213+- `updated_prompt`: last writer wins.
214+- `decision: "deny"` blocks the submission. The user sees `reason`; the turn
215+ never reaches the LLM.
216+
217+### Differences from `PreToolUse`
218+
219+- No `updated_input`: there are no tool inputs at this point.
220+- No permission-prompt bypass: there's no permission prompt for a user prompt.
221+- `decision: "allow"` is functionally identical to silence. It exists only for
222+ symmetry with `PreToolUse` and to give hook authors a consistent vocabulary.
223+ (Could be argued both ways — consider dropping it here.)
224+- Fires on every user submission, including follow-ups in the same session.
225+ Hooks should be fast; no subprocess-per-keystroke scenarios but the per-turn
226+ overhead is real.
227+
228+### Implementation sketch
229+
230+- New event constant `EventUserPromptSubmit` in `internal/hooks/hooks.go`.
231+- `Runner.Run` already takes an event name; no interface change.
232+- A new call site in `sessionAgent.Run` (or the coordinator's Run path) that
233+ fires hooks after creating the user message but before the first LLM call. If
234+ the aggregate decision is `deny` or `halt`, abort the turn and surface
235+ `reason` to the user.
236+- If hooks return `context`, prepend it to the prompt seen by the LLM (or attach
237+ as a system-message-level note — decide based on how the prompt is threaded
238+ through fantasy).
239+- If hooks return `updated_prompt`, replace the prompt body before the first LLM
240+ call. The message row in the DB should still store the _original_ prompt so
241+ the user sees what they typed; only the outbound version is rewritten. (Or:
242+ store both, show the original, send the rewritten — mirror how `updated_input`
243+ is handled today.)
244+
245+### Open questions
246+
247+- Store original vs rewritten prompt? Probably both, with UI showing original
248+ and a subtle indicator that a hook modified it.
249+- Do hooks fire on queued prompts too, or only when actually dispatched? If the
250+ user queues three prompts and the hook blocks the second, what happens to the
251+ third? Simplest rule: fire when dispatched; denial skips to the next queued
252+ prompt with a visible note.
253+- What about the `/commands` prefix? Does `UserPromptSubmit` fire for slash
254+ commands, or are those intercepted earlier? Probably earlier — hooks see only
255+ freeform prompts that would actually reach the LLM.
256+
257+## Cross-platform shell (Windows support)
258+
259+**Status:** implemented. See the [Execution model](README.md#execution-model)
260+section in `README.md` for the current behavior and contract.
docs/hooks/README.mdnew file+759
@@ -0,0 +1,759 @@
1+# Hooks
2+
3+> [!NOTE]
4+> This document was designed for both humans and agents.
5+
6+Hooks are user-defined shell scripts that run when various events happen during
7+the agent lifecycle, allowing you to both build on top of Crush, customize
8+its behavior, and exert deterministic control over an agent's wily behavior.
9+
10+Hooks are just shell commands, and were designed to be both simple and future
11+forward.
12+
13+### Hot Hook Facts
14+
15+- Hooks are just shell commands
16+- Hooks can be written in any language because they’re just executables: Bash, Python, Node, Rust, Haskell, whatever
17+- Hooks are Claude Code-compatible
18+- Crush ships with a builtin `crush-hook` skill write, edit, and configure
19+ hooks; just tell Crush how to configure Crush
20+- Crush currently supports just one hook, `PreToolUse`, with plans to support
21+ the full gamut; please let us know which hooks you'd like to see next
22+- Hooks run in parallel for speed, but their results compose in config order
23+ for determinism
24+
25+### Some things you can do with hooks:
26+
27+- Block "dangerous" commands: no more `git push -f` or `cabal init`
28+- Rewrite tool input: turn `node` calls info `deno`, scrub secrets from
29+ commands, rewrite all mentions of "Haskell" into "Haskell, The Best
30+ Language", and so on
31+- Inject context: add notes to the model's context whenever certain tools are
32+ called. For example: "remember to run gofumpt after editing Go files"
33+- Auto-approve tools: skip the permission prompt for bash commands that
34+ you know are safe
35+- Log certain tool calls
36+
37+…And lots more. Show us what you're building!
38+
39+## Baby's First Hook
40+
41+Let's just dive into it and make a simple hook. This particular hook will
42+disallow the use of Haskell (but we love you, Simon Peyton Jones).
43+
44+### Config
45+
46+The first thing we need to do is hook up our hook. Let's add the following to
47+our **project-level** `crush.json`. Relative paths like `./no-haskell.sh` work
48+here because the project root is your working directory. If you're configuring
49+a global hook (`~/.config/crush/crush.json`), use an absolute path instead.
50+
51+```jsonc
52+{
53+ // As expected, hooks go in a "hooks" object.
54+ "hooks": {
55+ // PreToolUse is an event that fires before a tool is used.
56+ "PreToolUse": [
57+ {
58+ // What tool do we want to hook into? In this case, Bash, because it
59+ // runs the stuff we wanna block.
60+ "matcher": "^bash$",
61+
62+ // The path to our actual hook script.
63+ "command": "./no-haskell.sh",
64+ },
65+ ],
66+ },
67+}
68+```
69+
70+Now, let's make our `no-haskell.sh` hook script.
71+
72+```bash
73+#!/usr/bin/env bash
74+
75+# Disallow ghc, cabal, and stack. Pipe the bash command output
76+# ($CRUSH_TOOL_INPUT_COMMAND) to grep and match on a regexp.
77+if echo "$CRUSH_TOOL_INPUT_COMMAND" | grep -qE '(^| )((ghc|cabal|stack)(\.exe)?)( |$)'; then
78+
79+ # Someone is trying to use Haskell. Let's send a message back to the model
80+ # and user explaining why we're blocking this. Note that we send all feedback
81+ # like this to stderr.
82+ echo "No Haskell allowed, kiddo." >&2
83+
84+ # Now, block the tool call by exiting with code 2.
85+ exit 2
86+fi
87+```
88+
89+That's basically it. For the full guide on how hooks work, however, read on.
90+
91+---
92+
93+## Execution model
94+
95+Hooks run through Crush's embedded POSIX shell (`mvdan.cc/sh`) — the same
96+interpreter the `bash` tool uses. Inline commands and shebang-less scripts
97+execute in-process; scripts with a `#!` shebang dispatch to the named
98+interpreter via `os/exec`. This contract is identical on macOS, Linux, and
99+Windows.
100+
101+What this means in practice:
102+
103+- **Windows without Unix tooling**: inline shell (`echo`, pipelines, `jq`,
104+ `grep`), shebang-less `.sh` scripts, inline PowerShell
105+ (`powershell -Command …`), and `.exe` invocations all work out of the box
106+ with no WSL, Git Bash, Cygwin, or MSYS required.
107+- **PowerShell scripts** (`.ps1`) are not auto-dispatched by extension.
108+ Invoke them explicitly: `powershell -File ./audit.ps1` (or
109+ `pwsh -File ./audit.ps1`).
110+- **Shebang'd scripts** require the named interpreter on `PATH`. Git for
111+ Windows ships `bash.exe`, which makes `#!/bin/bash` and
112+ `#!/usr/bin/env bash` scripts work on Windows the same way they do on
113+ Unix. CRLF line endings in the shebang line are tolerated.
114+- **Permissive shebang fallback**: if the absolute path in a shebang
115+ doesn't exist (e.g. `#!/bin/bash` on Windows), Crush falls back to a
116+ `PATH` lookup of the base name (`bash`) before giving up. A debug-level
117+ log records the fallback. If the interpreter isn't on `PATH` either, the
118+ hook fails cleanly as a non-blocking warning and the agent proceeds as
119+ "no opinion".
120+- **Environment**: every hook sees `CRUSH=1`, `AGENT=crush`, and
121+ `AI_AGENT=crush` on top of the `CRUSH_*` hook-specific variables. These
122+ three markers are guaranteed and match what the `bash` tool sets, so
123+ scripts that detect "am I being run by an AI agent?" behave the same in
124+ both contexts.
125+- **Timeout behavior**: when a hook exceeds its timeout, Crush cancels the
126+ context and waits a short grace period (~1s) for the interpreter to
127+ yield. If the hook still hasn't returned, Crush abandons it, logs a
128+ warning, and treats the result as "no opinion" so the agent can proceed.
129+ Long-running work should honor context cancellation or run in a
130+ subprocess via a shebang.
131+
132+## Configuration
133+
134+Hooks can be added to your `crush.json` (or `.crush.json`) at both the global
135+and project-level, with project level hooks taking precedence.
136+
137+```jsonc
138+{
139+ "hooks": {
140+ "PreToolUse": [
141+ {
142+ "name": "no-rm-rf", // friendly name shown in the TUI
143+ "matcher": "bash", // regex tested against the tool name
144+ "command": "./hooks/my-hot-hook.sh", // the path to the hook
145+ "timeout": 10, // in seconds; default 30
146+ },
147+ ],
148+ },
149+}
150+```
151+
152+> [!IMPORTANT]
153+> The `command` is resolved relative to your **current working directory** —
154+> not relative to the config file. Relative paths like `./hooks/whatever.sh`
155+> work fine in project-level `crush.json` because the project root is also
156+> your working directory. For **global** config (`~/.config/crush/`),
157+> however, you must use either an absolute path or an inline command:
158+>
159+> ```jsonc
160+> // Global ~/.config/crush/crush.json
161+> {
162+> "hooks": {
163+> "PreToolUse": [
164+> {
165+> "command": "/home/you/.config/crush/hooks/no-haskell.sh"
166+> // or use an inline command:
167+> // "command": "echo '{\"decision\":\"allow\"}'"
168+> }
169+> ]
170+> }
171+> }
172+> ```
173+
174+Remember, hooks will run in parallel but resolve in config order. Last hook
175+wins when rewriting input, but first deny wins when blocking.
176+
177+## Events
178+
179+Here are the events you can hook into (spoiler: there's currently just one):
180+
181+### PreToolUse
182+
183+This hook fires before every tool call. Use it to block dangerous commands,
184+enforce policies, rewrite tool input, inject context the model should see, log
185+stuff, and so on.
186+
187+**Matched against**: the tool name (e.g. `bash`, `edit`, `write`,
188+`mcp_github_create_pull_request`).
189+
190+> [!NOTE]
191+> Event names are case insensitive and snake-caseable, so `PreToolUse`,
192+> `pretooluse`, `PRETOOLUSE`, `pre_tool_use`, and `PRE_TOOL_USE` all work.
193+
194+**Scope**: `PreToolUse` only fires on the **top-level agent's** tool calls.
195+Sub-agents (the `agent` task tool, `agentic_fetch`, etc.) run without hook
196+interception so a single delegated turn doesn't trigger your hook N times. The
197+outer sub-agent tool call itself _is_ hooked, so policy like "never let the
198+agent spawn sub-agents" still works.
199+
200+Hooks are keyed by event name. Only `command` is required, and you can omit
201+`matcher` to match all tools.
202+
203+## Building Hooks
204+
205+When a hook fires, Crush:
206+
207+1. Filters hooks whose `matcher` regex matches the tool name (no matcher = match
208+ all).
209+2. Deduplicates by `command` (identical commands run once).
210+3. Runs all matching hooks **in parallel** through Crush's embedded POSIX
211+ shell (see [Execution model](#execution-model)).
212+4. Waits for all to finish (or time out), then aggregates results **in config
213+ order**: deny wins over allow, allow wins over none; `updated_input` patches
214+ shallow-merge in order.
215+5. Applies the result **before** permission checks. If the aggregated decision
216+ is `deny`, the tool call is blocked and you never see a permission prompt
217+ for it. If it's `allow`, Crush treats that as affirmative pre-approval and
218+ also skips the prompt. Silence (no decision) falls through to the normal
219+ permission flow.
220+
221+Note that you can omit `matcher` and match in your shell script instead,
222+however you'll incur some additional overhead as Crush will still parse and
223+run each hook.
224+
225+### Input
226+
227+Each hook receives data two ways: environment variables and stdin (as JSON).
228+Environment variables are typically easier to work with, with JSON being
229+available when input is more complex.
230+
231+#### Environment Variables
232+
233+The available environment variables are:
234+
235+| Variable | Description |
236+| ---------------------------- | ---------------------------------------------- |
237+| `CRUSH` | Always `1` when running under Crush. |
238+| `AGENT` | Always `crush`. |
239+| `AI_AGENT` | Always `crush`. |
240+| `CRUSH_EVENT` | The hook event name (e.g. `PreToolUse`). |
241+| `CRUSH_TOOL_NAME` | The tool being called (e.g. `bash`). |
242+| `CRUSH_SESSION_ID` | Current session ID. |
243+| `CRUSH_CWD` | Working directory. |
244+| `CRUSH_PROJECT_DIR` | Project root directory. |
245+| `CRUSH_TOOL_INPUT_COMMAND` | For `bash` calls: the shell command being run. |
246+| `CRUSH_TOOL_INPUT_FILE_PATH` | For file tools: the target file path. |
247+
248+The `CRUSH`, `AGENT`, and `AI_AGENT` markers are also set by the `bash`
249+tool, so a script can detect "am I running under Crush?" the same way in
250+either context.
251+
252+#### JSON
253+
254+Standard input provides the full context as JSON:
255+
256+```jsonc
257+{
258+ "event": "PreToolUse", // Hook event name
259+ "session_id": "313909e", // Current session ID
260+ "cwd": "/home/user/project", // Working directory
261+ "tool_name": "bash", // The tool being called
262+ "tool_input": { "command": "rm -rf /" }, // The tool's input
263+}
264+```
265+
266+Note that `tool_input` field contains the raw JSON the model sent to the tool.
267+
268+To parse the stdin JSON in your hook script, read from stdin and use a tool like
269+`jq`:
270+
271+```bash
272+#!/usr/bin/env bash
273+read -r input
274+tool_name=$(echo "$input" | jq -r '.tool_name')
275+command=$(echo "$input" | jq -r '.tool_input.command // empty')
276+```
277+
278+You can also use tools like Python:
279+
280+```python
281+#!/usr/bin/env python3
282+import json, sys
283+
284+data = json.load(sys.stdin)
285+tool_name = data.get("tool_name", "")
286+command = data.get("tool_input", {}).get("command", "")
287+```
288+
289+### Output
290+
291+Hooks communicate back to Crush via **exit code** and `stdout`/`stderr`. The
292+simplest way to do this is to return an error code and print additional context
293+to stderr. For example:
294+
295+```bash
296+# Here, error code 2 blocks the tool, using stderr as the reason:
297+if some_bad_condition; then
298+ echo "Blocked: reason here" >&2
299+ exit 2
300+fi
301+```
302+
303+| Exit Code | Meaning |
304+| --------- | ---------------------------------------------------------------- |
305+| 0 | Success. Stdout is parsed as JSON (see fields below). |
306+| 2 | **Block the tool.** Stderr is used as the deny reason (no JSON). |
307+| 49 | **Halt the turn.** Stderr is used as the halt reason (no JSON). |
308+| Other | Non-blocking error. Logged and ignored — the tool call proceeds. |
309+
310+The difference between exit 2 and exit 49:
311+
312+- **Exit 2** blocks the current tool call. The agent sees the error and can try
313+ something else.
314+- **Exit 49** halts the whole turn. The agent doesn't get to respond further;
315+ the user takes over. Use this when something is wrong enough that the agent
316+ shouldn't keep trying. 49 sits in an empty slice of the exit-code space —
317+ between the generic-error range (1-30), the BSD `sysexits.h` range (64-78),
318+ and the killed-by-signal range (128+) — so it can't be hit by accident.
319+
320+That said, if you need more control, or if you need to rewrite input, you can
321+use JSON on stdout. Exit 0 and print a JSON object to provide context, update
322+the input, or still deny/halt with a reason:
323+
324+```jsonc
325+{
326+ "version": 1, // Output envelope version. Optional; defaults to 1.
327+ "decision": "allow", // "allow", "deny", or null. Omit for no opinion.
328+ "halt": false, // If true, halts the turn entirely.
329+ "reason": "LGTM", // Shown when denying or halting.
330+ "context": "Scrubbed secrets", // String or array of strings. Appended to what the model sees.
331+ "updated_input": { "command": "…" }, // Shallow-merged into the tool's input before execution.
332+}
333+```
334+
335+`version` is an optional integer at the top of the envelope. It defaults to `1`
336+if omitted. Unknown higher versions are still parsed; the field exists so the
337+envelope can evolve without a compatibility shim.
338+
339+`decision: "allow"` is **affirmative**: it pre-approves the tool call and
340+bypasses the permission prompt entirely. Silence (no `decision`, or
341+`decision: null`) means "no opinion" — the tool still goes through the
342+normal permission flow. Use `"allow"` when you want to auto-approve; omit it
343+when you only want to inject context or rewrite input without also vouching
344+for the call.
345+
346+`updated_input` is a shallow-merge patch. Keys you include overwrite matching
347+keys in `tool_input`; keys you don't include are preserved. If the model called
348+`bash` with `{"command": "npm test", "timeout": 60000}` and your hook returns
349+`{"updated_input": {"command": "bun test"}}`, the tool runs with
350+`{"command": "bun test", "timeout": 60000}` — the timeout isn't dropped. The
351+merge is shallow: nested objects are replaced wholesale, not deep-merged.
352+
353+`halt: true` stops the turn entirely. The agent doesn't get to respond further;
354+the user takes over. The exit-code shorthand is `exit 49` with stderr as the
355+reason.
356+
357+`context` accepts either a string or an array of strings. Use the string form
358+for a single observation; use the array form when a hook produces multiple
359+distinct notes and you'd rather not concatenate them by hand. Empty strings and
360+empty array entries are dropped.
361+
362+Here's a full shell script that produces this JSON:
363+
364+```bash
365+#!/usr/bin/env bash
366+# Example: rewrite a bash command using RTK
367+
368+read -r input
369+original_cmd=$(echo "$input" | jq -r '.tool_input.command')
370+rewritten=$(secret-scrubber rewrite "$original_cmd")
371+
372+cat <<EOF
373+{
374+ "decision": "allow",
375+ "context": "Scrubbed secrets",
376+ "updated_input": {"command": "$rewritten"}
377+}
378+EOF
379+```
380+
381+### Multiple Hooks
382+
383+Hooks run in parallel, but their results compose in config order. Whichever hook
384+finishes first doesn't get to "win" by virtue of timing; composition is
385+deterministic based on the order hooks appear in `crush.json`.
386+
387+When multiple hooks match the same tool call:
388+
389+- If **any** hook denies, the tool call is blocked. `reason` values are
390+ concatenated in config order (newline-separated).
391+- If **any** hook halts, the turn ends after the tool call is blocked.
392+- If no hook denies or halts but at least one allows, the tool call proceeds
393+ **and the permission prompt is skipped**.
394+- `context` values are concatenated in config order. Strings and arrays compose
395+ uniformly — each string becomes one entry, and array entries are flattened in.
396+- `updated_input` patches shallow-merge in config order against the original
397+ tool input. Later hooks override earlier ones on colliding keys. If denied or
398+ halted, `updated_input` patches are ignored.
399+
400+### Timeouts
401+
402+If a hook exceeds its timeout, Crush cancels its context and treats the
403+result as a non-blocking error so the tool call proceeds. The default
404+timeout is 30 seconds. Shebang-dispatched subprocesses are killed through
405+`exec.CommandContext`; in-process hooks get a short grace period to yield
406+and are then abandoned (the agent moves on regardless). Long-running work
407+should honor context cancellation or run out-of-process via a shebang.
408+
409+## Examples
410+
411+### Block destructive commands
412+
413+Prevent the agent from running `rm -rf` in bash:
414+
415+```json
416+{
417+ "hooks": {
418+ "PreToolUse": [
419+ {
420+ "matcher": "^bash$",
421+ "command": "./hooks/no-rm-rf.sh"
422+ }
423+ ]
424+ }
425+}
426+```
427+
428+`hooks/no-rm-rf.sh`:
429+
430+```bash
431+#!/usr/bin/env bash
432+# Block rm -rf commands in the bash tool. Otherwise stay silent so the
433+# normal permission flow runs.
434+
435+if echo "$CRUSH_TOOL_INPUT_COMMAND" | grep -qE 'rm\s+-(rf|fr)\s+/'; then
436+ echo "Refusing to run rm -rf against root" >&2
437+ exit 2
438+fi
439+
440+exit 0
441+```
442+
443+### Auto-approve read-only tools
444+
445+Skip the permission prompt for tools that can't change anything. The hook
446+returns `decision: "allow"`, which tells Crush to pre-approve the call:
447+
448+```jsonc
449+{
450+ "hooks": {
451+ "PreToolUse": [
452+ {
453+ "matcher": "^(view|ls|grep|glob)$",
454+ "command": "echo '{\"decision\":\"allow\"}'",
455+ },
456+ ],
457+ },
458+}
459+```
460+
461+No script file needed — the command is inline. Every `view`/`ls`/`grep`/`glob`
462+call now runs without prompting. Add the `bash` tool to this list at your own
463+risk; consider a more targeted allowlist instead:
464+
465+```bash
466+#!/usr/bin/env bash
467+# hooks/safe-bash.sh — auto-approve read-only bash commands.
468+
469+case "$CRUSH_TOOL_INPUT_COMMAND" in
470+ ls*|cat*|grep*|rg*|echo*|pwd*)
471+ echo '{"decision":"allow"}'
472+ ;;
473+ *)
474+ # Silent — fall through to the normal permission prompt.
475+ exit 0
476+ ;;
477+esac
478+```
479+
480+### Inject context into file writes
481+
482+Add a reminder to the model whenever it writes a Go file:
483+
484+```json
485+{
486+ "hooks": {
487+ "PreToolUse": [
488+ {
489+ "matcher": "^(edit|write|multiedit)$",
490+ "command": "./hooks/go-context.sh"
491+ }
492+ ]
493+ }
494+}
495+```
496+
497+`hooks/go-context.sh`:
498+
499+```bash
500+#!/usr/bin/env bash
501+# Remind the model about Go formatting when editing .go files.
502+# Emit context only; stay silent on `decision` so the normal permission
503+# prompt still runs for edits/writes.
504+
505+if [[ "$CRUSH_TOOL_INPUT_FILE_PATH" == *.go ]]; then
506+ echo '{"context": "Remember: run gofumpt after editing Go files."}'
507+else
508+ echo '{}'
509+fi
510+```
511+
512+### Block all MCP tools
513+
514+The `command` can be inline. This one-liner matches all MCP tools and blocks
515+them:
516+
517+```jsonc
518+{ "matcher": "^mcp_", "command": "echo 'MCP tools are disabled' >&2; exit 2" }
519+```
520+
521+### Log every tool call
522+
523+With no `matcher` this fires for every tool. It exits 0 with no stdout so the
524+tool call always proceeds.
525+
526+```jsonc
527+{ "command": "echo \"$(date -Iseconds) $CRUSH_TOOL_NAME\" >> ./tools.log" }
528+```
529+
530+### A real-world Example:
531+
532+For a more practical example, see [`rtk-rewrite.sh`](./examples/rtk-rewrite.sh),
533+which demonstrates how to rewrite tool input using
534+[RTK](https://github.com/rtk-ai/rtk) to save tokens.
535+
536+### Using other languages
537+
538+Hooks aren't limited to shell scripts: any executable works. Here's the same
539+"block rm -rf" example in some other languages.
540+
541+#### Lua
542+
543+`{"matcher": "^bash$", "command": "lua ./hooks/no-rm-rf.lua"}`
544+
545+```lua
546+local input = io.read("*a")
547+local tool_input = input:match('"command":"(.-)"') or ""
548+
549+if tool_input:match("rm%s+%-[rf][rf]%s+/") then
550+ io.stderr:write("Refusing to run rm -rf against root\n")
551+ os.exit(2)
552+end
553+```
554+
555+#### JavaScript
556+
557+`{"matcher": "^bash$", "command": "node ./hooks/no-rm-rf.js"}`
558+
559+```js
560+let input = "";
561+process.stdin.on("data", (chunk) => (input += chunk));
562+process.stdin.on("end", () => {
563+ const { tool_input: toolInput } = JSON.parse(input);
564+
565+ if (/rm\s+-[rf]{2}\s+\//.test(toolInput.command)) {
566+ process.stderr.write("Refusing to run rm -rf against root\n");
567+ process.exit(2);
568+ }
569+});
570+```
571+
572+---
573+
574+## Claude Code compatibility
575+
576+Crush hooks are broadly compatible with [Claude Code
577+hooks](https://docs.claude.com/en/docs/claude-code/hooks): the config shape,
578+stdin payload, output envelope, and exit codes line up so most Claude Code
579+hooks run under Crush unchanged. This document covers the Crush-specific API
580+only — anything not documented here isn't guaranteed to work.
581+
582+One intentional divergence: Crush treats `updated_input` as a shallow-merge
583+patch against the original `tool_input` rather than a full replacement. Keys
584+you omit are preserved. See [Output](#output) for details.
585+
586+---
587+
588+## Reference
589+
590+This is the official reference of the narrative above. If prose and this section
591+disagree, the prose should be presumed canonical for intent, while this section
592+is canonical for shape.
593+
594+Both the stdin payload and the output envelope have **common fields** that apply
595+to every event and **per-event fields** that only some events recognize. When an
596+event doesn't understand a field, it's ignored.
597+
598+### Hook config
599+
600+Each entry under a `hooks.<EventName>` array:
601+
602+```jsonc
603+{
604+ // string. Optional. Friendly display name shown in the TUI. Falls back to
605+ // command when omitted.
606+ "name": "no-rm-rf",
607+
608+ // string. Optional. Regex tested against the tool name. Omit to match all.
609+ "matcher": "^bash$",
610+
611+ // string. Required. Shell command to run.
612+ "command": "./hooks/my-hook.sh",
613+
614+ // number. Optional. Seconds before the hook is killed. Defaults to 30.
615+ "timeout": 10,
616+}
617+```
618+
619+### Stdin payload (common)
620+
621+Present in every hook event:
622+
623+```jsonc
624+{
625+ // string. Hook event name.
626+ "event": "PreToolUse",
627+
628+ // string. Current session ID.
629+ "session_id": "313909e",
630+
631+ // string. Working directory when invoked.
632+ "cwd": "/home/user/project",
633+}
634+```
635+
636+### Stdin payload — PreToolUse
637+
638+Extends the common payload:
639+
640+```jsonc
641+{
642+ // ...common fields...
643+
644+ // string. The tool being called.
645+ "tool_name": "bash",
646+
647+ // object. Raw JSON input the model sent to the tool. Shape is per-tool.
648+ "tool_input": {
649+ "command": "npm test",
650+ },
651+}
652+```
653+
654+### Output envelope (common)
655+
656+Fields a hook may print to stdout on exit 0. All are optional and apply to every
657+event:
658+
659+```jsonc
660+{
661+ // number. Defaults to 1. Unknown higher values still parse; exists for
662+ // forward-compat.
663+ "version": 1,
664+
665+ // boolean. If true, ends the turn entirely. User takes over.
666+ "halt": false,
667+
668+ // string. Shown when denying (to the model) or halting (to the model and
669+ // user).
670+ "reason": "not allowed",
671+
672+ // string | string[]. Appended to what the model sees. Empty entries are
673+ // dropped.
674+ "context": "Rewrote with RTK",
675+}
676+```
677+
678+### Output envelope — PreToolUse
679+
680+Extends the common envelope:
681+
682+```jsonc
683+{
684+ // ...common fields...
685+
686+ // "allow" | "deny" | null. null/omitted = no opinion, the tool still goes
687+ // through the normal permission prompt. "allow" is affirmative: pre-approves
688+ // the tool call and bypasses the prompt. "deny" blocks the call; the model
689+ // sees the error and may try something else.
690+ "decision": "allow",
691+
692+ // object. Shallow-merge patch against tool_input. Nested objects are
693+ // replaced wholesale, not deep-merged.
694+ "updated_input": {
695+ "command": "bun test",
696+ },
697+}
698+```
699+
700+### Exit codes
701+
702+| Code | Meaning |
703+| ----- | ------------------------------------------------------------------------ |
704+| `0` | Success. Stdout is parsed as the output envelope. |
705+| `2` | Block this tool call. Stderr becomes the deny reason. Stdout is ignored. |
706+| `49` | Halt the whole turn. Stderr becomes the halt reason. Stdout is ignored. |
707+| other | Non-blocking error. Logged and ignored; the tool call proceeds. |
708+
709+Exit `2` only applies to events that can block something. On events where
710+there's nothing to block, it's treated as a non-blocking error.
711+
712+### Aggregation
713+
714+When multiple hooks match the same event, results compose in **config order**.
715+
716+Universal rules:
717+
718+1. `halt` is sticky: if any hook halts, the turn ends.
719+2. `reason` values concatenate with `\n` in config order. Halt-only hooks
720+ without a deny still contribute their reason.
721+3. `context` values concatenate with `\n` in config order. String entries and
722+ array entries flatten uniformly.
723+
724+PreToolUse-specific rules:
725+
726+4. `decision` precedence: `deny` > `allow` > `null`. First deny determines the
727+ outcome; subsequent allows don't override. If the final aggregated decision
728+ is `allow`, Crush pre-approves the tool call and skips the permission
729+ prompt. If it's `null` (no hook allowed), the tool goes through the normal
730+ permission flow.
731+5. `updated_input` patches shallow-merge sequentially against the original
732+ `tool_input`. Later patches override earlier ones on colliding keys. Patches
733+ are **ignored** if the final decision is deny or halt.
734+
735+### Environment variables
736+
737+See [Environment Variables](#environment-variables) above for the full list.
738+
739+---
740+
741+## Whatcha think?
742+
743+We'd love to hear your thoughts on this project. Need help? We gotchu. You can
744+find us on:
745+
746+- [Twitter](https://twitter.com/charmcli)
747+- [Slack](https://charm.land/slack)
748+- [Discord](https://charm.land/discord)
749+- [The Fediverse](https://mastodon.social/@charmcli)
750+- [Bluesky](https://bsky.app/profile/charm.land)
751+
752+---
753+
754+Part of [Charm](https://charm.land).
755+
756+<a href="https://charm.land/"><img alt="The Charm logo" width="400" src="https://stuff.charm.sh/charm-banner-softy.jpg" /></a>
757+
758+<!--prettier-ignore-->
759+Charm热爱开源 • Charm loves open source
docs/hooks/examples/rtk-rewrite.shnew file+60
@@ -0,0 +1,60 @@
1+#!/usr/bin/env bash
2+
3+# RTK hook for Crush
4+# This hook rewrites bash commands to use rtk for token savings.
5+#
6+# https://github.com/rtk-ai/rtk
7+#
8+# Requires: rtk >= 0.23.0, jq
9+#
10+# All rewrite logic lives in `rtk rewrite`, which is the single source of
11+# truth. To add or change rewrite rules, edit the Rust registry, not this
12+# file.
13+#
14+# Exit code protocol for `rtk rewrite`:
15+# 0 + stdout Rewrite found → allow with updated input
16+# 1 No RTK equivalent → pass through unchanged
17+# 2 Deny rule matched → pass through
18+
19+set -euo pipefail
20+
21+if ! command -v jq &>/dev/null; then
22+ echo "[rtk] WARNING: jq is not installed. Install: https://jqlang.github.io/jq/download/" >&2
23+ exit 0
24+fi
25+
26+if ! command -v rtk &>/dev/null; then
27+ echo "[rtk] WARNING: rtk is not installed. Install: https://github.com/rtk-ai/rtk#installation" >&2
28+ exit 0
29+fi
30+
31+# Version guard: rtk rewrite requires >= 0.23.0.
32+RTK_VERSION=$(rtk --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
33+if [ -n "$RTK_VERSION" ]; then
34+ MAJOR=$(echo "$RTK_VERSION" | cut -d. -f1)
35+ MINOR=$(echo "$RTK_VERSION" | cut -d. -f2)
36+ if [ "$MAJOR" -eq 0 ] && [ "$MINOR" -lt 23 ]; then
37+ echo "[rtk] WARNING: rtk $RTK_VERSION is too old (need >= 0.23.0). Upgrade: cargo install rtk" >&2
38+ exit 0
39+ fi
40+fi
41+
42+CMD="${CRUSH_TOOL_INPUT_COMMAND:-}"
43+if [ -z "$CMD" ]; then
44+ exit 0
45+fi
46+
47+REWRITTEN=$(rtk rewrite "$CMD" 2>/dev/null) && EXIT_CODE=0 || EXIT_CODE=$?
48+
49+case $EXIT_CODE in
50+0 | 3)
51+ # Rewrite found. If identical, the command already uses rtk.
52+ [ "$CMD" = "$REWRITTEN" ] && exit 0
53+ jq -n --arg cmd "$REWRITTEN" \
54+ '{decision: "allow", updated_input: ({command: $cmd} | tostring)}'
55+ ;;
56+*)
57+ # No rewrite (1), deny (2), or unexpected — pass through.
58+ exit 0
59+ ;;
60+esac
flake.locknew file+60
@@ -0,0 +1,60 @@
1+{
2+ "nodes": {
3+ "flake-utils": {
4+ "inputs": {
5+ "systems": "systems"
6+ },
7+ "locked": {
8+ "lastModified": 1731533236,
9+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
10+ "owner": "numtide",
11+ "repo": "flake-utils",
12+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
13+ "type": "github"
14+ },
15+ "original": {
16+ "owner": "numtide",
17+ "repo": "flake-utils",
18+ "type": "github"
19+ }
20+ },
21+ "nixpkgs": {
22+ "locked": {
23+ "lastModified": 1782964654,
24+ "narHash": "sha256-oqyac50OyRdni5ZK9H7ZuAJoR3LzgsOdUcbBlUsk9lg=",
25+ "owner": "NixOS",
26+ "repo": "nixpkgs",
27+ "rev": "3130a1cf8f7c794ea5a4760c3fa4c745d64ec269",
28+ "type": "github"
29+ },
30+ "original": {
31+ "owner": "NixOS",
32+ "repo": "nixpkgs",
33+ "type": "github"
34+ }
35+ },
36+ "root": {
37+ "inputs": {
38+ "flake-utils": "flake-utils",
39+ "nixpkgs": "nixpkgs"
40+ }
41+ },
42+ "systems": {
43+ "locked": {
44+ "lastModified": 1681028828,
45+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
46+ "owner": "nix-systems",
47+ "repo": "default",
48+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
49+ "type": "github"
50+ },
51+ "original": {
52+ "owner": "nix-systems",
53+ "repo": "default",
54+ "type": "github"
55+ }
56+ }
57+ },
58+ "root": "root",
59+ "version": 7
60+}
flake.nixnew file+75
@@ -0,0 +1,75 @@
1+{
2+ description = "Crush development environment";
3+
4+ inputs = {
5+ nixpkgs.url = "github:NixOS/nixpkgs";
6+ flake-utils.url = "github:numtide/flake-utils";
7+ };
8+
9+ outputs = {
10+ self,
11+ nixpkgs,
12+ flake-utils,
13+ }:
14+ flake-utils.lib.eachDefaultSystem (
15+ system: let
16+ pkgs = nixpkgs.legacyPackages.${system};
17+ version = "devel";
18+ in {
19+ packages.default = pkgs.buildGoModule {
20+ pname = "crush";
21+ inherit version;
22+
23+ src = ./.;
24+
25+ vendorHash = null;
26+
27+ # Match the Go toolchain used in the dev shell.
28+ go = pkgs.go_1_26;
29+
30+ env.CGO_ENABLED = 0;
31+
32+ ldflags = [
33+ "-s"
34+ "-w"
35+ "-X github.com/charmbracelet/crush/internal/version.Version=${version}"
36+ ];
37+
38+ # The test suite requires network access and external tools.
39+ doCheck = false;
40+
41+ meta = {
42+ description = "Terminal-based AI coding assistant";
43+ homepage = "https://github.com/charmbracelet/crush";
44+ license = pkgs.lib.licenses.mit;
45+ mainProgram = "crush";
46+ };
47+ };
48+
49+ devShells.default = pkgs.mkShell {
50+ buildInputs = with pkgs; [
51+ # Go toolchain
52+ go_1_26
53+
54+ # Development tools
55+ gopls # Go language server
56+ golangci-lint # Linter
57+ gofumpt # Formatter (stricter than gofmt)
58+ go-task # Task runner
59+ delve # Go debugger
60+
61+ # Additional tools
62+ git # Version control
63+ gh # GitHub CLI
64+ svu # Semantic version utility
65+ sqlc # SQL code generator
66+ ];
67+
68+ shellHook = ''
69+ # Set Go environment variables
70+ export CGO_ENABLED=0
71+ '';
72+ };
73+ }
74+ );
75+}
go.mod+162−111
@@ -1,119 +1,159 @@
11module github.com/charmbracelet/crush
22
3−go 1.25.0
3+go 1.26.4
44
55require (
6− charm.land/fantasy v0.0.0
6+ charm.land/bubbles/v2 v2.1.1
7+ charm.land/bubbletea/v2 v2.0.8
8+ charm.land/catwalk v0.49.0
9+ charm.land/fang/v2 v2.0.1
10+ charm.land/fantasy v0.35.0
11+ charm.land/glamour/v2 v2.0.1
12+ charm.land/lipgloss/v2 v2.0.5
13+ charm.land/log/v2 v2.0.0
14+ charm.land/x/vcr v0.1.1
715 github.com/JohannesKaufmann/html-to-markdown v1.6.0
816 github.com/MakeNowJust/heredoc v1.0.0
9− github.com/PuerkitoBio/goquery v1.10.3
10− github.com/alecthomas/chroma/v2 v2.20.0
11− github.com/atotto/clipboard v0.1.4
12− github.com/aymanbagabas/go-udiff v0.3.1
13− github.com/bmatcuk/doublestar/v4 v4.9.1
17+ github.com/Microsoft/go-winio v0.6.2
18+ github.com/PuerkitoBio/goquery v1.12.0
19+ github.com/alecthomas/chroma/v2 v2.27.0
20+ github.com/aymanbagabas/go-udiff v0.4.1
21+ github.com/bmatcuk/doublestar/v4 v4.10.0
1422 github.com/charlievieth/fastwalk v1.0.14
15− github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250820203609-601216f68ee2
16− github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20251011205917-3b687ffc1619
17− github.com/charmbracelet/catwalk v0.6.5-0.20251015124117-3bfe9eb6d20f
18− github.com/charmbracelet/fang v0.4.3
19− github.com/charmbracelet/glamour/v2 v2.0.0-20250811143442-a27abb32f018
20− github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3.0.20250917201909-41ff0bf215ea
21− github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706
22− github.com/charmbracelet/x/ansi v0.10.2
23− github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3
24− github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a
23+ github.com/charmbracelet/colorprofile v0.4.3
24+ github.com/charmbracelet/openai-go v0.0.0-20260617131321-5e4b9c18c4be
25+ github.com/charmbracelet/ultraviolet v0.0.0-20260703014108-f5a850f9c2b7
26+ github.com/charmbracelet/x/ansi v0.11.7
27+ github.com/charmbracelet/x/editor v0.2.0
28+ github.com/charmbracelet/x/etag v0.2.0
29+ github.com/charmbracelet/x/exp/charmtone v0.0.0-20260527151214-009e6338d40d
30+ github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f
2531 github.com/charmbracelet/x/exp/ordered v0.1.0
26− github.com/charmbracelet/x/powernap v0.0.0-20251015113943-25f979b54ad4
27− github.com/charmbracelet/x/term v0.2.1
28− github.com/disintegration/imageorient v0.0.0-20180920195336-8147d86e83ec
32+ github.com/charmbracelet/x/exp/slice v0.0.0-20260622092256-25656177ba8e
33+ github.com/charmbracelet/x/exp/strings v0.1.0
34+ github.com/charmbracelet/x/powernap v0.1.6
35+ github.com/charmbracelet/x/term v0.2.2
36+ github.com/clipperhouse/displaywidth v0.11.0
37+ github.com/clipperhouse/uax29/v2 v2.7.0
38+ github.com/denisbrodbeck/machineid v1.0.1
39+ github.com/disintegration/imaging v1.6.2
40+ github.com/dustin/go-humanize v1.0.1
41+ github.com/gen2brain/beeep v0.11.2
42+ github.com/go-git/go-git/v5 v5.19.1
2943 github.com/google/uuid v1.6.0
30− github.com/invopop/jsonschema v0.13.0
44+ github.com/invopop/jsonschema v0.14.0
45+ github.com/itchyny/gojq v0.12.19
3146 github.com/joho/godotenv v1.5.1
32− github.com/modelcontextprotocol/go-sdk v1.0.0
33− github.com/muesli/termenv v0.16.0
34− github.com/ncruces/go-sqlite3 v0.29.1
35− github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
47+ github.com/jordanella/go-ansi-paintbrush v0.0.0-20240728195301-b7ad996ecf3d
48+ github.com/lucasb-eyer/go-colorful v1.4.0
49+ github.com/mattn/go-isatty v0.0.22
50+ github.com/modelcontextprotocol/go-sdk v1.6.1
51+ github.com/ncruces/go-sqlite3 v0.35.1
3652 github.com/nxadm/tail v1.4.11
37− github.com/pressly/goose/v3 v3.25.0
38− github.com/qjebbs/go-jsons v1.0.0-alpha.4
39− github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
40− github.com/sahilm/fuzzy v0.1.1
41− github.com/spf13/cobra v1.10.1
42− github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c
43− github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
53+ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
54+ github.com/posthog/posthog-go v1.17.5
55+ github.com/pressly/goose/v3 v3.27.2
56+ github.com/qjebbs/go-jsons v1.0.0-alpha.6
57+ github.com/rivo/uniseg v0.4.7
58+ github.com/sahilm/fuzzy v0.1.3
59+ github.com/sourcegraph/jsonrpc2 v0.2.1
60+ github.com/spf13/cobra v1.10.2
4461 github.com/stretchr/testify v1.11.1
62+ github.com/swaggo/http-swagger/v2 v2.0.2
63+ github.com/swaggo/swag v1.16.6
64+ github.com/tidwall/gjson v1.19.0
4565 github.com/tidwall/sjson v1.2.5
46− github.com/zeebo/xxh3 v1.0.2
47− go.yaml.in/yaml/v4 v4.0.0-rc.2
48− gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20250923044825-7b4892dd3117
66+ github.com/zeebo/xxh3 v1.1.0
67+ go.uber.org/goleak v1.3.0
68+ golang.design/x/clipboard v0.8.0
69+ golang.org/x/net v0.56.0
70+ golang.org/x/sync v0.21.0
71+ golang.org/x/sys v0.46.0
72+ golang.org/x/text v0.38.0
4973 gopkg.in/natefinch/lumberjack.v2 v2.2.1
50− mvdan.cc/sh/v3 v3.12.1-0.20250902163504-3cf4fd5717a5
74+ gopkg.in/yaml.v3 v3.0.1
75+ modernc.org/sqlite v1.53.0
76+ mvdan.cc/sh/moreinterp v0.0.0-20250902163504-3cf4fd5717a5
77+ mvdan.cc/sh/v3 v3.13.1
5178)
5279
53−replace charm.land/fantasy => ../../fantasy/main/
54−
5580require (
56− cloud.google.com/go v0.116.0 // indirect
57− cloud.google.com/go/auth v0.17.0 // indirect
81+ cloud.google.com/go v0.123.0 // indirect
82+ cloud.google.com/go/auth v0.20.0 // indirect
5883 cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
59− cloud.google.com/go/compute/metadata v0.8.0 // indirect
84+ cloud.google.com/go/compute/metadata v0.9.0 // indirect
85+ git.sr.ht/~jackmordaunt/go-toast v1.1.2 // indirect
6086 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect
6187 github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
88+ github.com/KyleBanks/depth v1.2.1 // indirect
89+ github.com/andybalholm/brotli v1.2.1 // indirect
6290 github.com/andybalholm/cascadia v1.3.3 // indirect
63− github.com/aws/aws-sdk-go-v2 v1.39.3 // indirect
64− github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
65− github.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect
66− github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect
67− github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
68− github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
69− github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect
70− github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
71− github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
72− github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
73− github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect
74− github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
75− github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
76− github.com/aws/smithy-go v1.23.1 // indirect
77− github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
91+ github.com/atotto/clipboard v0.1.4 // indirect
92+ github.com/aws/aws-sdk-go-v2 v1.42.0 // indirect
93+ github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.13 // indirect
94+ github.com/aws/aws-sdk-go-v2/config v1.32.25 // indirect
95+ github.com/aws/aws-sdk-go-v2/credentials v1.19.24 // indirect
96+ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29 // indirect
97+ github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 // indirect
98+ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 // indirect
99+ github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 // indirect
100+ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 // indirect
101+ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29 // indirect
102+ github.com/aws/aws-sdk-go-v2/service/signin v1.2.0 // indirect
103+ github.com/aws/aws-sdk-go-v2/service/sso v1.31.3 // indirect
104+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.6 // indirect
105+ github.com/aws/aws-sdk-go-v2/service/sts v1.43.3 // indirect
106+ github.com/aws/smithy-go v1.27.3 // indirect
78107 github.com/aymerick/douceur v0.2.0 // indirect
79108 github.com/bahlo/generic-list-go v0.2.0 // indirect
80− github.com/buger/jsonparser v1.1.1 // indirect
81− github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251022202715-ec1499142678 // indirect
82− github.com/charmbracelet/colorprofile v0.3.2
83− github.com/charmbracelet/go-genai v0.0.0-20251021165952-9befde14ce97 // indirect
84− github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef
85− github.com/charmbracelet/x/cellbuf v0.0.14-0.20250811133356-e0c5dbe5ea4a // indirect
86− github.com/charmbracelet/x/exp/slice v0.0.0-20250904123553-b4e2667e5ad5
87− github.com/charmbracelet/x/json v0.2.0 // indirect
109+ github.com/buger/jsonparser v1.1.2 // indirect
110+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
111+ github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab // indirect
88112 github.com/charmbracelet/x/termios v0.1.1 // indirect
89113 github.com/charmbracelet/x/windows v0.2.2 // indirect
90− github.com/davecgh/go-spew v1.1.1 // indirect
91− github.com/denisbrodbeck/machineid v1.0.1
92− github.com/disintegration/gift v1.1.2 // indirect
93− github.com/dlclark/regexp2 v1.11.5 // indirect
94− github.com/dustin/go-humanize v1.0.1 // indirect
95− github.com/felixge/httpsnoop v1.0.4 // indirect
114+ github.com/cyphar/filepath-securejoin v0.6.1 // indirect
115+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
116+ github.com/dlclark/regexp2/v2 v2.2.1 // indirect
117+ github.com/ebitengine/purego v0.10.1 // indirect
118+ github.com/esiqveland/notify v0.13.3 // indirect
119+ github.com/felixge/httpsnoop v1.1.0 // indirect
96120 github.com/fsnotify/fsnotify v1.9.0 // indirect
121+ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
122+ github.com/go-git/go-billy/v5 v5.9.0 // indirect
123+ github.com/go-json-experiment/json v0.0.0-20260623181947-01eb4420fa68 // indirect
97124 github.com/go-logfmt/logfmt v0.6.0 // indirect
98125 github.com/go-logr/logr v1.4.3 // indirect
99126 github.com/go-logr/stdr v1.2.2 // indirect
100− github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
127+ github.com/go-ole/go-ole v1.3.0 // indirect
128+ github.com/go-openapi/jsonpointer v0.19.5 // indirect
129+ github.com/go-openapi/jsonreference v0.20.0 // indirect
130+ github.com/go-openapi/spec v0.20.6 // indirect
131+ github.com/go-openapi/swag v0.19.15 // indirect
132+ github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
133+ github.com/goccy/go-json v0.10.5 // indirect
134+ github.com/goccy/go-yaml v1.19.2 // indirect
135+ github.com/godbus/dbus/v5 v5.2.2 // indirect
136+ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
101137 github.com/google/go-cmp v0.7.0 // indirect
102− github.com/google/jsonschema-go v0.3.0 // indirect
138+ github.com/google/jsonschema-go v0.4.3 // indirect
103139 github.com/google/s2a-go v0.1.9 // indirect
104− github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
105− github.com/googleapis/gax-go/v2 v2.15.0 // indirect
140+ github.com/googleapis/enterprise-certificate-proxy v0.3.17 // indirect
141+ github.com/googleapis/gax-go/v2 v2.22.0 // indirect
106142 github.com/gorilla/css v1.0.1 // indirect
107143 github.com/gorilla/websocket v1.5.3 // indirect
108144 github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
109145 github.com/inconshreveable/mousetrap v1.1.0 // indirect
110− github.com/klauspost/compress v1.18.0 // indirect
111− github.com/klauspost/cpuid/v2 v2.0.9 // indirect
146+ github.com/itchyny/timefmt-go v0.1.8 // indirect
147+ github.com/jackmordaunt/icns/v3 v3.0.1 // indirect
148+ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
149+ github.com/josharian/intern v1.0.0 // indirect
150+ github.com/kaptinlin/jsonpointer v0.4.26 // indirect
151+ github.com/kaptinlin/jsonschema v0.9.2 // indirect
152+ github.com/klauspost/compress v1.18.6 // indirect
153+ github.com/klauspost/cpuid/v2 v2.3.0 // indirect
112154 github.com/klauspost/pgzip v1.2.6 // indirect
113− github.com/lucasb-eyer/go-colorful v1.3.0
114155 github.com/mailru/easyjson v0.7.7 // indirect
115− github.com/mattn/go-isatty v0.0.20 // indirect
116− github.com/mattn/go-runewidth v0.0.17 // indirect
156+ github.com/mattn/go-runewidth v0.0.24 // indirect
117157 github.com/mfridman/interpolate v0.0.2 // indirect
118158 github.com/microcosm-cc/bluemonday v1.0.27 // indirect
119159 github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -122,49 +162,60 @@ require (
122162 github.com/muesli/mango-cobra v1.2.0 // indirect
123163 github.com/muesli/mango-pflag v0.1.0 // indirect
124164 github.com/muesli/roff v0.1.0 // indirect
165+ github.com/ncruces/go-sqlite3-wasm/v3 v3.1.35302 // indirect
166+ github.com/ncruces/go-strftime v1.0.0 // indirect
125167 github.com/ncruces/julianday v1.0.0 // indirect
126− github.com/openai/openai-go/v2 v2.7.1 // indirect
127− github.com/pierrec/lz4/v4 v4.1.22 // indirect
128− github.com/pmezard/go-difflib v1.0.0 // indirect
129− github.com/posthog/posthog-go v1.6.11
130− github.com/rivo/uniseg v0.4.7
131− github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
168+ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
169+ github.com/pb33f/ordered-map/v2 v2.3.1 // indirect
170+ github.com/pierrec/lz4/v4 v4.1.26 // indirect
171+ github.com/pjbgf/sha1cd v0.6.0 // indirect
172+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
173+ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
174+ github.com/segmentio/asm v1.2.1 // indirect
175+ github.com/segmentio/encoding v0.5.4 // indirect
176+ github.com/sergeymakinen/go-bmp v1.0.0 // indirect
177+ github.com/sergeymakinen/go-ico v1.0.0-beta.0 // indirect
132178 github.com/sethvargo/go-retry v0.3.0 // indirect
133− github.com/sourcegraph/jsonrpc2 v0.2.1 // indirect
134179 github.com/spf13/pflag v1.0.9 // indirect
135− github.com/tetratelabs/wazero v1.9.0 // indirect
136− github.com/tidwall/gjson v1.18.0 // indirect
180+ github.com/swaggo/files/v2 v2.0.0 // indirect
181+ github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect
137182 github.com/tidwall/match v1.1.1 // indirect
138183 github.com/tidwall/pretty v1.2.1 // indirect
139184 github.com/u-root/u-root v0.14.1-0.20250807200646-5e7721023dc7 // indirect
140185 github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
141− github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
142186 github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
143187 github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
144188 github.com/yuin/goldmark v1.7.8 // indirect
145189 github.com/yuin/goldmark-emoji v1.0.5 // indirect
146− go.opentelemetry.io/auto/sdk v1.1.0 // indirect
147− go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
148− go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
149− go.opentelemetry.io/otel v1.37.0 // indirect
150− go.opentelemetry.io/otel/metric v1.37.0 // indirect
151− go.opentelemetry.io/otel/trace v1.37.0 // indirect
190+ go.opentelemetry.io/auto/sdk v1.2.1 // indirect
191+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 // indirect
192+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 // indirect
193+ go.opentelemetry.io/otel v1.44.0 // indirect
194+ go.opentelemetry.io/otel/metric v1.44.0 // indirect
195+ go.opentelemetry.io/otel/trace v1.44.0 // indirect
152196 go.uber.org/multierr v1.11.0 // indirect
153− golang.org/x/crypto v0.42.0 // indirect
154− golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
155− golang.org/x/image v0.27.0 // indirect
156− golang.org/x/net v0.44.0 // indirect
157− golang.org/x/oauth2 v0.32.0 // indirect
158− golang.org/x/sync v0.17.0 // indirect
159− golang.org/x/sys v0.37.0 // indirect
160− golang.org/x/term v0.35.0 // indirect
161− golang.org/x/text v0.30.0
162− golang.org/x/time v0.12.0 // indirect
163− google.golang.org/api v0.239.0 // indirect
164− google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
165− google.golang.org/grpc v1.74.2 // indirect
166− google.golang.org/protobuf v1.36.10 // indirect
197+ go.yaml.in/yaml/v4 v4.0.0-rc.3 // indirect
198+ golang.design/x/x11 v0.2.0 // indirect
199+ golang.org/x/crypto v0.53.0 // indirect
200+ golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
201+ golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476 // indirect
202+ golang.org/x/image v0.43.0 // indirect
203+ golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f // indirect
204+ golang.org/x/mod v0.36.0 // indirect
205+ golang.org/x/oauth2 v0.36.0 // indirect
206+ golang.org/x/term v0.44.0 // indirect
207+ golang.org/x/time v0.15.0 // indirect
208+ golang.org/x/tools v0.45.0 // indirect
209+ google.golang.org/api v0.286.0 // indirect
210+ google.golang.org/genai v1.62.0 // indirect
211+ google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d // indirect
212+ google.golang.org/grpc v1.81.1 // indirect
213+ google.golang.org/protobuf v1.36.11 // indirect
214+ gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20251110073552-01de4eb40290 // indirect
167215 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
168− gopkg.in/yaml.v3 v3.0.1 // indirect
169− mvdan.cc/sh/moreinterp v0.0.0-20250902163504-3cf4fd5717a5
216+ gopkg.in/warnings.v0 v0.1.2 // indirect
217+ gopkg.in/yaml.v2 v2.4.0 // indirect
218+ modernc.org/libc v1.73.4 // indirect
219+ modernc.org/mathutil v1.7.1 // indirect
220+ modernc.org/memory v1.11.0 // indirect
170221)
go.sum+367−212
@@ -1,11 +1,31 @@
1−cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
2−cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
3−cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4=
4−cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ=
1+charm.land/bubbles/v2 v2.1.1 h1:7r55WzBxpo/R3z98hGmY7KKPd3ET6vsf0Fb9sDHOV60=
2+charm.land/bubbles/v2 v2.1.1/go.mod h1:GE6M31gaWZVXzGw73OeuTTgy4lX+OtkH0E5ymnNsHxo=
3+charm.land/bubbletea/v2 v2.0.8 h1:SxTJMhCAI3lbPmy4SgX5LWZ24AdINr4I6UEqzZvYJuY=
4+charm.land/bubbletea/v2 v2.0.8/go.mod h1:2SkdgoTXluXJHOUwAoRlRXF/28vklb1rFl6GcgV1/ss=
5+charm.land/catwalk v0.49.0 h1:pXcHh9H76VvwGqPYMZhJe5vRqMLpzGsv0anJArKw70g=
6+charm.land/catwalk v0.49.0/go.mod h1:bw6/oiChsa9Fkr8LgYn84KrbbJY2z1+m7Jmlmmv3B2A=
7+charm.land/fang/v2 v2.0.1 h1:zQCM8JQJ1JnQX/66B5jlCYBUxL2as5JXQZ2KJ6EL0mY=
8+charm.land/fang/v2 v2.0.1/go.mod h1:S1GmkpcvK+OB5w9caywUnJcsMew45Ot8FXqoz8ALrII=
9+charm.land/fantasy v0.35.0 h1:iFES7cnt3/o20T01+y2PDkHj5dHEWRFQH0vSXYzV8xo=
10+charm.land/fantasy v0.35.0/go.mod h1:rUqUhunz+c6k66L0hHd51CrXB3SSzPNKkwBrzIe6XnY=
11+charm.land/glamour/v2 v2.0.1 h1:xl+r00A4aJWU0z8fgwKd9fQQ4rsphqGUzuEiXZP5n+c=
12+charm.land/glamour/v2 v2.0.1/go.mod h1:jo9z8XqVKPeEFMVdvCRLGk++RyJ3CdUwgNr7EvXLw3k=
13+charm.land/lipgloss/v2 v2.0.5 h1:kbNxgeeUOYv5J0YdpxFjfvf3dFvqH8Aci4zB6xqFtrY=
14+charm.land/lipgloss/v2 v2.0.5/go.mod h1:9oqhxt4yxIMe6q5A4kHr44DremZk7J9UNh74GlWa5nc=
15+charm.land/log/v2 v2.0.0 h1:SY3Cey7ipx86/MBXQHwsguOT6X1exT94mmJRdzTNs+s=
16+charm.land/log/v2 v2.0.0/go.mod h1:c3cZSRqm20qUVVAR1WmS/7ab8bgha3C6G7DjPcaVZz0=
17+charm.land/x/vcr v0.1.1 h1:PXCFMUG0rPtyk35rhfzYCJEduOzWXCIbrXTFq4OF/9Q=
18+charm.land/x/vcr v0.1.1/go.mod h1:eByq2gqzWvcct/8XE2XO5KznoWEBiXH56+y2gphbltM=
19+cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
20+cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
21+cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA=
22+cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q=
523cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
624cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
7−cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA=
8−cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw=
25+cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
26+cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
27+git.sr.ht/~jackmordaunt/go-toast v1.1.2 h1:/yrfI55LRt1M7H1vkaw+NaH1+L1CDxrqDltwm5euVuE=
28+git.sr.ht/~jackmordaunt/go-toast v1.1.2/go.mod h1:jA4OqHKTQ4AFBdwrSnwnskUIIS3HYzlJSgdzCKqfavo=
929github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ=
1030github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ=
1131github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
@@ -16,129 +36,154 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mx
1636github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
1737github.com/JohannesKaufmann/html-to-markdown v1.6.0 h1:04VXMiE50YYfCfLboJCLcgqF5x+rHJnb1ssNmqpLH/k=
1838github.com/JohannesKaufmann/html-to-markdown v1.6.0/go.mod h1:NUI78lGg/a7vpEJTz/0uOcYMaibytE4BUOQS8k78yPQ=
39+github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
40+github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
1941github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
2042github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
43+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
44+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
2145github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
22−github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
23−github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y=
46+github.com/PuerkitoBio/goquery v1.12.0 h1:pAcL4g3WRXekcB9AU/y1mbKez2dbY2AajVhtkO8RIBo=
47+github.com/PuerkitoBio/goquery v1.12.0/go.mod h1:802ej+gV2y7bbIhOIoPY5sT183ZW0YFofScC4q/hIpQ=
2448github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
2549github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
26−github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw=
27−github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA=
28−github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg=
29−github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
50+github.com/alecthomas/chroma/v2 v2.27.0 h1:FodwmyOBgJULFYmDqibcp9pvfDLWdtPRh9v/r5BXYZs=
51+github.com/alecthomas/chroma/v2 v2.27.0/go.mod h1:NjJ3ciIgrqBNeIkWZ4e46nseoLDslxU1LmfCoL+wcY8=
52+github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
53+github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
54+github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro=
55+github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
3056github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
3157github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
3258github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
3359github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
3460github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
35−github.com/aws/aws-sdk-go-v2 v1.39.3 h1:h7xSsanJ4EQJXG5iuW4UqgP7qBopLpj84mpkNx3wPjM=
36−github.com/aws/aws-sdk-go-v2 v1.39.3/go.mod h1:yWSxrnioGUZ4WVv9TgMrNUeLV3PFESn/v+6T/Su8gnM=
37−github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 h1:tW1/Rkad38LA15X4UQtjXZXNKsCgkshC3EbmcUmghTg=
38−github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3/go.mod h1:UbnqO+zjqk3uIt9yCACHJ9IVNhyhOCnYk8yA19SAWrM=
39−github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=
40−github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg=
41−github.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI=
42−github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4=
43−github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
44−github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
45−github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
46−github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8=
47−github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI=
48−github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM=
49−github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
50−github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
51−github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
52−github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
53−github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
54−github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=
55−github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 h1:BXx0ZIxvrJdSgSvKTZ+yRBeSqqgPM89VPlulEcl37tM=
56−github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=
57−github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=
58−github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=
59−github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=
60−github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=
61−github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M=
62−github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
63−github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
64−github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
65−github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
66−github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
61+github.com/aws/aws-sdk-go-v2 v1.42.0 h1:XvXMJTkFQtpBKIWZnmr9ZEOc2InWM2yldjXEJ/bymhA=
62+github.com/aws/aws-sdk-go-v2 v1.42.0/go.mod h1:27+ACypSLljLAEKsCYOmrjKh83vuTRkuAe9Uv/3A4bg=
63+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.13 h1:p1BBrg/Hhp6uK7zpejeI8QFXHJeC/mynzi04Sl03k9g=
64+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.13/go.mod h1:8cIfkE9MDhkRZGpQ22aV6/lkYeYSozpz16Smrs5x4Ls=
65+github.com/aws/aws-sdk-go-v2/config v1.32.25 h1:ACCejvStYoilgwrfegSt5ZntCbPrk52qfwyNcnl3omM=
66+github.com/aws/aws-sdk-go-v2/config v1.32.25/go.mod h1:LJyU8sDRbXUxFn8xMJIGP+v9QYYwveNLI8a/giAOiAs=
67+github.com/aws/aws-sdk-go-v2/credentials v1.19.24 h1:2hQqYCV9yqyePQ9o6dCrZc/zO8U3TwPr9mIKlZnPu/I=
68+github.com/aws/aws-sdk-go-v2/credentials v1.19.24/go.mod h1:IDwpACtwqHLISdzfwUUNq4P9DsB/h5BLg4FwJPNfqFY=
69+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29 h1:r6qZHbT+wxgWO/e9vYNUEtg7lv5+UN3pRqKhLXvnArg=
70+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29/go.mod h1:QRnaRcTVGKPGRy8w78HMQtKUGRYcnMZAANATkeVA6Mo=
71+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 h1:f3vKqSo13fhTYb+JEcXwXefZQE26I1FB5eTSniU67ko=
72+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29/go.mod h1:MzoLFUArKGpGD+ukmPiTPG1X5x4o6M2kq4v2dr1FiEc=
73+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 h1:RdwIf/CuUsvJX3RgJagbOyotl/cxoLY4xviKuE7p2GY=
74+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29/go.mod h1:71wt8W2EgswdZy9Mf9KNnzxZ3TiZlv4caKghPktDOkA=
75+github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 h1:VTGy885W5DKBxWRUJbym9hytNaYzsyaPkCHGRRMAOhU=
76+github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30/go.mod h1:AS0HycUvJRFvTt613AYDOgO2jzw+00cVSMny8XB3yMY=
77+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 h1:ZD2+BSw9vFsNlKYIasSNt3uDbjqqXIBcM13UJv/Lx2k=
78+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12/go.mod h1:Ms4zlcVBbXbiP7EVLhl+lgjvA/a7YphqQ3Ih3174EmI=
79+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29 h1:DRebniUGZ2MqiiIVmQJ04vIXr918hubdHMnarSLEWyU=
80+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.29/go.mod h1:LfRkPCD8YHDM2E5eTkos2UpwYeZnBcVarTa8L59bJHA=
81+github.com/aws/aws-sdk-go-v2/service/signin v1.2.0 h1:3nXpRcFwRCW8n7HgO2QGy0Dc20eQNfBuUemGQhpF8m8=
82+github.com/aws/aws-sdk-go-v2/service/signin v1.2.0/go.mod h1:LxYujSTLPRlp2vTtcUO/+1ilrew8ytt6SvQyOgejzFQ=
83+github.com/aws/aws-sdk-go-v2/service/sso v1.31.3 h1:ey1XLTYXb9PcLt4535632o5kCGXNXEhNb620Dqwuylo=
84+github.com/aws/aws-sdk-go-v2/service/sso v1.31.3/go.mod h1:Lk7PlmoTYryQmyBG0EXqj5BcUbj3whXdU2s3yGI3EAc=
85+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.6 h1:yLr03zQE/5Eu5l3QU0Si+xMbLMbSDF2YXsigqXngs6g=
86+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.6/go.mod h1:Q5N6icH+KJZDLh+ESNwzdv6cZ6vLFF/egy3IOxWhmz4=
87+github.com/aws/aws-sdk-go-v2/service/sts v1.43.3 h1:VrIhKRCSK1umelSgB9RghvA9RTUYeQffyAS5ApXehNI=
88+github.com/aws/aws-sdk-go-v2/service/sts v1.43.3/go.mod h1:r8wkDOuLaaMFqFiYAb8dGY2A3gJCOujMc6CFOVC4Zhc=
89+github.com/aws/smithy-go v1.27.3 h1:F3Zb497UhhskkfpJmfkXswyo+t0sh9OTBnIHjogWbVY=
90+github.com/aws/smithy-go v1.27.3/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
91+github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o=
92+github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w=
6793github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
6894github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
6995github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
7096github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
71−github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
72−github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
73−github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
74−github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
97+github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs=
98+github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
99+github.com/buger/jsonparser v1.1.2 h1:frqHqw7otoVbk5M8LlE/L7HTnIq2v9RX6EJ48i9AxJk=
100+github.com/buger/jsonparser v1.1.2/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
101+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
102+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
75103github.com/charlievieth/fastwalk v1.0.14 h1:3Eh5uaFGwHZd8EGwTjJnSpBkfwfsak9h6ICgnWlhAyg=
76104github.com/charlievieth/fastwalk v1.0.14/go.mod h1:diVcUreiU1aQ4/Wu3NbxxH4/KYdKpLDojrQ1Bb2KgNY=
77−github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251022202715-ec1499142678 h1:ruB8GXJ6K6lbuU+NhHKsqoHbU/+E+/+0kfUxhWPLvFs=
78−github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251022202715-ec1499142678/go.mod h1:8TIYxZxsuCqqeJ0lga/b91tBwrbjoHDC66Sq5t8N2R4=
79−github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250820203609-601216f68ee2 h1:973OHYuq2Jx9deyuPwe/6lsuQrDCatOsjP8uCd02URE=
80−github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250820203609-601216f68ee2/go.mod h1:6HamsBKWqEC/FVHuQMHgQL+knPyvHH55HwJDHl/adMw=
81−github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20251011205917-3b687ffc1619 h1:hjOhtqsxa+LVuCAkzhfA43wtusOaUPyQdSTg/wbRscw=
82−github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20251011205917-3b687ffc1619/go.mod h1:5IzIGXU1n0foRc8bRAherC8ZuQCQURPlwx3ANLq1138=
83−github.com/charmbracelet/catwalk v0.6.5-0.20251015124117-3bfe9eb6d20f h1:9wLwRJy2LXcq44A7DJJuctYrTptH8nUDBSCj5y2e7c8=
84−github.com/charmbracelet/catwalk v0.6.5-0.20251015124117-3bfe9eb6d20f/go.mod h1:ReU4SdrLfe63jkEjWMdX2wlZMV3k9r11oQAmzN0m+KY=
85−github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
86−github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
87−github.com/charmbracelet/fang v0.4.3 h1:qXeMxnL4H6mSKBUhDefHu8NfikFbP/MBNTfqTrXvzmY=
88−github.com/charmbracelet/fang v0.4.3/go.mod h1:wHJKQYO5ReYsxx+yZl+skDtrlKO/4LLEQ6EXsdHhRhg=
89−github.com/charmbracelet/glamour/v2 v2.0.0-20250811143442-a27abb32f018 h1:PU4Zvpagsk5sgaDxn5W4sxHuLp9QRMBZB3bFSk40A4w=
90−github.com/charmbracelet/glamour/v2 v2.0.0-20250811143442-a27abb32f018/go.mod h1:Z/GLmp9fzaqX4ze3nXG7StgWez5uBM5XtlLHK8V/qSk=
91−github.com/charmbracelet/go-genai v0.0.0-20251021165952-9befde14ce97 h1:HK7B5Q+0FidxjQD5CovniMw7axkUeMHwgVkxkbmiW/s=
92−github.com/charmbracelet/go-genai v0.0.0-20251021165952-9befde14ce97/go.mod h1:ZagL2esO4qxlOJBj0d4PVvLM82akQFtne8s3ivxBnTQ=
93−github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3.0.20250917201909-41ff0bf215ea h1:g1HfUgSMvye8mgecMD1mPscpt+pzJoDEiSA+p2QXzdQ=
94−github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3.0.20250917201909-41ff0bf215ea/go.mod h1:ngHerf1JLJXBrDXdphn5gFrBPriCL437uwukd5c93pM=
95−github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706 h1:WkwO6Ks3mSIGnGuSdKl9qDSyfbYK50z2wc2gGMggegE=
96−github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706/go.mod h1:mjJGp00cxcfvD5xdCa+bso251Jt4owrQvuimJtVmEmM=
97−github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef h1:VrWaUi2LXYLjfjCHowdSOEc6dQ9Ro14KY7Bw4IWd19M=
98−github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef/go.mod h1:AThRsQH1t+dfyOKIwXRoJBniYFQUkUpQq4paheHMc2o=
99−github.com/charmbracelet/x/ansi v0.10.2 h1:ith2ArZS0CJG30cIUfID1LXN7ZFXRCww6RUvAPA+Pzw=
100−github.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8=
101−github.com/charmbracelet/x/cellbuf v0.0.14-0.20250811133356-e0c5dbe5ea4a h1:zYSNtEJM9jwHbJts2k+Hroj+xQwsW1yxc4Wopdv7KaI=
102−github.com/charmbracelet/x/cellbuf v0.0.14-0.20250811133356-e0c5dbe5ea4a/go.mod h1:rc2bsPC6MWae3LdOxNO1mOb443NlMrrDL0xEya48NNc=
103−github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3 h1:1xwHZg6eMZ9Wv5TE1UGub6ARubyOd1Lo5kPUI/6VL50=
104−github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3/go.mod h1:T9jr8CzFpjhFVHjNjKwbAD7KwBNyFnj2pntAO7F2zw0=
105−github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a h1:FsHEJ52OC4VuTzU8t+n5frMjLvpYWEznSr/u8tnkCYw=
106−github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
105+github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab h1:J7XQLgl9sefgTnTGrmX3xqvp5o6MCiBzEjGv5igAlc4=
106+github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab/go.mod h1:hqlYqR7uPKOKfnNeicUbZp0Ps0GeYFlKYtwh5HGDCx8=
107+github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
108+github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
109+github.com/charmbracelet/openai-go v0.0.0-20260617131321-5e4b9c18c4be h1:pg+OWlIkk9HOe/8P5J95aKe2wGDzFUiiyFOUpwR30B4=
110+github.com/charmbracelet/openai-go v0.0.0-20260617131321-5e4b9c18c4be/go.mod h1:1DahUaExbUZx/jD+FNT2PKP4L9rLE5+ZBRuI8mZjd/E=
111+github.com/charmbracelet/ultraviolet v0.0.0-20260703014108-f5a850f9c2b7 h1:3FmWoGNWK4STvqg0O0Aeav2T7rodWJAPeF0QpH+8gFw=
112+github.com/charmbracelet/ultraviolet v0.0.0-20260703014108-f5a850f9c2b7/go.mod h1:f/jRa757WUmaOZrbPspXymbg/GnbF+rwe4OLsG7aXYo=
113+github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
114+github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ=
115+github.com/charmbracelet/x/editor v0.2.0 h1:7XLUKtaRaB8jN7bWU2p2UChiySyaAuIfYiIRg8gGWwk=
116+github.com/charmbracelet/x/editor v0.2.0/go.mod h1:p3oQ28TSL3YPd+GKJ1fHWcp+7bVGpedHpXmo0D6t1dY=
117+github.com/charmbracelet/x/etag v0.2.0 h1:Euj1VkheoHfTYA9y+TCwkeXF/hN8Fb9l4LqZl79pt04=
118+github.com/charmbracelet/x/etag v0.2.0/go.mod h1:C1B7/bsgvzzxpfu0Rabbd+rTHJa5TmC/qgTseCf6DF0=
119+github.com/charmbracelet/x/exp/charmtone v0.0.0-20260527151214-009e6338d40d h1:sMilwx1YIYTrQva6jsB522AoRYAerNaDIKP4ZPtUq0A=
120+github.com/charmbracelet/x/exp/charmtone v0.0.0-20260527151214-009e6338d40d/go.mod h1:nsExn0DGyX0lh9LwLHTn2Gg+hafdzfSXnC+QmEJTZFY=
121+github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA=
122+github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I=
107123github.com/charmbracelet/x/exp/ordered v0.1.0 h1:55/qLwjIh0gL0Vni+QAWk7T/qRVP6sBf+2agPBgnOFE=
108124github.com/charmbracelet/x/exp/ordered v0.1.0/go.mod h1:5UHwmG+is5THxMyCJHNPCn2/ecI07aKNrW+LcResjJ8=
109−github.com/charmbracelet/x/exp/slice v0.0.0-20250904123553-b4e2667e5ad5 h1:DTSZxdV9qQagD4iGcAt9RgaRBZtJl01bfKgdLzUzUPI=
110−github.com/charmbracelet/x/exp/slice v0.0.0-20250904123553-b4e2667e5ad5/go.mod h1:vI5nDVMWi6veaYH+0Fmvpbe/+cv/iJfMntdh+N0+Tms=
111−github.com/charmbracelet/x/json v0.2.0 h1:DqB+ZGx2h+Z+1s98HOuOyli+i97wsFQIxP2ZQANTPrQ=
112−github.com/charmbracelet/x/json v0.2.0/go.mod h1:opFIflx2YgXgi49xVUu8gEQ21teFAxyMwvOiZhIvWNM=
113−github.com/charmbracelet/x/powernap v0.0.0-20251015113943-25f979b54ad4 h1:i/XilBPYK4L1Yo/mc9FPx0SyJzIsN0y4sj1MWq9Sscc=
114−github.com/charmbracelet/x/powernap v0.0.0-20251015113943-25f979b54ad4/go.mod h1:cmdl5zlP5mR8TF2Y68UKc7hdGUDiSJ2+4hk0h04Hsx4=
115−github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
116−github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
125+github.com/charmbracelet/x/exp/slice v0.0.0-20260622092256-25656177ba8e h1:TerxTCW/3BrnpqKxeouW0cWSjZb7PsVAmtNftRAAFRE=
126+github.com/charmbracelet/x/exp/slice v0.0.0-20260622092256-25656177ba8e/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA=
127+github.com/charmbracelet/x/exp/strings v0.1.0 h1:i69S2XI7uG1u4NLGeJPSYU++Nmjvpo9nwd6aoEm7gkA=
128+github.com/charmbracelet/x/exp/strings v0.1.0/go.mod h1:/ehtMPNh9K4odGFkqYJKpIYyePhdp1hLBRvyY4bWkH8=
129+github.com/charmbracelet/x/powernap v0.1.6 h1:tsnQWQVl9arYm5S/tQVXuMJcvnkUNNkXhBWlEBDRNqM=
130+github.com/charmbracelet/x/powernap v0.1.6/go.mod h1:cmdl5zlP5mR8TF2Y68UKc7hdGUDiSJ2+4hk0h04Hsx4=
131+github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
132+github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
117133github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
118134github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
119135github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
120136github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
137+github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
138+github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
139+github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
140+github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
141+github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik=
142+github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4=
121143github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
144+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
122145github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
123146github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
147+github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
148+github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
124149github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
125−github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
126150github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
151+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
152+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
127153github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
128154github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
129−github.com/disintegration/gift v1.1.2 h1:9ZyHJr+kPamiH10FX3Pynt1AxFUob812bU9Wt4GMzhs=
130−github.com/disintegration/gift v1.1.2/go.mod h1:Jh2i7f7Q2BM7Ezno3PhfezbR1xpUg9dUg3/RlKGr4HI=
131−github.com/disintegration/imageorient v0.0.0-20180920195336-8147d86e83ec h1:YrB6aVr9touOt75I9O1SiancmR2GMg45U9UYf0gtgWg=
132−github.com/disintegration/imageorient v0.0.0-20180920195336-8147d86e83ec/go.mod h1:K0KBFIr1gWu/C1Gp10nFAcAE4hsB7JxE6OgLijrJ8Sk=
133−github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
134−github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
155+github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
156+github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
157+github.com/dlclark/regexp2/v2 v2.2.1 h1:mf4KkFUj0gJuarK8P+LgiS+Lit7m9N1yAwEfPbee7R0=
158+github.com/dlclark/regexp2/v2 v2.2.1/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU=
159+github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
160+github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
135161github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
136162github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
137−github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
138−github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
163+github.com/ebitengine/purego v0.10.1 h1:dewVBCBT2GaMu1SrNTYxQhgQBethzfhiwvZiLGP/qyY=
164+github.com/ebitengine/purego v0.10.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
165+github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA=
166+github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ=
167+github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A=
168+github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds=
169+github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0=
170+github.com/esiqveland/notify v0.13.3 h1:QCMw6o1n+6rl+oLUfg8P1IIDSFsDEb2WlXvVvIJbI/o=
171+github.com/esiqveland/notify v0.13.3/go.mod h1:hesw/IRYTO0x99u1JPweAl4+5mwXJibQVUcP0Iu5ORE=
172+github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc=
173+github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE=
139174github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
140175github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
141176github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
177+github.com/gen2brain/beeep v0.11.2 h1:+KfiKQBbQCuhfJFPANZuJ+oxsSKAYNe88hIpJuyKWDA=
178+github.com/gen2brain/beeep v0.11.2/go.mod h1:jQVvuwnLuwOcdctHn/uyh8horSBNJ8uGb9Cn2W4tvoc=
179+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
180+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
181+github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA=
182+github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw=
183+github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00=
184+github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ=
185+github.com/go-json-experiment/json v0.0.0-20260623181947-01eb4420fa68 h1:KZaTBSyshWX3MP5jukJcNSuXDQTO+rNpt0J564dX/eg=
186+github.com/go-json-experiment/json v0.0.0-20260623181947-01eb4420fa68/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg=
142187github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
143188github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
144189github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -146,27 +191,50 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
146191github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
147192github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
148193github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
194+github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
195+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
196+github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
197+github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
198+github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
199+github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
200+github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
201+github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ=
202+github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
203+github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
204+github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
205+github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
149206github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
150207github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
151−github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
152−github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
153−github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
154−github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
208+github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
209+github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
210+github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
211+github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
212+github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
213+github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
214+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
215+github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
216+github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
217+github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
218+github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
219+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
220+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
155221github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
156222github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
157223github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
158224github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
159225github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
160−github.com/google/jsonschema-go v0.3.0 h1:6AH2TxVNtk3IlvkkhjrtbUc4S8AvO0Xii0DxIygDg+Q=
161−github.com/google/jsonschema-go v0.3.0/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
226+github.com/google/jsonschema-go v0.4.3 h1:/DBOLZTfDow7pe2GmaJNhltueGTtDKICi8V8p+DQPd0=
227+github.com/google/jsonschema-go v0.4.3/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
228+github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
229+github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
162230github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
163231github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
164232github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
165233github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
166−github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
167−github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
168−github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
169−github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
234+github.com/googleapis/enterprise-certificate-proxy v0.3.17 h1:73NfMHdiqo9JFU9+7a5ExpVa10/R29pXfZIaW559nrg=
235+github.com/googleapis/enterprise-certificate-proxy v0.3.17/go.mod h1:rSEsBUemEBZEexP2y6jPp16LUmUbjmSbcPMQizR0o4k=
236+github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4=
237+github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY=
170238github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
171239github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
172240github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -178,15 +246,30 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq
178246github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
179247github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
180248github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
181−github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
182−github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
249+github.com/invopop/jsonschema v0.14.0 h1:MHQqLhvpNUZfw+hM3AZDYK7jxO8FZoQeQM77g8iyZjg=
250+github.com/invopop/jsonschema v0.14.0/go.mod h1:ygm6C2EaVNMBDPpaPlnOA2pFAxBnxGjFlMZABxm9n2I=
251+github.com/itchyny/gojq v0.12.19 h1:ttXA0XCLEMoaLOz5lSeFOZ6u6Q3QxmG46vfgI4O0DEs=
252+github.com/itchyny/gojq v0.12.19/go.mod h1:5galtVPDywX8SPSOrqjGxkBeDhSxEW1gSxoy7tn1iZY=
253+github.com/itchyny/timefmt-go v0.1.8 h1:1YEo1JvfXeAHKdjelbYr/uCuhkybaHCeTkH8Bo791OI=
254+github.com/itchyny/timefmt-go v0.1.8/go.mod h1:5E46Q+zj7vbTgWY8o5YkMeYb4I6GeWLFnetPy5oBrAI=
255+github.com/jackmordaunt/icns/v3 v3.0.1 h1:xxot6aNuGrU+lNgxz5I5H0qSeCjNKp8uTXB1j8D4S3o=
256+github.com/jackmordaunt/icns/v3 v3.0.1/go.mod h1:5sHL59nqTd2ynTnowxB/MDQFhKNqkK8X687uKNygaSQ=
257+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
258+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
183259github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
184260github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
261+github.com/jordanella/go-ansi-paintbrush v0.0.0-20240728195301-b7ad996ecf3d h1:on25kP+Sx7sxUMRQiA8gdcToAGet4DK/EIA30mXre+4=
262+github.com/jordanella/go-ansi-paintbrush v0.0.0-20240728195301-b7ad996ecf3d/go.mod h1:SV0W0APWP9MZ1/gfDQ/NzzTlWdIgYZ/ZbpN4d/UXRYw=
263+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
185264github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
186−github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
187−github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
188−github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
189−github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
265+github.com/kaptinlin/jsonpointer v0.4.26 h1:tw616yszHek+B3/GtDSia+uzBa3sLXGpmo4tYeMhBZw=
266+github.com/kaptinlin/jsonpointer v0.4.26/go.mod h1:wVOBaXGGnP42YsMb6zev/3W5POTvspdNfh8DXzf8XS8=
267+github.com/kaptinlin/jsonschema v0.9.2 h1:zqowDnBkpg80OeIt4Bl1bOyfKY1/KVVzst1m3MCsxd4=
268+github.com/kaptinlin/jsonschema v0.9.2/go.mod h1:mCH2W5lXd29tdDjvoFfY32nedPORnlk7pCVrrcs/NkQ=
269+github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
270+github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
271+github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
272+github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
190273github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
191274github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
192275github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -198,22 +281,25 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
198281github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
199282github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
200283github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
201−github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
202−github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
284+github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
285+github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
286+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
287+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
288+github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
203289github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
204290github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
205−github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
206−github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
207−github.com/mattn/go-runewidth v0.0.17 h1:78v8ZlW0bP43XfmAfPsdXcoNCelfMHsDmd/pkENfrjQ=
208−github.com/mattn/go-runewidth v0.0.17/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
291+github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
292+github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
293+github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU=
294+github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
209295github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
210296github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
211297github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
212298github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
213299github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
214300github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
215−github.com/modelcontextprotocol/go-sdk v1.0.0 h1:Z4MSjLi38bTgLrd/LjSmofqRqyBiVKRyQSJgw8q8V74=
216−github.com/modelcontextprotocol/go-sdk v1.0.0/go.mod h1:nYtYQroQ2KQiM0/SbyEPUWQ6xs4B95gJjEalc9AQyOs=
301+github.com/modelcontextprotocol/go-sdk v1.6.1 h1:0zOSupjKUxPKSocPT1Wtago+mUHU2/uZ4xSOY0FGReU=
302+github.com/modelcontextprotocol/go-sdk v1.6.1/go.mod h1:kzm3kzFL1/+AziGOE0nUs3gvPoNxMCvkxokMkuFapXQ=
217303github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
218304github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
219305github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI=
@@ -224,47 +310,62 @@ github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe
224310github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0=
225311github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8=
226312github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig=
227−github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
228−github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
229−github.com/ncruces/go-sqlite3 v0.29.1 h1:NIi8AISWBToRHyoz01FXiTNvU147Tqdibgj2tFzJCqM=
230−github.com/ncruces/go-sqlite3 v0.29.1/go.mod h1:PpccBNNhvjwUOwDQEn2gXQPFPTWdlromj0+fSkd5KSg=
231−github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
232−github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
313+github.com/ncruces/go-sqlite3 v0.35.1 h1:h/LaVyQwIvBBT0+2JmVe2tbYyWjUQ093/pYhpBqdxJo=
314+github.com/ncruces/go-sqlite3 v0.35.1/go.mod h1:fXOSIkWwN5NXgbJk+7Zls8QIW4xOflmgh11OFvcY+J0=
315+github.com/ncruces/go-sqlite3-wasm/v3 v3.1.35302 h1:Cew7/eNAMd1zhpXYBjofBua/63pFvbvB2h4PM/p6gKU=
316+github.com/ncruces/go-sqlite3-wasm/v3 v3.1.35302/go.mod h1:xe0CfafDUxfh+fSVKjHHMiAxoG9KALt5nFtbGNb/jRs=
317+github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
318+github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
233319github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
234320github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
235321github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
236322github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
323+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
237324github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
238325github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
239−github.com/openai/openai-go/v2 v2.7.1 h1:/tfvTJhfv7hTSL8mWwc5VL4WLLSDL5yn9VqVykdu9r8=
240−github.com/openai/openai-go/v2 v2.7.1/go.mod h1:jrJs23apqJKKbT+pqtFgNKpRju/KP9zpUTZhz3GElQE=
241−github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
242−github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
326+github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
327+github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
328+github.com/pb33f/ordered-map/v2 v2.3.1 h1:5319HDO0aw4DA4gzi+zv4FXU9UlSs3xGZ40wcP1nBjY=
329+github.com/pb33f/ordered-map/v2 v2.3.1/go.mod h1:qxFQgd0PkVUtOMCkTapqotNgzRhMPL7VvaHKbd1HnmQ=
330+github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY=
331+github.com/pierrec/lz4/v4 v4.1.26/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
332+github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU=
333+github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
243334github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
244335github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
245336github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
246−github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
337+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
338+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
339+github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
340+github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
247341github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
248−github.com/posthog/posthog-go v1.6.11 h1:5G8Y3pxnOpc3S4+PK1z1dCmZRuldiWxBsqqvvSfC2+w=
249−github.com/posthog/posthog-go v1.6.11/go.mod h1:LcC1Nu4AgvV22EndTtrMXTy+7RGVC0MhChSw7Qk5XkY=
250−github.com/pressly/goose/v3 v3.25.0 h1:6WeYhMWGRCzpyd89SpODFnCBCKz41KrVbRT58nVjGng=
251−github.com/pressly/goose/v3 v3.25.0/go.mod h1:4hC1KrritdCxtuFsqgs1R4AU5bWtTAf+cnWvfhf2DNY=
252−github.com/qjebbs/go-jsons v1.0.0-alpha.4 h1:Qsb4ohRUHQODIUAsJKdKJ/SIDbsO7oGOzsfy+h1yQZs=
253−github.com/qjebbs/go-jsons v1.0.0-alpha.4/go.mod h1:wNJrtinHyC3YSf6giEh4FJN8+yZV7nXBjvmfjhBIcw4=
342+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
343+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
344+github.com/posthog/posthog-go v1.17.5 h1:mrLiAdyiQpl8Yeyg23iShyAztJMaUrYzsBjKeH52Aak=
345+github.com/posthog/posthog-go v1.17.5/go.mod h1://M430hNH3e8CDv4i8SJesb26816Mpa6GIZaiP4pNQU=
346+github.com/pressly/goose/v3 v3.27.2 h1:FjKNzcmMdGrQlSIu5alMSmakQtJFBgtw+A0bb1p/LC8=
347+github.com/pressly/goose/v3 v3.27.2/go.mod h1:qWW+/8dkVtJYjJrbIpwD5xxnEJTUKvxkQ9JKQp9LaIM=
348+github.com/qjebbs/go-jsons v1.0.0-alpha.6 h1:9pMjdrCT7rj9CDIM0FXf9Ilie8PEy9g1b4qMkCnedjQ=
349+github.com/qjebbs/go-jsons v1.0.0-alpha.6/go.mod h1:wNJrtinHyC3YSf6giEh4FJN8+yZV7nXBjvmfjhBIcw4=
254350github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
255351github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
256−github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
257352github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
258353github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
259354github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
260355github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
261356github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
262−github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
263−github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
264−github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
265−github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
357+github.com/sahilm/fuzzy v0.1.3 h1:juByESSS32nVD81vr6tHmKmA/8zde7gE+x5CLxrzXPU=
358+github.com/sahilm/fuzzy v0.1.3/go.mod h1:au6//VbVSqu6DFrkL2CfjlJ5iURpNCPeE+1GwY3XsT8=
266359github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
267360github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
361+github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=
362+github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
363+github.com/segmentio/encoding v0.5.4 h1:OW1VRern8Nw6ITAtwSZ7Idrl3MXCFwXHPgqESYfvNt0=
364+github.com/segmentio/encoding v0.5.4/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0=
365+github.com/sergeymakinen/go-bmp v1.0.0 h1:SdGTzp9WvCV0A1V0mBeaS7kQAwNLdVJbmHlqNWq0R+M=
366+github.com/sergeymakinen/go-bmp v1.0.0/go.mod h1:/mxlAQZRLxSvJFNIEGGLBE/m40f3ZnUifpgVDlcUIEY=
367+github.com/sergeymakinen/go-ico v1.0.0-beta.0 h1:m5qKH7uPKLdrygMWxbamVn+tl2HfiA3K6MFJw4GfZvQ=
368+github.com/sergeymakinen/go-ico v1.0.0-beta.0/go.mod h1:wQ47mTczswBO5F0NoDt7O0IXgnV4Xy3ojrroMQzyhUk=
268369github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
269370github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
270371github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
@@ -273,25 +374,32 @@ github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah
273374github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
274375github.com/sourcegraph/jsonrpc2 v0.2.1 h1:2GtljixMQYUYCmIg7W9aF2dFmniq/mOr2T9tFRh6zSQ=
275376github.com/sourcegraph/jsonrpc2 v0.2.1/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo=
276−github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
277−github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
377+github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
378+github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
278379github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
279380github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
280−github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
281−github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
282−github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
283−github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
284381github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
382+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
383+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
285384github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
286385github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
287386github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
387+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
388+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
389+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
288390github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
289391github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
290−github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
291−github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
392+github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
393+github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
394+github.com/swaggo/http-swagger/v2 v2.0.2 h1:FKCdLsl+sFCx60KFsyM0rDarwiUSZ8DqbfSyIKC9OBg=
395+github.com/swaggo/http-swagger/v2 v2.0.2/go.mod h1:r7/GBkAWIfK6E/OLnE8fXnviHiDeAHmgIyooa4xm3AQ=
396+github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
397+github.com/swaggo/swag v1.16.6/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4Xesg=
398+github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
399+github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
292400github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
293−github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
294−github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
401+github.com/tidwall/gjson v1.19.0 h1:xwxm7n691Uf3u5OFjzngavjGTh55KX5q/9w9xHW88JU=
402+github.com/tidwall/gjson v1.19.0/go.mod h1:V37/opeE/JbLUOfH0QTXiNez2l0RUjYUhpT4szFQAfc=
295403github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
296404github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
297405github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
@@ -303,10 +411,10 @@ github.com/u-root/u-root v0.14.1-0.20250807200646-5e7721023dc7 h1:ax+jBy7xFhh+Ka
303411github.com/u-root/u-root v0.14.1-0.20250807200646-5e7721023dc7/go.mod h1:/0Qr7qJeDwWxoKku2xKQ4Szc+SwBE3g9VE8jNiamsmc=
304412github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
305413github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
306−github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
307−github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
308414github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
309415github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
416+github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
417+github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
310418github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
311419github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
312420github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@@ -317,28 +425,35 @@ github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC
317425github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
318426github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
319427github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
320−github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
321−github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
322−go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
323−go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
324−go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
325−go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
326−go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
327−go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
328−go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
329−go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
330−go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
331−go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
332−go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
333−go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
334−go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
335−go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
336−go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
337−go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
428+github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
429+github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
430+go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
431+go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
432+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 h1:2yEATaop1/a1I4psnSLgWVPLWwCzkqWakgJy7xTDVy0=
433+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0/go.mod h1:D7J12YRapIekYyPWgGPlA/23pRmpSEZC5xJC/TTLI9U=
434+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo=
435+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI=
436+go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
437+go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
438+go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
439+go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=
440+go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=
441+go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=
442+go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=
443+go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
444+go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=
445+go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=
446+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
447+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
338448go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
339449go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
340−go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s=
341−go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
450+go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
451+go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
452+go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
453+golang.design/x/clipboard v0.8.0 h1:6VEcH28wwcSgKc+vnxHHDWiRjrakTQIAJnPUrt3aOgg=
454+golang.design/x/clipboard v0.8.0/go.mod h1:s0pwrtA3Q9fgnVtGDmP5ZK/pp55cQKB23esKsjwWhWM=
455+golang.design/x/x11 v0.2.0 h1:Uiwu2guGihsJX/ZCzpoDPFz5gR/Qntm08mvoBCmRydo=
456+golang.design/x/x11 v0.2.0/go.mod h1:/5q1mFkdc1rL8mvB7DsQFi6as4tIkBv4FXjcP07mrkE=
342457golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
343458golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
344459golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
@@ -346,17 +461,24 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
346461golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
347462golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
348463golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
349−golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
350−golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
351−golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
352−golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
353−golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
354−golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
464+golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
465+golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
466+golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
467+golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
468+golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476 h1:Wdx0vgH5Wgsw+lF//LJKmWOJBLWX6nprsMqnf99rYDE=
469+golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:ygj7T6vSGhhm/9yTpOQQNvuAUFziTH7RUiH74EoE2C8=
470+golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
471+golang.org/x/image v0.43.0 h1:FLxcP4ec2350nTfOC8ysKtqYSIFbk/QGjw1ZHNP4tsY=
472+golang.org/x/image v0.43.0/go.mod h1:rrpelvGFt+kLPAjPM4HeWPgrl0FtafueU//e5N0qk/Q=
473+golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f h1:/n+PL2HlfqeSiDCuhdBbRNlGS/g2fM4OHufalHaTVG8=
474+golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f/go.mod h1:ESkJ836Z6LpG6mTVAhA48LpfW/8fNR0ifStlH2axyfg=
355475golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
356476golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
357477golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
358478golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
359479golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
480+golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
481+golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
360482golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
361483golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
362484golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
@@ -368,10 +490,10 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
368490golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
369491golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
370492golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
371−golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
372−golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
373−golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
374−golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
493+golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
494+golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
495+golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
496+golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
375497golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
376498golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
377499golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -379,16 +501,16 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
379501golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
380502golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
381503golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
382−golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
383−golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
504+golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
505+golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
384506golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
385507golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
386508golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
387509golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
388510golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
389511golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
512+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
390513golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
391−golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
392514golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
393515golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
394516golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -396,8 +518,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
396518golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
397519golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
398520golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
399−golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
400−golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
521+golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
522+golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
401523golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
402524golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
403525golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -409,8 +531,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
409531golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
410532golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
411533golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
412−golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
413−golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
534+golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
535+golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
414536golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
415537golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
416538golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
@@ -420,52 +542,85 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
420542golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
421543golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
422544golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
423−golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
424−golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
425−golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
426−golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
545+golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
546+golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
547+golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
548+golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
427549golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
428550golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
429551golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
430552golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
431553golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
432554golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
433−golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
434−golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
555+golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
556+golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
435557golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
436−google.golang.org/api v0.239.0 h1:2hZKUnFZEy81eugPs4e2XzIJ5SOwQg0G82bpXD65Puo=
437−google.golang.org/api v0.239.0/go.mod h1:cOVEm2TpdAGHL2z+UwyS+kmlGr3bVWQQ6sYEqkKje50=
438−google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
439−google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
440−google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
441−google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
442−google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
443−google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
558+gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
559+gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
560+google.golang.org/api v0.286.0 h1:TdTXMvzYKnWV1/lPbCdbXRqBrkDqjPto22H2xeZZ8LI=
561+google.golang.org/api v0.286.0/go.mod h1:NlOlUIr8MPoIhT9Bb/oUnRuHbJOLwxb6JSYJM8Yz+jQ=
562+google.golang.org/genai v1.62.0 h1:PaBju84orf4Vbcc6OfHe4vxhxhjwulKTgOpEc3iIc00=
563+google.golang.org/genai v1.62.0/go.mod h1:mDdPDFXo1Ats7f1WXVyZgWb/CkMzFWTWJruIMy7hGIU=
564+google.golang.org/genproto v0.0.0-20260622175928-b703f567277d h1:CP5omUq8AJTiWMrPKM1WRLJ7zZeXd9OPcQD3TbBNAyY=
565+google.golang.org/genproto v0.0.0-20260622175928-b703f567277d/go.mod h1:DrwuGJgFSEVNpv3S5Q5VxhRTvdnjauw9GtvwVOEARfA=
566+google.golang.org/genproto/googleapis/api v0.0.0-20260622175928-b703f567277d h1:xr2lwHI91bn3UiXcnyzRMQjp2LRiM8wEHzwUaE0YhTs=
567+google.golang.org/genproto/googleapis/api v0.0.0-20260622175928-b703f567277d/go.mod h1:O0ZOWSrfWfJ+Z5HbwZ+wNtHsg/vk1k2C/w67eww8PfQ=
568+google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d h1:mpAgMyM9vQHxycBlDq50y1VHpfSfVwzXvrQKtYbXuUY=
569+google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
570+google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
571+google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
572+google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
573+google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
444574gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
575+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
445576gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
577+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
446578gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
447579gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
448−gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20250923044825-7b4892dd3117 h1:fbE/sTnBb9UNfE8cJsOzrYYPqVWVHb7jWH4SI1W//cM=
449−gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20250923044825-7b4892dd3117/go.mod h1:YuVT9NPq7t3oT2WpUemB0DbNL7djIjgajZycxoDLnqs=
580+gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20251110073552-01de4eb40290 h1:g3ah7zaWmw41EtOgBNXpx8zk4HYuH3OMwB+qh1Dt834=
581+gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20251110073552-01de4eb40290/go.mod h1:sbq5oMEcM4PXngbcNbHhzfCP9OdZodLhrbRYoyg09HY=
450582gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
451583gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
452584gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
453585gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
586+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
587+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
454588gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
455589gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
456590gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
457591gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
592+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
458593gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
459594gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
460−modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ=
461−modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8=
595+modernc.org/cc/v4 v4.28.4 h1:Hd/4Es+MBj+/7hSdZaisNyu6bv3V0Dp2MdllyfqaH+c=
596+modernc.org/cc/v4 v4.28.4/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
597+modernc.org/ccgo/v4 v4.34.4 h1:OVnSOWQjVKOYkFxoHYB+qQmSHK5gqMqARM+K9DpR/Ws=
598+modernc.org/ccgo/v4 v4.34.4/go.mod h1:qdKqE8FNIYyysougB1RX9MxCzp5oJOcQXSobANJ4TuE=
599+modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM=
600+modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU=
601+modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
602+modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
603+modernc.org/gc/v3 v3.1.3 h1:6QAplYyVO+KdPW3pGnqmJDUxtkec8ooEWvks/hhU3lc=
604+modernc.org/gc/v3 v3.1.3/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
605+modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
606+modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
607+modernc.org/libc v1.73.4 h1:+ra4Ui8ngyt8HDcO1FTDPWlkAh6yOdaO2yAoh8MddQA=
608+modernc.org/libc v1.73.4/go.mod h1:DXZ3eO8qMCNn2SnmTNCiC71nJ9Rcq3PsnpU6Vc4rWK8=
462609modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
463610modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
464611modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
465612modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
466−modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek=
467−modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E=
613+modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg=
614+modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
615+modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
616+modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
617+modernc.org/sqlite v1.53.0 h1:20WG8N9q4ji/dEqGk4uiI0c6OPjSeLTNYGFCc3+7c1M=
618+modernc.org/sqlite v1.53.0/go.mod h1:xoEpOIpGrgT48H5iiyt/YXPCZPEzlfmfFwtk8Lklw8s=
619+modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
620+modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
621+modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
622+modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
468623mvdan.cc/sh/moreinterp v0.0.0-20250902163504-3cf4fd5717a5 h1:mO2lyKtGwu4mGQ+Qqjx0+fd5UU5BXhX/rslFmxd5aco=
469624mvdan.cc/sh/moreinterp v0.0.0-20250902163504-3cf4fd5717a5/go.mod h1:Of9PCedbLDYT8b3EyiYG64rNnx5nOp27OLCVdDrjJyo=
470−mvdan.cc/sh/v3 v3.12.1-0.20250902163504-3cf4fd5717a5 h1:e7Z/Lgw/zMijvQBVrfh/vUDZ+9FpuSLrJDVGBuoJtuo=
471−mvdan.cc/sh/v3 v3.12.1-0.20250902163504-3cf4fd5717a5/go.mod h1:P21wo2gLLe3426sP+CmANLBaixSEbRtPl35w3YlM6dg=
625+mvdan.cc/sh/v3 v3.13.1 h1:DP3TfgZhDkT7lerUdnp6PTGKyxxzz6T+cOlY/xEvfWk=
626+mvdan.cc/sh/v3 v3.13.1/go.mod h1:lXJ8SexMvEVcHCoDvAGLZgFJ9Wsm2sulmoNEXGhYZD0=
internal/agent/.env.sample+1
@@ -1,4 +1,5 @@
11CRUSH_ANTHROPIC_API_KEY=
2+CRUSH_HYPER_API_KEY=
23CRUSH_OPENAI_API_KEY=
34CRUSH_OPENROUTER_API_KEY=
45CRUSH_ZAI_API_KEY=
internal/agent/accepted_run_test.gonew file+231
@@ -0,0 +1,231 @@
1+package agent
2+
3+import (
4+ "context"
5+ "testing"
6+
7+ "github.com/charmbracelet/crush/internal/message"
8+ "github.com/stretchr/testify/assert"
9+ "github.com/stretchr/testify/require"
10+)
11+
12+// newCancelTestAgent builds a DB-backed sessionAgent with no model. The
13+// tests here exercise the dispatch/cancel/persist paths, none of which
14+// reach agent.Stream, so a model is unnecessary.
15+func newCancelTestAgent(t *testing.T) (*sessionAgent, fakeEnv) {
16+ t.Helper()
17+ env := testEnv(t)
18+ sa := NewSessionAgent(SessionAgentOptions{
19+ Sessions: env.sessions,
20+ Messages: env.messages,
21+ }).(*sessionAgent)
22+ return sa, env
23+}
24+
25+func (a *sessionAgent) acceptedCount(sessionID string) int {
26+ c, _ := a.acceptedRuns.Get(sessionID)
27+ return c
28+}
29+
30+func (a *sessionAgent) hasPendingCancel(sessionID string) bool {
31+ mark, ok := a.cancelMark.Get(sessionID)
32+ return ok && mark > 0
33+}
34+
35+func (a *sessionAgent) pendingCancelMark(sessionID string) uint64 {
36+ mark, _ := a.cancelMark.Get(sessionID)
37+ return mark
38+}
39+
40+func TestAcceptedRun_CloseIsIdempotent(t *testing.T) {
41+ t.Parallel()
42+ sa, _ := newCancelTestAgent(t)
43+
44+ accept := sa.BeginAccepted("sid")
45+ require.Equal(t, "sid", accept.SessionID())
46+ require.Equal(t, 1, sa.acceptedCount("sid"))
47+
48+ accept.Close()
49+ require.Equal(t, 0, sa.acceptedCount("sid"))
50+
51+ // Repeated Close must not underflow the counter.
52+ accept.Close()
53+ accept.Close()
54+ require.Equal(t, 0, sa.acceptedCount("sid"))
55+}
56+
57+func TestAcceptedRun_MultipleReservations(t *testing.T) {
58+ t.Parallel()
59+ sa, _ := newCancelTestAgent(t)
60+
61+ a1 := sa.BeginAccepted("sid")
62+ a2 := sa.BeginAccepted("sid")
63+ require.Equal(t, 2, sa.acceptedCount("sid"))
64+
65+ a1.Close()
66+ require.Equal(t, 1, sa.acceptedCount("sid"))
67+
68+ a2.Close()
69+ require.Equal(t, 0, sa.acceptedCount("sid"))
70+}
71+
72+func TestAcceptedRun_NilSafe(t *testing.T) {
73+ t.Parallel()
74+ var accept *AcceptedRun
75+ require.Equal(t, "", accept.SessionID())
76+ // Must not panic.
77+ accept.Close()
78+}
79+
80+func TestCancel_IdleDoesNotRecordPendingCancel(t *testing.T) {
81+ t.Parallel()
82+ sa, _ := newCancelTestAgent(t)
83+
84+ // No accepted run, no active request: a true no-op.
85+ sa.Cancel("sid")
86+ require.False(t, sa.hasPendingCancel("sid"))
87+}
88+
89+func TestCancel_AcceptedRecordsPendingCancel(t *testing.T) {
90+ t.Parallel()
91+ sa, _ := newCancelTestAgent(t)
92+
93+ accept := sa.BeginAccepted("sid")
94+ defer accept.Close()
95+
96+ sa.Cancel("sid")
97+ require.True(t, sa.hasPendingCancel("sid"))
98+}
99+
100+func TestCancel_SecondCancelWhilePendingIsNoOp(t *testing.T) {
101+ t.Parallel()
102+ sa, _ := newCancelTestAgent(t)
103+
104+ accept := sa.BeginAccepted("sid")
105+ defer accept.Close()
106+
107+ sa.Cancel("sid")
108+ require.True(t, sa.hasPendingCancel("sid"))
109+
110+ // A second cancel while a pending cancel is already recorded must
111+ // remain a single pending cancel; one Run consumes exactly one.
112+ sa.Cancel("sid")
113+ require.True(t, sa.hasPendingCancel("sid"))
114+}
115+
116+func TestRun_CancelOnEntryPersistsCanceledTurn(t *testing.T) {
117+ t.Parallel()
118+ sa, env := newCancelTestAgent(t)
119+
120+ sess, err := env.sessions.Create(t.Context(), "session")
121+ require.NoError(t, err)
122+
123+ accept := sa.BeginAccepted(sess.ID)
124+ // A cancel arrives in the accepted-but-not-yet-active window.
125+ sa.Cancel(sess.ID)
126+ require.True(t, sa.hasPendingCancel(sess.ID))
127+
128+ result, err := sa.Run(t.Context(), SessionAgentCall{
129+ SessionID: sess.ID,
130+ Prompt: "hello",
131+ Accepted: accept,
132+ })
133+ require.NoError(t, err)
134+ require.Nil(t, result)
135+
136+ // The pending cancel was consumed and the accept released.
137+ require.False(t, sa.hasPendingCancel(sess.ID))
138+ require.Equal(t, 0, sa.acceptedCount(sess.ID))
139+
140+ msgs, err := env.messages.List(t.Context(), sess.ID)
141+ require.NoError(t, err)
142+ require.Len(t, msgs, 2)
143+ assert.Equal(t, message.User, msgs[0].Role)
144+ assert.Equal(t, message.Assistant, msgs[1].Role)
145+ assert.Equal(t, message.FinishReasonCanceled, msgs[1].FinishReason())
146+}
147+
148+func TestPersistCanceledTurn_WritesBothWhenUserMissing(t *testing.T) {
149+ t.Parallel()
150+ sa, env := newCancelTestAgent(t)
151+
152+ sess, err := env.sessions.Create(t.Context(), "session")
153+ require.NoError(t, err)
154+
155+ err = sa.persistCanceledTurn(t.Context(), SessionAgentCall{
156+ SessionID: sess.ID,
157+ Prompt: "hello",
158+ }, false)
159+ require.NoError(t, err)
160+
161+ msgs, err := env.messages.List(t.Context(), sess.ID)
162+ require.NoError(t, err)
163+ require.Len(t, msgs, 2)
164+ assert.Equal(t, message.User, msgs[0].Role)
165+ assert.Equal(t, message.Assistant, msgs[1].Role)
166+ assert.Equal(t, message.FinishReasonCanceled, msgs[1].FinishReason())
167+}
168+
169+func TestPersistCanceledTurn_WritesAssistantOnlyWhenUserCreated(t *testing.T) {
170+ t.Parallel()
171+ sa, env := newCancelTestAgent(t)
172+
173+ sess, err := env.sessions.Create(t.Context(), "session")
174+ require.NoError(t, err)
175+
176+ // Simulate PrepareStep having already created the user message.
177+ _, err = sa.createUserMessage(t.Context(), SessionAgentCall{
178+ SessionID: sess.ID,
179+ Prompt: "hello",
180+ })
181+ require.NoError(t, err)
182+
183+ err = sa.persistCanceledTurn(t.Context(), SessionAgentCall{
184+ SessionID: sess.ID,
185+ Prompt: "hello",
186+ }, true)
187+ require.NoError(t, err)
188+
189+ msgs, err := env.messages.List(t.Context(), sess.ID)
190+ require.NoError(t, err)
191+ require.Len(t, msgs, 2)
192+ assert.Equal(t, message.User, msgs[0].Role)
193+ assert.Equal(t, message.Assistant, msgs[1].Role)
194+ assert.Equal(t, message.FinishReasonCanceled, msgs[1].FinishReason())
195+}
196+
197+func TestPersistCanceledTurn_SucceedsWithCanceledContext(t *testing.T) {
198+ t.Parallel()
199+ sa, env := newCancelTestAgent(t)
200+
201+ sess, err := env.sessions.Create(t.Context(), "session")
202+ require.NoError(t, err)
203+
204+ // Simulate workspace shutdown having already canceled the run
205+ // context. WithoutCancel must let the writes through.
206+ ctx, cancel := context.WithCancel(t.Context())
207+ cancel()
208+
209+ err = sa.persistCanceledTurn(ctx, SessionAgentCall{
210+ SessionID: sess.ID,
211+ Prompt: "hello",
212+ }, false)
213+ require.NoError(t, err)
214+
215+ msgs, err := env.messages.List(t.Context(), sess.ID)
216+ require.NoError(t, err)
217+ require.Len(t, msgs, 2)
218+}
219+
220+func TestClearPendingCancel(t *testing.T) {
221+ t.Parallel()
222+ sa, _ := newCancelTestAgent(t)
223+
224+ accept := sa.BeginAccepted("sid")
225+ defer accept.Close()
226+ sa.Cancel("sid")
227+ require.True(t, sa.hasPendingCancel("sid"))
228+
229+ sa.clearPendingCancel("sid")
230+ require.False(t, sa.hasPendingCancel("sid"))
231+}
internal/agent/agent.go+1672−196
@@ -1,39 +1,89 @@
1+// Package agent is the core orchestration layer for Crush AI agents.
2+//
3+// It provides session-based AI agent functionality for managing
4+// conversations, tool execution, and message handling. It coordinates
5+// interactions between language models, messages, sessions, and tools while
6+// handling features like automatic summarization, queuing, and token
7+// management.
18package agent
29
310import (
11+ "cmp"
412 "context"
513 _ "embed"
14+ "encoding/base64"
15+ "encoding/json"
616 "errors"
717 "fmt"
818 "log/slog"
19+ "math"
20+ "net/http"
921 "os"
22+ "regexp"
1023 "strconv"
1124 "strings"
1225 "sync"
26+ "sync/atomic"
1327 "time"
1428
29+ "charm.land/catwalk/pkg/catwalk"
1530 "charm.land/fantasy"
1631 "charm.land/fantasy/providers/anthropic"
1732 "charm.land/fantasy/providers/bedrock"
1833 "charm.land/fantasy/providers/google"
1934 "charm.land/fantasy/providers/openai"
20− "github.com/charmbracelet/catwalk/pkg/catwalk"
35+ "charm.land/fantasy/providers/openrouter"
36+ "charm.land/fantasy/providers/vercel"
37+ "charm.land/lipgloss/v2"
38+ "github.com/charmbracelet/crush/internal/agent/hyper"
39+ "github.com/charmbracelet/crush/internal/agent/notify"
2140 "github.com/charmbracelet/crush/internal/agent/tools"
41+ "github.com/charmbracelet/crush/internal/agent/tools/mcp"
2242 "github.com/charmbracelet/crush/internal/config"
2343 "github.com/charmbracelet/crush/internal/csync"
2444 "github.com/charmbracelet/crush/internal/message"
25− "github.com/charmbracelet/crush/internal/permission"
45+ "github.com/charmbracelet/crush/internal/pubsub"
2646 "github.com/charmbracelet/crush/internal/session"
47+ "github.com/charmbracelet/crush/internal/stringext"
48+ "github.com/charmbracelet/crush/internal/version"
49+ "github.com/charmbracelet/x/ansi"
50+ "github.com/charmbracelet/x/exp/charmtone"
2751)
2852
53+const (
54+ DefaultSessionName = "Untitled Session"
55+
56+ // Constants for auto-summarization thresholds
57+ largeContextWindowThreshold = 200_000
58+ largeContextWindowBuffer = 20_000
59+ smallContextWindowRatio = 0.2
60+)
61+
62+var userAgent = fmt.Sprintf("Charm-Crush/%s (https://charm.land/crush)", version.Version)
63+
2964//go:embed templates/title.md
3065var titlePrompt []byte
3166
3267//go:embed templates/summary.md
3368var summaryPrompt []byte
3469
70+// Used to remove <think> tags from generated titles.
71+var (
72+ thinkTagRegex = regexp.MustCompile(`(?s)<think>.*?</think>`)
73+ orphanThinkTagRegex = regexp.MustCompile(`</?think>`)
74+)
75+
3576type SessionAgentCall struct {
36− SessionID string
77+ SessionID string
78+ // RunID, when non-empty, is the caller-supplied correlator that
79+ // gets echoed back on the notify.RunComplete event emitted for
80+ // this turn. It is preserved when the call is enqueued behind a
81+ // busy session so the queued turn's terminal event is still
82+ // recognisable to the original caller. Callers that need a
83+ // reliable completion contract (e.g. `crush run` against a
84+ // session that may be busy) MUST set it; SessionID alone is
85+ // ambiguous when concurrent turns share the same session.
86+ RunID string
3787 Prompt string
3888 ProviderOptions fantasy.ProviderOptions
3989 Attachments []message.Attachment
@@ -43,95 +93,592 @@ type SessionAgentCall struct {
4393 TopK *int64
4494 FrequencyPenalty *float64
4595 PresencePenalty *float64
96+ NonInteractive bool
97+ // OnComplete, when non-nil, replaces the default RunComplete
98+ // publish path: the inner Run hands the terminal payload to this
99+ // callback instead of emitting it on the RunComplete broker. The
100+ // coordinator uses this hook to coalesce the unauthorized →
101+ // re-auth → retry chain into a single user-visible terminal
102+ // event, so non-interactive clients (e.g. `crush run`) don't
103+ // exit on a stale failed-attempt RunComplete before the
104+ // successful retry. It is intentionally stripped when queueing
105+ // a busy-session call (see Run): the originating
106+ // coordinator.Run has long returned by the time the queued
107+ // recursion drains, so falling back to the default broker
108+ // publish keeps the event visible to subscribers.
109+ OnComplete func(notify.RunComplete)
110+ // Accepted, when non-nil, is the accept reservation taken by
111+ // BeginAccepted before the call was dispatched onto a goroutine
112+ // (the client/server fire-and-forget path). Run consumes it under
113+ // dispatchMu[SessionID] once the accepted -> (cancel-on-entry |
114+ // queued | active) transition has been chosen. When nil
115+ // (in-process / local callers like AppWorkspace), behavior is
116+ // unchanged and no accept tracking applies.
117+ Accepted *AcceptedRun
118+ // acceptSeq carries the accept sequence of the handle that produced
119+ // this call after it has been enqueued and its Accepted handle
120+ // stripped. The queue-drain paths compare it against a session's
121+ // cancel mark so a follow-up queued before a cancel is dropped while
122+ // one queued after the cancel survives. 0 means untracked (an
123+ // in-process enqueue with no accept reservation), which the drain
124+ // paths treat as covered by any present mark, preserving the
125+ // pre-sequence behavior.
126+ acceptSeq uint64
46127}
47128
48129type SessionAgent interface {
49130 Run(context.Context, SessionAgentCall) (*fantasy.AgentResult, error)
131+ BeginAccepted(sessionID string) *AcceptedRun
50132 SetModels(large Model, small Model)
51133 SetTools(tools []fantasy.AgentTool)
134+ SetSystemPrompt(systemPrompt string)
52135 Cancel(sessionID string)
53136 CancelAll()
54137 IsSessionBusy(sessionID string) bool
55138 IsBusy() bool
56139 QueuedPrompts(sessionID string) int
140+ QueuedPromptsList(sessionID string) []string
57141 ClearQueue(sessionID string)
58142 Summarize(context.Context, string, fantasy.ProviderOptions) error
59143 Model() Model
144+ GenerateTitle(ctx context.Context, sessionID, userPrompt string)
60145}
61146
62147type Model struct {
63148 Model fantasy.LanguageModel
64149 CatwalkCfg catwalk.Model
65150 ModelCfg config.SelectedModel
151+ FlatRate bool
66152}
67153
68154type sessionAgent struct {
69− largeModel Model
70− smallModel Model
71− systemPrompt string
72− tools []fantasy.AgentTool
155+ largeModel *csync.Value[Model]
156+ smallModel *csync.Value[Model]
157+ systemPromptPrefix *csync.Value[string]
158+ systemPrompt *csync.Value[string]
159+ tools *csync.Slice[fantasy.AgentTool]
160+ toolsGen atomic.Uint64 // bumped by SetTools; lets PrepareStep skip re-copying unchanged tools
161+
162+ isSubAgent bool
73163 sessions session.Service
74164 messages message.Service
75165 disableAutoSummarize bool
166+ isYolo bool
167+ notify pubsub.Publisher[notify.Notification]
168+ runComplete pubsub.Publisher[notify.RunComplete]
76169
77170 messageQueue *csync.Map[string, []SessionAgentCall]
78171 activeRequests *csync.Map[string, context.CancelFunc]
172+
173+ // dispatchMu holds a per-session mutex that serializes the
174+ // accepted -> (cancel-on-entry | queued | active) transition in
175+ // Run against a concurrent Cancel. The lock is held only during
176+ // the brief handoff (no DB or LLM I/O under the lock).
177+ dispatchMu *csync.Map[string, *sync.Mutex]
178+ // acceptedRuns counts dispatched-but-not-yet-active runs per
179+ // session. A counter > 0 means a dispatched prompt is in flight
180+ // and has not yet completed the dispatch handoff in Run. Only
181+ // BeginAccepted increments it; only AcceptedRun.Close decrements
182+ // it.
183+ acceptedRuns *csync.Map[string, int]
184+ // cancelMark records, per session, a high-water accept sequence: an
185+ // accepted handle is canceled by it iff the handle's sequence is at
186+ // or below the mark. Cancel raises the mark to the latest sequence
187+ // assigned at cancel time, so a single Cancel covers every prompt
188+ // accepted-but-not-yet-active then, while a prompt accepted later
189+ // (higher sequence) is never poisoned. Absent or 0 means no pending
190+ // cancel. It is only raised by Cancel when acceptedRuns > 0, so an
191+ // idle Escape never records a mark.
192+ cancelMark *csync.Map[string, uint64]
193+ // dispatchMuCreate guards lazy creation of per-session entries in
194+ // dispatchMu so two goroutines can't race to lock different mutex
195+ // instances for the same session.
196+ dispatchMuCreate sync.Mutex
197+ // acceptedMu serializes increments/decrements of acceptedRuns and
198+ // the assignment of accept sequence numbers from acceptSeqGen. It
199+ // is separate from dispatchMu so AcceptedRun.Close (which may run
200+ // while Run holds dispatchMu for the same session) does not
201+ // deadlock by re-entering the dispatch lock.
202+ acceptedMu sync.Mutex
203+ // acceptSeqGen is the monotonic source of accept sequence numbers.
204+ // Each BeginAccepted increments it under acceptedMu and stamps the
205+ // returned handle, so sequences strictly increase in accept order
206+ // across the agent. Cancel uses its current value as the per-session
207+ // high-water mark.
208+ acceptSeqGen uint64
79209}
80210
81211type SessionAgentOptions struct {
82212 LargeModel Model
83213 SmallModel Model
214+ SystemPromptPrefix string
84215 SystemPrompt string
216+ IsSubAgent bool
85217 DisableAutoSummarize bool
218+ IsYolo bool
86219 Sessions session.Service
87220 Messages message.Service
88221 Tools []fantasy.AgentTool
222+ Notify pubsub.Publisher[notify.Notification]
223+ RunComplete pubsub.Publisher[notify.RunComplete]
89224}
90225
91226func NewSessionAgent(
92227 opts SessionAgentOptions,
93228) SessionAgent {
94229 return &sessionAgent{
95− largeModel: opts.LargeModel,
96− smallModel: opts.SmallModel,
97− systemPrompt: opts.SystemPrompt,
230+ largeModel: csync.NewValue(opts.LargeModel),
231+ smallModel: csync.NewValue(opts.SmallModel),
232+ systemPromptPrefix: csync.NewValue(opts.SystemPromptPrefix),
233+ systemPrompt: csync.NewValue(opts.SystemPrompt),
234+ isSubAgent: opts.IsSubAgent,
98235 sessions: opts.Sessions,
99236 messages: opts.Messages,
100237 disableAutoSummarize: opts.DisableAutoSummarize,
101− tools: opts.Tools,
238+ tools: csync.NewSliceFrom(opts.Tools),
239+ isYolo: opts.IsYolo,
240+ notify: opts.Notify,
241+ runComplete: opts.RunComplete,
102242 messageQueue: csync.NewMap[string, []SessionAgentCall](),
103243 activeRequests: csync.NewMap[string, context.CancelFunc](),
244+ dispatchMu: csync.NewMap[string, *sync.Mutex](),
245+ acceptedRuns: csync.NewMap[string, int](),
246+ cancelMark: csync.NewMap[string, uint64](),
104247 }
105248}
106249
107−func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy.AgentResult, error) {
108− if call.Prompt == "" {
109− return nil, ErrEmptyPrompt
250+// AcceptedRun owns exactly one accept reservation taken by
251+// BeginAccepted. It is the only carrier of accept-state across the
252+// backend.runAgent / Coordinator.Run / sessionAgent.Run layers: a
253+// counter > 0 means a dispatched prompt is in flight and has not yet
254+// completed the dispatch handoff in Run. Close is the only way to
255+// release the reservation and is idempotent.
256+type AcceptedRun struct {
257+ agent *sessionAgent
258+ sessionID string
259+ // seq is the monotonic accept sequence stamped by BeginAccepted. A
260+ // cancel covers this handle iff seq is at or below the session's
261+ // cancel mark, so a handle accepted after a cancel (higher seq) is
262+ // never poisoned by it.
263+ seq uint64
264+ done atomic.Bool
265+}
266+
267+// Close decrements the accept counter for this reservation. It is safe
268+// to call multiple times; only the first call has effect.
269+func (r *AcceptedRun) Close() {
270+ if r == nil {
271+ return
272+ }
273+ if !r.done.CompareAndSwap(false, true) {
274+ return
275+ }
276+ r.agent.endAccepted(r.sessionID)
277+}
278+
279+// SessionID exposes the session this reservation is for so the run path
280+// can use it without an extra parameter.
281+func (r *AcceptedRun) SessionID() string {
282+ if r == nil {
283+ return ""
284+ }
285+ return r.sessionID
286+}
287+
288+// BeginAccepted increments the accept counter for sessionID and returns
289+// a handle whose Close is the only way to decrement it. It is the only
290+// entry point that mutates acceptedRuns.
291+func (a *sessionAgent) BeginAccepted(sessionID string) *AcceptedRun {
292+ a.acceptedMu.Lock()
293+ defer a.acceptedMu.Unlock()
294+ count, _ := a.acceptedRuns.Get(sessionID)
295+ a.acceptedRuns.Set(sessionID, count+1)
296+ a.acceptSeqGen++
297+ return &AcceptedRun{agent: a, sessionID: sessionID, seq: a.acceptSeqGen}
298+}
299+
300+// endAccepted decrements the accept counter for sessionID. It is only
301+// called via AcceptedRun.Close. It uses a dedicated lock (not the
302+// per-session dispatch mutex) so it can run while Run holds dispatchMu
303+// for the same session without deadlocking.
304+//
305+// When the count reaches zero the session's cancel mark is dropped: no
306+// accepted handle remains for it to cover, and any handle accepted later
307+// gets a strictly higher sequence that the mark would not match anyway.
308+// Handles canceled on entry never reach RunComplete, so this is the only
309+// place that clears the mark for an all-canceled batch. Sibling handles
310+// covered by the same mark are serialized on the per-session dispatch
311+// mutex and read the mark before they Close, so this never clears it out
312+// from under a covered handle still waiting to enter Run.
313+func (a *sessionAgent) endAccepted(sessionID string) {
314+ a.acceptedMu.Lock()
315+ defer a.acceptedMu.Unlock()
316+ count, ok := a.acceptedRuns.Get(sessionID)
317+ if !ok || count <= 1 {
318+ a.acceptedRuns.Del(sessionID)
319+ a.cancelMark.Del(sessionID)
320+ return
321+ }
322+ a.acceptedRuns.Set(sessionID, count-1)
323+}
324+
325+// sessionMu returns the per-session dispatch mutex, creating it on first
326+// use. Creation is guarded so concurrent callers always observe the same
327+// mutex instance for a given session.
328+func (a *sessionAgent) sessionMu(sessionID string) *sync.Mutex {
329+ if mu, ok := a.dispatchMu.Get(sessionID); ok {
330+ return mu
331+ }
332+ a.dispatchMuCreate.Lock()
333+ defer a.dispatchMuCreate.Unlock()
334+ if mu, ok := a.dispatchMu.Get(sessionID); ok {
335+ return mu
336+ }
337+ mu := &sync.Mutex{}
338+ a.dispatchMu.Set(sessionID, mu)
339+ return mu
340+}
341+
342+// enqueueCall appends call to the session's message queue. The
343+// OnComplete hook is stripped: the caller that supplied it (typically
344+// coordinator.Run) has its own retry/coalesce scope that ends when it
345+// returns, so by the time the queue drains nobody is left to consume the
346+// buffered terminal event. The recursive Run falls back to the default
347+// broker publish, which is what existing subscribers expect for queued
348+// turns.
349+func (a *sessionAgent) enqueueCall(call SessionAgentCall) {
350+ existing, ok := a.messageQueue.Get(call.SessionID)
351+ if !ok {
352+ existing = make([]SessionAgentCall, 0, 4)
353+ }
354+ queued := call
355+ if call.Accepted != nil {
356+ // Preserve the accept sequence after the handle is stripped so
357+ // the queue-drain paths can tell a follow-up queued before a
358+ // cancel (covered by the mark) from one queued after it.
359+ queued.acceptSeq = call.Accepted.seq
360+ }
361+ queued.OnComplete = nil
362+ queued.Accepted = nil
363+ existing = append(existing, queued)
364+ a.messageQueue.Set(call.SessionID, existing)
365+}
366+
367+// drainQueueForStep partitions the session's queued calls for the current
368+// streaming step under the per-session dispatch mutex so the filtering is
369+// atomic against a concurrent Cancel: canceledBySeq requires the caller to
370+// hold that mutex, and evaluating it here (rather than after unlocking)
371+// prevents a cancel recorded between the drain and the check from being
372+// observed inconsistently.
373+//
374+// Calls covered by a pending cancel are dropped; the dropped ones that
375+// carry a RunID are returned in canceledWithRunID so the caller can
376+// publish their terminal cancelled RunComplete (a caller waiting on that
377+// RunID, e.g. `crush run`, would otherwise hang). Uncanceled calls without
378+// a RunID are returned in fold to be folded into the active turn,
379+// preserving the existing follow-up behavior. Uncanceled calls that carry
380+// a RunID are left in the queue so each runs as its own turn via the
381+// recursive run path and publishes its own RunComplete, giving every
382+// RunID-bearing prompt an explicit lifecycle instead of being silently
383+// absorbed into another turn. fold is processed by the caller without the
384+// lock held.
385+func (a *sessionAgent) drainQueueForStep(sessionID string) (fold, canceledWithRunID []SessionAgentCall) {
386+ dispatchLock := a.sessionMu(sessionID)
387+ dispatchLock.Lock()
388+ defer dispatchLock.Unlock()
389+ queuedCalls, _ := a.messageQueue.Get(sessionID)
390+ var keep []SessionAgentCall
391+ for _, queued := range queuedCalls {
392+ if a.canceledBySeq(sessionID, queued.acceptSeq) {
393+ if queued.RunID != "" {
394+ canceledWithRunID = append(canceledWithRunID, queued)
395+ }
396+ continue
397+ }
398+ if queued.RunID != "" {
399+ keep = append(keep, queued)
400+ continue
401+ }
402+ fold = append(fold, queued)
403+ }
404+ if len(keep) == 0 {
405+ a.messageQueue.Del(sessionID)
406+ } else {
407+ a.messageQueue.Set(sessionID, keep)
408+ }
409+ return fold, canceledWithRunID
410+}
411+
412+// publishCanceledQueueDrops emits a terminal cancelled RunComplete for
413+// every dropped queued call that carries a RunID. A queued prompt removed
414+// from the queue without ever running — covered by a pending cancel, or
415+// cleared by Cancel/ClearQueue — would otherwise leave a caller blocked on
416+// that RunID: `crush run` ignores live message events and exits only on a
417+// RunComplete whose RunID matches. Calls without a RunID had no such waiter
418+// and are dropped silently as before. A detached, bounded context keeps the
419+// must-deliver publish alive even when the run context that triggered the
420+// drop is already canceled.
421+func (a *sessionAgent) publishCanceledQueueDrops(drops []SessionAgentCall) {
422+ var hasRunID bool
423+ for _, d := range drops {
424+ if d.RunID != "" {
425+ hasRunID = true
426+ break
427+ }
428+ }
429+ if !hasRunID {
430+ return
431+ }
432+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
433+ defer cancel()
434+ for _, d := range drops {
435+ if d.RunID == "" {
436+ continue
437+ }
438+ a.publishRunComplete(ctx, d, notify.RunComplete{
439+ SessionID: d.SessionID,
440+ RunID: d.RunID,
441+ Cancelled: true,
442+ })
443+ }
444+}
445+
446+// clearQueueAndNotify removes all queued prompts for the session and
447+// publishes a terminal cancelled RunComplete for any that carried a RunID,
448+// so callers waiting on those RunIDs (e.g. `crush run`) are not left
449+// hanging when their queued prompt is discarded without running.
450+func (a *sessionAgent) clearQueueAndNotify(sessionID string) {
451+ queued, ok := a.messageQueue.Get(sessionID)
452+ a.messageQueue.Del(sessionID)
453+ if !ok {
454+ return
455+ }
456+ a.publishCanceledQueueDrops(queued)
457+}
458+
459+// clearPendingCancel removes any pending-cancel mark for sessionID. It
460+// takes the per-session dispatch lock so it is ordered against Cancel
461+// and the dispatch handoff.
462+func (a *sessionAgent) clearPendingCancel(sessionID string) {
463+ mu := a.sessionMu(sessionID)
464+ mu.Lock()
465+ defer mu.Unlock()
466+ a.cancelMark.Del(sessionID)
467+}
468+
469+// canceledBySeq reports whether an accepted handle or queued call with
470+// the given accept sequence is covered by a pending cancel for the
471+// session. Callers must hold the session's dispatch mutex. A tracked
472+// sequence (seq > 0) is covered only when it is at or below the cancel
473+// high-water mark, so a prompt accepted after the cancel (higher seq) is
474+// never poisoned. An untracked sequence (seq == 0, an in-process enqueue
475+// with no accept reservation) is covered whenever any mark is present,
476+// preserving the pre-sequence behavior. The mark is not consumed: it
477+// stays so every sibling handle it covers observes the same cancel, and
478+// a later handle (higher seq) ignores it regardless.
479+func (a *sessionAgent) canceledBySeq(sessionID string, seq uint64) bool {
480+ mark, ok := a.cancelMark.Get(sessionID)
481+ if !ok || mark == 0 {
482+ return false
483+ }
484+ return seq == 0 || seq <= mark
485+}
486+
487+// persistCanceledTurn writes the user/assistant records for a turn that
488+// was canceled before (or just as) streaming would have produced them.
489+// It creates the user message only when it was not already created by an
490+// earlier createUserMessage call (userMsgCreated), then writes an
491+// assistant message with FinishReasonCanceled. Both writes use
492+// context.WithoutCancel(ctx) so workspace shutdown (which cancels the run
493+// context) can't drop them.
494+func (a *sessionAgent) persistCanceledTurn(ctx context.Context, call SessionAgentCall, userMsgCreated bool) error {
495+ writeCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 5*time.Second)
496+ defer cancel()
497+ if !userMsgCreated {
498+ if _, err := a.createUserMessage(writeCtx, call); err != nil {
499+ return err
500+ }
501+ }
502+ largeModel := a.largeModel.Get()
503+ assistant, err := a.messages.Create(writeCtx, call.SessionID, message.CreateMessageParams{
504+ Role: message.Assistant,
505+ Parts: []message.ContentPart{},
506+ Model: largeModel.ModelCfg.Model,
507+ Provider: largeModel.ModelCfg.Provider,
508+ })
509+ if err != nil {
510+ return err
511+ }
512+ assistant.AddFinish(message.FinishReasonCanceled, "User canceled request", "")
513+ return a.messages.Update(writeCtx, assistant)
514+}
515+
516+// publishRunComplete emits the authoritative terminal event for a turn.
517+// It honors the per-call OnComplete hook when set (so the coordinator can
518+// coalesce retries) and otherwise falls back to the RunComplete broker.
519+// ctx is used only for the bounded-blocking must-deliver publish; the
520+// terminal payload is supplied by the caller. This is the single emit path
521+// shared by the streaming defer and the cancel-on-entry early return so a
522+// caller waiting on RunComplete (e.g. `crush run` with a RunID) always
523+// observes exactly one terminal event regardless of which Run branch ends
524+// the turn.
525+func (a *sessionAgent) publishRunComplete(ctx context.Context, call SessionAgentCall, complete notify.RunComplete) {
526+ if call.OnComplete != nil {
527+ call.OnComplete(complete)
528+ return
529+ }
530+ if a.runComplete == nil {
531+ return
532+ }
533+ a.runComplete.PublishMustDeliver(ctx, pubsub.UpdatedEvent, complete)
534+}
535+
536+// ValidateCall performs the cheap structural validation that
537+// sessionAgent.Run requires before a call can be dispatched: a call must
538+// carry either a non-empty prompt or a text attachment, and it must name a
539+// session. It is exported so callers that accept a run before dispatching it
540+// (e.g. backend.SendMessage) can apply the same checks and keep the error
541+// contract consistent.
542+func ValidateCall(call SessionAgentCall) error {
543+ if call.Prompt == "" && !message.ContainsTextAttachment(call.Attachments) {
544+ return ErrEmptyPrompt
110545 }
111546 if call.SessionID == "" {
112− return nil, ErrSessionMissing
547+ return ErrSessionMissing
113548 }
549+ return nil
550+}
114551
115− // Queue the message if busy
116− if a.IsSessionBusy(call.SessionID) {
117− existing, ok := a.messageQueue.Get(call.SessionID)
118− if !ok {
119− existing = []SessionAgentCall{}
552+func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (result *fantasy.AgentResult, retErr error) {
553+ if err := ValidateCall(call); err != nil {
554+ return nil, err
555+ }
556+
557+ // genCtx/cancel are the run context and its cancel func. For the
558+ // accepted (fire-and-forget) dispatch path they are created under
559+ // dispatchMu below so a concurrent Cancel can observe the
560+ // activeRequests entry before the assistant message exists. For
561+ // the in-process path they stay nil here and are created later,
562+ // preserving the original ordering.
563+ var (
564+ genCtx context.Context
565+ cancel context.CancelFunc
566+ activeRegistered bool
567+ userMsgCreated bool
568+ )
569+
570+ if call.Accepted != nil {
571+ // Serialize the accepted -> (cancel-on-entry | queued |
572+ // active) transition against a concurrent Cancel. Cancel takes
573+ // the same per-session lock, so every cancel observes at least
574+ // one of: a cancel mark, an activeRequests entry, or a
575+ // messageQueue entry it then clears.
576+ mu := a.sessionMu(call.SessionID)
577+ mu.Lock()
578+
579+ if a.canceledBySeq(call.SessionID, call.Accepted.seq) {
580+ // Cancel-on-entry: a cancel arrived while this run was
581+ // dispatched but not yet active, and this handle's accept
582+ // sequence is at or below the session's cancel mark. The
583+ // mark is left in place so sibling handles it also covers
584+ // observe the same cancel; release the accept reservation,
585+ // drop the lock, and persist a canceled turn without
586+ // entering Stream.
587+ //
588+ // This path returns before the streaming defer that
589+ // publishes RunComplete is installed, so emit the terminal
590+ // event explicitly. Without it, a caller waiting on
591+ // RunComplete for this RunID (e.g. `crush run`, which
592+ // ignores message events and blocks on RunComplete) would
593+ // hang on an immediately-canceled accepted run.
594+ call.Accepted.Close()
595+ mu.Unlock()
596+ complete := notify.RunComplete{
597+ SessionID: call.SessionID,
598+ RunID: call.RunID,
599+ Cancelled: true,
600+ }
601+ if err := a.persistCanceledTurn(ctx, call, false); err != nil {
602+ complete.Error = err.Error()
603+ a.publishRunComplete(ctx, call, complete)
604+ return nil, err
605+ }
606+ a.publishRunComplete(ctx, call, complete)
607+ return nil, nil
608+ }
609+
610+ if a.IsSessionBusy(call.SessionID) {
611+ // Busy: an earlier prompt is active. Queue this call and
612+ // release the accept reservation. A Cancel arriving after
613+ // this point sees the active entry and clears the queue.
614+ a.enqueueCall(call)
615+ call.Accepted.Close()
616+ mu.Unlock()
617+ return nil, nil
120618 }
121− existing = append(existing, call)
122− a.messageQueue.Set(call.SessionID, existing)
619+
620+ // Idle: become the active run. Register the cancel func before
621+ // dropping the lock so a Cancel that arrives between here and
622+ // assistant creation is not lost.
623+ runCtx := context.WithValue(ctx, tools.SessionIDContextKey, call.SessionID)
624+ genCtx, cancel = context.WithCancel(runCtx)
625+ a.activeRequests.Set(call.SessionID, cancel)
626+ activeRegistered = true
627+ call.Accepted.Close()
628+ mu.Unlock()
629+
630+ defer cancel()
631+ defer a.activeRequests.Del(call.SessionID)
632+ } else if a.IsSessionBusy(call.SessionID) {
633+ // Queue the message if busy. Strip OnComplete: the caller that
634+ // supplied the hook (typically coordinator.Run) has its own
635+ // retry/coalesce scope that ends when it returns, so by the time
636+ // the queue drains nobody is left to consume the buffered
637+ // terminal event. The recursive Run will fall back to the
638+ // default broker publish, which is what existing subscribers
639+ // expect for queued turns.
640+ a.enqueueCall(call)
123641 return nil, nil
124642 }
125643
126− if len(a.tools) > 0 {
127− // add anthropic caching to the last tool
128− a.tools[len(a.tools)-1].SetProviderOptions(a.getCacheControlOptions())
644+ // Copy mutable fields under lock to avoid races with SetTools/SetModels.
645+ agentTools := a.tools.Copy()
646+ // Per-step tool snapshot reused across PrepareStep calls; only
647+ // re-copied when SetTools bumps toolsGen (see PrepareStep below).
648+ var (
649+ stepTools []fantasy.AgentTool
650+ stepToolsGen uint64
651+ stepToolsInit bool
652+ )
653+ largeModel := a.largeModel.Get()
654+ systemPrompt := a.systemPrompt.Get()
655+ promptPrefix := a.systemPromptPrefix.Get()
656+ var instructions strings.Builder
657+
658+ for _, server := range mcp.GetStates() {
659+ if server.State != mcp.StateConnected {
660+ continue
661+ }
662+ if s := server.Client.InitializeResult().Instructions; s != "" {
663+ instructions.WriteString(s)
664+ instructions.WriteString("\n\n")
665+ }
666+ }
667+
668+ if s := instructions.String(); s != "" {
669+ systemPrompt += "\n\n<mcp-instructions>\n" + s + "\n</mcp-instructions>"
670+ }
671+
672+ if len(agentTools) > 0 {
673+ // Add Anthropic caching to the last tool.
674+ agentTools[len(agentTools)-1].SetProviderOptions(a.getCacheControlOptions())
129675 }
130676
131677 agent := fantasy.NewAgent(
132− a.largeModel.Model,
133− fantasy.WithSystemPrompt(a.systemPrompt),
134− fantasy.WithTools(a.tools...),
678+ largeModel.Model,
679+ fantasy.WithSystemPrompt(systemPrompt),
680+ fantasy.WithTools(agentTools...),
681+ fantasy.WithUserAgent(userAgent),
135682 )
136683
137684 sessionLock := sync.Mutex{}
@@ -146,56 +693,150 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
146693 }
147694
148695 var wg sync.WaitGroup
149− // Generate title if first message
150− if len(msgs) == 0 {
696+ // Generate title from the first real (non-shell) user prompt.
697+ if !hasUserTextMessage(msgs) {
698+ titleCtx := ctx // Copy to avoid race with ctx reassignment below.
151699 wg.Go(func() {
152− sessionLock.Lock()
153− a.generateTitle(ctx, &currentSession, call.Prompt)
154− sessionLock.Unlock()
700+ a.GenerateTitle(titleCtx, call.SessionID, call.Prompt)
155701 })
156702 }
703+ defer wg.Wait()
157704
158− // Add the user message to the session
705+ // Add the user message to the session.
159706 _, err = a.createUserMessage(ctx, call)
160707 if err != nil {
161708 return nil, err
162709 }
710+ userMsgCreated = true
163711
164− // add the session to the context
712+ // Add the session to the context.
165713 ctx = context.WithValue(ctx, tools.SessionIDContextKey, call.SessionID)
166714
167− genCtx, cancel := context.WithCancel(ctx)
168− a.activeRequests.Set(call.SessionID, cancel)
169−
170− defer cancel()
171− defer a.activeRequests.Del(call.SessionID)
172−
173− history, files := a.preparePrompt(msgs, call.Attachments...)
715+ // For the accepted dispatch path the run context and cancel func
716+ // were already created and registered under dispatchMu above; reuse
717+ // them. For the in-process path create them here, preserving the
718+ // original ordering.
719+ if !activeRegistered {
720+ genCtx, cancel = context.WithCancel(ctx)
721+ a.activeRequests.Set(call.SessionID, cancel)
174722
723+ defer cancel()
724+ defer a.activeRequests.Del(call.SessionID)
725+ }
726+ // skipRunComplete is set just before the queued-recursion path so
727+ // the outer Run doesn't publish a RunComplete that would race
728+ // with — and be superseded by — the recursive call's own
729+ // RunComplete (each queued user prompt is its own turn and
730+ // publishes exactly one terminal event).
731+ var skipRunComplete bool
732+ // currentAssistant is declared here so the deferred RunComplete
733+ // publish below can capture the pointer that PrepareStep will
734+ // later (re)assign for each streaming step. The final assistant
735+ // message of the turn is the value reachable through this
736+ // pointer when the defer runs.
175737 var currentAssistant *message.Message
738+ // Drain any debounced message updates before returning. message.Service
739+ // already flushes synchronously on terminal updates, but a defer here
740+ // guarantees the contract at every Run exit (success, error, panic
741+ // recovery upstream) without callers needing to know.
742+ //
743+ // After the flush completes — meaning all per-message
744+ // Publish(UpdatedEvent) calls have fired and been buffered into
745+ // every subscriber's channel — publish the authoritative
746+ // RunComplete event for this turn. The flush-then-publish order
747+ // gives well-behaved clients the best chance of seeing the final
748+ // message event before RunComplete; the embedded Text field
749+ // reconciles for clients that observe the events out of order
750+ // (the pubsub broker fan-in does not serialize publishes from
751+ // different upstream brokers).
752+ defer func() {
753+ // Use a context detached from the run context: workspace
754+ // shutdown cancels ctx before this goroutine returns, but the
755+ // buffered streaming deltas must still land before the DB is
756+ // closed. A short timeout bounds the flush.
757+ flushCtx, flushCancel := context.WithTimeout(context.WithoutCancel(ctx), 5*time.Second)
758+ defer flushCancel()
759+ if flushErr := a.messages.FlushAll(flushCtx); flushErr != nil {
760+ slog.Error("Failed to flush pending message updates after run", "error", flushErr)
761+ }
762+ if skipRunComplete {
763+ return
764+ }
765+ complete := notify.RunComplete{SessionID: call.SessionID, RunID: call.RunID}
766+ if currentAssistant != nil {
767+ complete.MessageID = currentAssistant.ID
768+ complete.Text = currentAssistant.Content().String()
769+ }
770+ if retErr != nil {
771+ complete.Error = retErr.Error()
772+ complete.Cancelled = errors.Is(retErr, context.Canceled)
773+ } else if ctx.Err() != nil {
774+ complete.Cancelled = true
775+ }
776+ // Prefer the per-call hook when supplied so the coordinator
777+ // can coalesce retries (e.g. unauthorized → re-auth → retry)
778+ // into a single user-visible terminal event. The fallback
779+ // must-deliver publish applies bounded-blocking semantics to
780+ // the authoritative terminal event so a momentarily-full
781+ // subscriber channel can't silently drop it and hang
782+ // non-interactive clients waiting on RunComplete.
783+ a.publishRunComplete(ctx, call, complete)
784+ }()
785+
786+ history, files := a.preparePrompt(msgs, largeModel.CatwalkCfg.SupportsImages, call.Attachments...)
787+
788+ startTime := time.Now()
789+ a.eventPromptSent(call.SessionID)
790+
791+ var stepMessages []fantasy.Message
176792 var shouldSummarize bool
177− result, err := agent.Stream(genCtx, fantasy.AgentStreamCall{
178− Prompt: call.Prompt,
793+ sanitizedToolCalls := make(map[string]bool)
794+ // Don't send MaxOutputTokens if 0 — some providers (e.g. LM Studio) reject it
795+ var maxOutputTokens *int64
796+ if call.MaxOutputTokens > 0 {
797+ maxOutputTokens = &call.MaxOutputTokens
798+ }
799+ result, err = agent.Stream(genCtx, fantasy.AgentStreamCall{
800+ Prompt: message.PromptWithTextAttachments(call.Prompt, call.Attachments),
179801 Files: files,
180802 Messages: history,
181803 ProviderOptions: call.ProviderOptions,
182− MaxOutputTokens: &call.MaxOutputTokens,
804+ MaxOutputTokens: maxOutputTokens,
183805 TopP: call.TopP,
184806 Temperature: call.Temperature,
185807 PresencePenalty: call.PresencePenalty,
186808 TopK: call.TopK,
187809 FrequencyPenalty: call.FrequencyPenalty,
188− // Before each step create the new assistant message
189810 PrepareStep: func(callContext context.Context, options fantasy.PrepareStepFunctionOptions) (_ context.Context, prepared fantasy.PrepareStepResult, err error) {
190811 prepared.Messages = options.Messages
191− // reset all cached items
192812 for i := range prepared.Messages {
193813 prepared.Messages[i].ProviderOptions = nil
194814 }
195815
196− queuedCalls, _ := a.messageQueue.Get(call.SessionID)
197− a.messageQueue.Del(call.SessionID)
198− for _, queued := range queuedCalls {
816+ // Use latest tools (updated by SetTools when MCP tools change).
817+ // Reuse the previous step's copy unless SetTools has bumped the
818+ // generation, so an unchanged tool set isn't re-copied every step.
819+ if gen := a.toolsGen.Load(); !stepToolsInit || gen != stepToolsGen {
820+ stepTools = a.tools.Copy()
821+ stepToolsGen = gen
822+ stepToolsInit = true
823+ }
824+ prepared.Tools = stepTools
825+
826+ // Drain queued follow-up prompts for this step. Calls covered
827+ // by a cancel recorded while they sat in the queue are dropped:
828+ // a cancel that arrived after a prompt was queued must not let
829+ // it run as part of this step. Coverage is per-call by accept
830+ // sequence so a follow-up queued after the cancel (higher seq)
831+ // is not dropped. A dropped prompt carrying a RunID still gets
832+ // its terminal cancelled RunComplete so a caller waiting on it
833+ // does not hang. Uncanceled prompts without a RunID are folded
834+ // into this turn; uncanceled prompts with a RunID are left
835+ // queued so each runs as its own turn (with its own
836+ // RunComplete) via the recursive run path below.
837+ fold, canceledRunIDs := a.drainQueueForStep(call.SessionID)
838+ a.publishCanceledQueueDrops(canceledRunIDs)
839+ for _, queued := range fold {
199840 userMessage, createErr := a.createUserMessage(callContext, queued)
200841 if createErr != nil {
201842 return callContext, prepared, createErr
@@ -203,36 +844,55 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
203844 prepared.Messages = append(prepared.Messages, userMessage.ToAIMessage()...)
204845 }
205846
847+ prepared.Messages = a.workaroundProviderMediaLimitations(prepared.Messages, largeModel)
848+
206849 lastSystemRoleInx := 0
207850 systemMessageUpdated := false
208851 for i, msg := range prepared.Messages {
209− // only add cache control to the last message
852+ // Only add cache control to the last message.
210853 if msg.Role == fantasy.MessageRoleSystem {
211854 lastSystemRoleInx = i
212855 } else if !systemMessageUpdated {
213856 prepared.Messages[lastSystemRoleInx].ProviderOptions = a.getCacheControlOptions()
214857 systemMessageUpdated = true
215858 }
216− // than add cache control to the last 2 messages
859+ // Than add cache control to the last 2 messages.
217860 if i > len(prepared.Messages)-3 {
218861 prepared.Messages[i].ProviderOptions = a.getCacheControlOptions()
219862 }
220863 }
221864
865+ if promptPrefix != "" {
866+ prepared.Messages = append([]fantasy.Message{fantasy.NewSystemMessage(promptPrefix)}, prepared.Messages...)
867+ }
868+
869+ // Save a reference to the prepared messages for token
870+ // estimation in OnStepFinish. No clone needed here — the
871+ // messages are not modified between PrepareStep and
872+ // OnStepFinish (which run sequentially), and the clone is
873+ // only needed when the provider returns zero usage.
874+ stepMessages = prepared.Messages
875+
222876 var assistantMsg message.Message
223877 assistantMsg, err = a.messages.Create(callContext, call.SessionID, message.CreateMessageParams{
224878 Role: message.Assistant,
225879 Parts: []message.ContentPart{},
226− Model: a.largeModel.ModelCfg.Model,
227− Provider: a.largeModel.ModelCfg.Provider,
880+ Model: largeModel.ModelCfg.Model,
881+ Provider: largeModel.ModelCfg.Provider,
228882 })
229883 if err != nil {
230884 return callContext, prepared, err
231885 }
232886 callContext = context.WithValue(callContext, tools.MessageIDContextKey, assistantMsg.ID)
887+ callContext = context.WithValue(callContext, tools.SupportsImagesContextKey, largeModel.CatwalkCfg.SupportsImages)
888+ callContext = context.WithValue(callContext, tools.ModelNameContextKey, largeModel.CatwalkCfg.Name)
233889 currentAssistant = &assistantMsg
234890 return callContext, prepared, err
235891 },
892+ OnReasoningStart: func(id string, reasoning fantasy.ReasoningContent) error {
893+ currentAssistant.AppendReasoningContent(reasoning.Text)
894+ return a.messages.Update(genCtx, *currentAssistant)
895+ },
236896 OnReasoningDelta: func(id string, text string) error {
237897 currentAssistant.AppendReasoningContent(text)
238898 return a.messages.Update(genCtx, *currentAssistant)
@@ -246,7 +906,7 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
246906 }
247907 if googleData, ok := reasoning.ProviderMetadata[google.Name]; ok {
248908 if reasoning, ok := googleData.(*google.ReasoningMetadata); ok {
249− currentAssistant.AppendReasoningSignature(reasoning.Signature)
909+ currentAssistant.AppendThoughtSignature(reasoning.Signature, reasoning.ToolID)
250910 }
251911 }
252912 if openaiData, ok := reasoning.ProviderMetadata[openai.Name]; ok {
@@ -258,6 +918,13 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
258918 return a.messages.Update(genCtx, *currentAssistant)
259919 },
260920 OnTextDelta: func(id string, text string) error {
921+ // Strip leading newline from initial text content. This is is
922+ // particularly important in non-interactive mode where leading
923+ // newlines are very visible.
924+ if len(currentAssistant.Parts) == 0 {
925+ text = strings.TrimPrefix(text, "\n")
926+ }
927+
261928 currentAssistant.AppendContent(text)
262929 return a.messages.Update(genCtx, *currentAssistant)
263930 },
@@ -269,59 +936,50 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
269936 Finished: false,
270937 }
271938 currentAssistant.AddToolCall(toolCall)
272− return a.messages.Update(genCtx, *currentAssistant)
939+ // Use parent ctx instead of genCtx to ensure the update succeeds
940+ // even if the request is canceled mid-stream
941+ return a.messages.Update(ctx, *currentAssistant)
273942 },
274− OnRetry: func(err *fantasy.APICallError, delay time.Duration) {
275− // TODO: implement
943+ OnRetry: func(err *fantasy.ProviderError, delay time.Duration) {
944+ slog.Warn("Provider request failed, retrying", providerRetryLogFields(err, delay)...)
276945 },
277946 OnToolCall: func(tc fantasy.ToolCallContent) error {
947+ input, wasSanitized := sanitizeToolInput(tc.ToolName, tc.ToolCallID, tc.Input)
948+ if wasSanitized {
949+ sanitizedToolCalls[tc.ToolCallID] = true
950+ }
278951 toolCall := message.ToolCall{
279952 ID: tc.ToolCallID,
280953 Name: tc.ToolName,
281− Input: tc.Input,
954+ Input: input,
282955 ProviderExecuted: false,
283956 Finished: true,
284957 }
285958 currentAssistant.AddToolCall(toolCall)
286− return a.messages.Update(genCtx, *currentAssistant)
959+ // Use parent ctx instead of genCtx to ensure the update succeeds
960+ // even if the request is canceled mid-stream
961+ return a.messages.Update(ctx, *currentAssistant)
287962 },
288963 OnToolResult: func(result fantasy.ToolResultContent) error {
289− var resultContent string
290− isError := false
291− switch result.Result.GetType() {
292− case fantasy.ToolResultContentTypeText:
293− r, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentText](result.Result)
294− if ok {
295− resultContent = r.Text
296− }
297− case fantasy.ToolResultContentTypeError:
298− r, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentError](result.Result)
299− if ok {
300− isError = true
301− resultContent = r.Error.Error()
302− }
303− case fantasy.ToolResultContentTypeMedia:
304− // TODO: handle this message type
305− }
306− toolResult := message.ToolResult{
307− ToolCallID: result.ToolCallID,
308− Name: result.ToolName,
309− Content: resultContent,
310− IsError: isError,
311− Metadata: result.ClientMetadata,
964+ toolResult := a.convertToToolResult(result)
965+ if sanitizedToolCalls[result.ToolCallID] {
966+ toolResult.Content = "Tool call failed: arguments were not valid JSON. Please check your tool call format and try again."
967+ toolResult.IsError = true
312968 }
313− _, createMsgErr := a.messages.Create(genCtx, currentAssistant.SessionID, message.CreateMessageParams{
969+ // Use parent ctx instead of genCtx to ensure the message is created
970+ // even if the request is canceled mid-stream
971+ _, createMsgErr := a.messages.Create(ctx, currentAssistant.SessionID, message.CreateMessageParams{
314972 Role: message.Tool,
315973 Parts: []message.ContentPart{
316974 toolResult,
317975 },
318976 })
319− if createMsgErr != nil {
320− return createMsgErr
321− }
322− return nil
977+ return createMsgErr
323978 },
324979 OnStepFinish: func(stepResult fantasy.StepResult) error {
980+ for _, w := range stepResult.Warnings {
981+ slog.Warn("Provider warning", "type", w.Type, "message", w.Message)
982+ }
325983 finishReason := message.FinishReasonUnknown
326984 switch stepResult.FinishReason {
327985 case fantasy.FinishReasonLength:
@@ -331,40 +989,100 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
331989 case fantasy.FinishReasonToolCalls:
332990 finishReason = message.FinishReasonToolUse
333991 }
992+ // If a tool result halted the turn (e.g. a hook halt or a
993+ // permission denial), the step ends on FinishReasonToolCalls but
994+ // the model will not be called again. Treat it as the end of the
995+ // turn so the UI can render the assistant footer.
996+ if finishReason == message.FinishReasonToolUse {
997+ for _, tr := range stepResult.Content.ToolResults() {
998+ if tr.StopTurn {
999+ finishReason = message.FinishReasonEndTurn
1000+ break
1001+ }
1002+ }
1003+ }
3341004 currentAssistant.AddFinish(finishReason, "", "")
335− a.updateSessionUsage(a.largeModel, &currentSession, stepResult.Usage)
3361005 sessionLock.Lock()
337− _, sessionErr := a.sessions.Save(genCtx, currentSession)
338− sessionLock.Unlock()
1006+ defer sessionLock.Unlock()
1007+
1008+ updatedSession, getSessionErr := a.sessions.Get(ctx, call.SessionID)
1009+ if getSessionErr != nil {
1010+ return getSessionErr
1011+ }
1012+ usage, estimated := fallbackStepUsage(stepMessages, stepResult)
1013+ a.updateSessionUsage(largeModel, &updatedSession, usage, a.openrouterCost(stepResult.ProviderMetadata), estimated)
1014+ extractHyperCredits(stepResult.ProviderMetadata)
1015+ _, sessionErr := a.sessions.Save(ctx, updatedSession)
3391016 if sessionErr != nil {
3401017 return sessionErr
3411018 }
1019+ currentSession = updatedSession
3421020 return a.messages.Update(genCtx, *currentAssistant)
3431021 },
3441022 StopWhen: []fantasy.StopCondition{
3451023 func(_ []fantasy.StepResult) bool {
346− contextWindow := a.largeModel.CatwalkCfg.ContextWindow
1024+ cw := int64(largeModel.CatwalkCfg.ContextWindow)
1025+ // If context window is unknown (0), skip auto-summarize
1026+ // to avoid immediately truncating custom/local models.
1027+ if cw == 0 {
1028+ return false
1029+ }
3471030 tokens := currentSession.CompletionTokens + currentSession.PromptTokens
348− percentage := (float64(tokens) / float64(contextWindow)) * 100
349− if (percentage > 80) && !a.disableAutoSummarize {
1031+ remaining := cw - tokens
1032+ var threshold int64
1033+ if cw > largeContextWindowThreshold {
1034+ threshold = largeContextWindowBuffer
1035+ } else {
1036+ threshold = int64(float64(cw) * smallContextWindowRatio)
1037+ }
1038+ if (remaining <= threshold) && !a.disableAutoSummarize {
3501039 shouldSummarize = true
3511040 return true
3521041 }
3531042 return false
3541043 },
1044+ func(steps []fantasy.StepResult) bool {
1045+ return hasRepeatedToolCalls(steps, loopDetectionWindowSize, loopDetectionMaxRepeats)
1046+ },
3551047 },
3561048 })
1049+
1050+ a.eventPromptResponded(call.SessionID, time.Since(startTime).Truncate(time.Second))
1051+
3571052 if err != nil {
1053+ isHyper := largeModel.ModelCfg.Provider == hyper.Name
3581054 isCancelErr := errors.Is(err, context.Canceled)
359− isPermissionErr := errors.Is(err, permission.ErrorPermissionDenied)
3601055 if currentAssistant == nil {
1056+ // Cancel-before-assistant-creation window: the run was
1057+ // canceled after activeRequests.Set but before PrepareStep
1058+ // created the assistant message. Without this, the turn
1059+ // would return with no FinishReasonCanceled marker and no
1060+ // user-visible record. The user message was already created
1061+ // above, so persistCanceledTurn only writes the assistant
1062+ // record.
1063+ if isCancelErr {
1064+ if persistErr := a.persistCanceledTurn(ctx, call, userMsgCreated); persistErr != nil {
1065+ return nil, persistErr
1066+ }
1067+ }
3611068 return result, err
3621069 }
363− // Ensure we finish thinking on error to close the reasoning state
1070+ // Persist final state with a context detached from the run
1071+ // context. The run context (ctx) is derived from the
1072+ // workspace context, which workspace shutdown cancels before
1073+ // agent goroutines finish; using ctx here would drop the
1074+ // final assistant state. WithoutCancel keeps the values
1075+ // (e.g. session ID) while ignoring cancellation, and a short
1076+ // timeout bounds the cleanup writes.
1077+ cleanupCtx, cleanupCancel := context.WithTimeout(context.WithoutCancel(ctx), 5*time.Second)
1078+ defer cleanupCancel()
1079+ // Ensure we finish thinking on error to close the reasoning state.
3641080 currentAssistant.FinishThinking()
3651081 toolCalls := currentAssistant.ToolCalls()
366− // INFO: we use the parent context here because the genCtx has been cancelled
367− msgs, createErr := a.messages.List(ctx, currentAssistant.SessionID)
1082+ // INFO: we use the cleanup context here because the genCtx has been cancelled.
1083+ // Only load messages from the current assistant message onward — tool
1084+ // results for this turn's tool calls can only exist after it.
1085+ msgs, createErr := a.messages.ListAfter(cleanupCtx, currentAssistant.SessionID, currentAssistant.ID)
3681086 if createErr != nil {
3691087 return nil, createErr
3701088 }
@@ -373,7 +1091,7 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
3731091 tc.Finished = true
3741092 tc.Input = "{}"
3751093 currentAssistant.AddToolCall(tc)
376− updateErr := a.messages.Update(ctx, *currentAssistant)
1094+ updateErr := a.messages.Update(cleanupCtx, *currentAssistant)
3771095 if updateErr != nil {
3781096 return nil, updateErr
3791097 }
@@ -398,9 +1116,7 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
3981116 }
3991117 content := "There was an error while executing the tool"
4001118 if isCancelErr {
401− content = "Tool execution canceled by user"
402− } else if isPermissionErr {
403− content = "Permission denied"
1119+ content = "Error: user cancelled assistant tool calling"
4041120 }
4051121 toolResult := message.ToolResult{
4061122 ToolCallID: tc.ID,
@@ -408,7 +1124,7 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
4081124 Content: content,
4091125 IsError: true,
4101126 }
411− _, createErr = a.messages.Create(context.Background(), currentAssistant.SessionID, message.CreateMessageParams{
1127+ _, createErr = a.messages.Create(cleanupCtx, currentAssistant.SessionID, message.CreateMessageParams{
4121128 Role: message.Tool,
4131129 Parts: []message.ContentPart{
4141130 toolResult,
@@ -418,28 +1134,50 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
4181134 return nil, createErr
4191135 }
4201136 }
1137+ var fantasyErr *fantasy.Error
1138+ var providerErr *fantasy.ProviderError
1139+ const defaultTitle = "Provider Error"
1140+ linkStyle := lipgloss.NewStyle().Foreground(charmtone.Guac).Underline(true)
4211141 if isCancelErr {
422− currentAssistant.AddFinish(message.FinishReasonCanceled, "Request cancelled", "")
423− } else if isPermissionErr {
424− currentAssistant.AddFinish(message.FinishReasonPermissionDenied, "Permission denied", "")
1142+ currentAssistant.AddFinish(message.FinishReasonCanceled, "User canceled request", "")
1143+ } else if isHyper && errors.As(err, &providerErr) && providerErr.StatusCode == http.StatusUnauthorized {
1144+ currentAssistant.AddFinish(message.FinishReasonError, "Unauthorized", `Please re-authenticate with Hyper. You can also run "crush auth" to re-authenticate.`)
1145+ } else if isHyper && errors.As(err, &providerErr) && providerErr.StatusCode == http.StatusPaymentRequired {
1146+ url := hyper.BaseURL()
1147+ link := linkStyle.Hyperlink(url, "id=hyper").Render(url)
1148+ currentAssistant.AddFinish(message.FinishReasonError, "No credits", "You're out of credits. Add more at "+link)
1149+ } else if errors.As(err, &providerErr) {
1150+ if providerErr.Message == "The requested model is not supported." {
1151+ url := "https://github.com/settings/copilot/features"
1152+ link := linkStyle.Hyperlink(url, "id=copilot").Render(url)
1153+ currentAssistant.AddFinish(
1154+ message.FinishReasonError,
1155+ "Copilot model not enabled",
1156+ fmt.Sprintf("%q is not enabled in Copilot. Go to the following page to enable it. Then, wait 5 minutes before trying again. %s", largeModel.CatwalkCfg.Name, link),
1157+ )
1158+ } else {
1159+ currentAssistant.AddFinish(message.FinishReasonError, cmp.Or(stringext.Capitalize(providerErr.Title), defaultTitle), providerErr.Message)
1160+ }
1161+ } else if errors.As(err, &fantasyErr) {
1162+ currentAssistant.AddFinish(message.FinishReasonError, cmp.Or(stringext.Capitalize(fantasyErr.Title), defaultTitle), fantasyErr.Message)
4251163 } else {
426− currentAssistant.AddFinish(message.FinishReasonError, "API Error", err.Error())
1164+ currentAssistant.AddFinish(message.FinishReasonError, defaultTitle, err.Error())
4271165 }
428− // INFO: we use the parent context here because the genCtx has been cancelled
429− updateErr := a.messages.Update(ctx, *currentAssistant)
1166+ // Note: we use the cleanup context here because the genCtx has been
1167+ // cancelled.
1168+ updateErr := a.messages.Update(cleanupCtx, *currentAssistant)
4301169 if updateErr != nil {
4311170 return nil, updateErr
4321171 }
4331172 return nil, err
4341173 }
435− wg.Wait()
4361174
4371175 if shouldSummarize {
4381176 a.activeRequests.Del(call.SessionID)
4391177 if summarizeErr := a.Summarize(genCtx, call.SessionID, call.ProviderOptions); summarizeErr != nil {
4401178 return nil, summarizeErr
4411179 }
442− // if the agent was not done...
1180+ // If the agent wasn't done...
4431181 if len(currentAssistant.ToolCalls()) > 0 {
4441182 existing, ok := a.messageQueue.Get(call.SessionID)
4451183 if !ok {
@@ -451,17 +1189,123 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
4511189 }
4521190 }
4531191
454− // release active request before processing queued messages
1192+ // Release active request before publishing the notification.
1193+ // TUI handlers poll IsSessionBusy() and only re-evaluate when a
1194+ // tea.Msg arrives, so the cleanup must precede the notify or
1195+ // subscribers see stale busy state at the moment of receipt.
4551196 a.activeRequests.Del(call.SessionID)
4561197 cancel()
4571198
458− queuedMessages, ok := a.messageQueue.Get(call.SessionID)
459− if !ok || len(queuedMessages) == 0 {
1199+ // Send notification that agent has finished its turn (skip for
1200+ // nested/non-interactive sessions).
1201+ if !call.NonInteractive && a.notify != nil {
1202+ a.notify.Publish(pubsub.CreatedEvent, notify.Notification{
1203+ SessionID: call.SessionID,
1204+ SessionTitle: currentSession.Title,
1205+ Type: notify.TypeAgentFinished,
1206+ })
1207+ }
1208+
1209+ // Hand off to the next queued prompt (if any) under dispatchMu so
1210+ // the transition from this finished run to the queued run is atomic
1211+ // against a concurrent Cancel. activeRequests for this session was
1212+ // just deleted above, so without the lock there is a window in
1213+ // which the session looks idle and a cancel becomes a no-op that
1214+ // fails to stop the queued prompt. Holding the lock lets us observe
1215+ // a pending cancel recorded against the session and drop the queue
1216+ // instead of running it, and (for the recursion) hand a fresh
1217+ // accept reservation to the dequeued call so acceptedRuns stays > 0
1218+ // across the recursive Run's own dispatch handoff — keeping the
1219+ // session observable to Cancel for the entire transition and
1220+ // closing the dequeue -> re-register window.
1221+ mu := a.sessionMu(call.SessionID)
1222+ mu.Lock()
1223+ queuedMessages, _ := a.messageQueue.Get(call.SessionID)
1224+ if mark, ok := a.cancelMark.Get(call.SessionID); ok && mark > 0 && len(queuedMessages) > 0 {
1225+ // A cancel was recorded for this session (e.g. it arrived while
1226+ // this run was active and follow-ups had been queued). Drop the
1227+ // queued prompts it covers (accept sequence at or below the
1228+ // mark, or untracked); keep any queued after the cancel (higher
1229+ // sequence) so they still run.
1230+ var kept []SessionAgentCall
1231+ var canceledRunIDDrops []SessionAgentCall
1232+ for _, q := range queuedMessages {
1233+ if q.acceptSeq == 0 || q.acceptSeq <= mark {
1234+ if q.RunID != "" {
1235+ canceledRunIDDrops = append(canceledRunIDDrops, q)
1236+ }
1237+ continue
1238+ }
1239+ kept = append(kept, q)
1240+ }
1241+ queuedMessages = kept
1242+ a.messageQueue.Set(call.SessionID, kept)
1243+ // A dropped prompt carrying a RunID must still publish its
1244+ // terminal cancelled RunComplete so a caller waiting on that
1245+ // RunID does not hang.
1246+ a.publishCanceledQueueDrops(canceledRunIDDrops)
1247+ }
1248+ if len(queuedMessages) == 0 {
1249+ // No queued work. Clear the cancel mark only when no accepted
1250+ // run remains in flight that it might still cover; otherwise a
1251+ // sibling prompt (sequence at or below the mark) waiting to
1252+ // enter Run would lose its cancellation. When accepted runs are
1253+ // gone, this also clears a stale mark so it can't catch a
1254+ // future run.
1255+ a.messageQueue.Del(call.SessionID)
1256+ a.acceptedMu.Lock()
1257+ inFlight, _ := a.acceptedRuns.Get(call.SessionID)
1258+ a.acceptedMu.Unlock()
1259+ if inFlight == 0 {
1260+ a.cancelMark.Del(call.SessionID)
1261+ }
1262+ mu.Unlock()
4601263 return result, err
4611264 }
462− // there are queued messages restart the loop
1265+ // There are queued messages, restart the loop. Suppress the outer
1266+ // defer's emit: it would otherwise observe the recursive Run's retErr
1267+ // (named-return clobbering through the return below) against this
1268+ // turn's MessageID/Text and publish a mixed, racing event.
1269+ skipRunComplete = true
1270+ // Decide whether this turn still owes its own terminal RunComplete.
1271+ // Each submitted prompt with a RunID has its own lifecycle, so a turn
1272+ // that is finished and handing off to a *different* queued prompt must
1273+ // publish its own RunComplete here — leaving it to the recursive turn
1274+ // (which carries a different RunID) would hang a caller waiting on
1275+ // this turn's RunID. The exception is the summarize-continuation path,
1276+ // which re-queues this same call (same RunID) to resume after a
1277+ // summary; in that case the eventual terminal turn for this RunID
1278+ // publishes, so publishing now would double-emit.
1279+ outerOwesRunComplete := call.RunID != ""
1280+ if outerOwesRunComplete {
1281+ for _, q := range queuedMessages {
1282+ if q.RunID == call.RunID {
1283+ outerOwesRunComplete = false
1284+ break
1285+ }
1286+ }
1287+ }
4631288 firstQueuedMessage := queuedMessages[0]
4641289 a.messageQueue.Set(call.SessionID, queuedMessages[1:])
1290+ // Reserve a fresh accept for the dequeued prompt before dropping the
1291+ // lock so acceptedRuns > 0 across the handoff into the recursive
1292+ // Run. This closes the window between this dequeue and the recursive
1293+ // Run registering its activeRequests entry: a cancel arriving in
1294+ // that window now records a pending cancel (acceptedRuns > 0) that
1295+ // the recursive Run's accepted path observes as cancel-on-entry.
1296+ firstQueuedMessage.Accepted = a.BeginAccepted(call.SessionID)
1297+ mu.Unlock()
1298+ if outerOwesRunComplete {
1299+ complete := notify.RunComplete{SessionID: call.SessionID, RunID: call.RunID}
1300+ if currentAssistant != nil {
1301+ complete.MessageID = currentAssistant.ID
1302+ complete.Text = currentAssistant.Content().String()
1303+ }
1304+ if ctx.Err() != nil {
1305+ complete.Cancelled = true
1306+ }
1307+ a.publishRunComplete(ctx, call, complete)
1308+ }
4651309 return a.Run(ctx, firstQueuedMessage)
4661310}
4671311
@@ -470,6 +1314,10 @@ func (a *sessionAgent) Summarize(ctx context.Context, sessionID string, opts fan
4701314 return ErrSessionBusy
4711315 }
4721316
1317+ // Copy mutable fields under lock to avoid races with SetModels.
1318+ largeModel := a.largeModel.Get()
1319+ systemPromptPrefix := a.systemPromptPrefix.Get()
1320+
4731321 currentSession, err := a.sessions.Get(ctx, sessionID)
4741322 if err != nil {
4751323 return fmt.Errorf("failed to get session: %w", err)
@@ -479,40 +1327,56 @@ func (a *sessionAgent) Summarize(ctx context.Context, sessionID string, opts fan
4791327 return err
4801328 }
4811329 if len(msgs) == 0 {
482− // nothing to summarize
1330+ // Nothing to summarize.
4831331 return nil
4841332 }
4851333
486− aiMsgs, _ := a.preparePrompt(msgs)
1334+ aiMsgs, _ := a.preparePrompt(msgs, largeModel.CatwalkCfg.SupportsImages)
4871335
4881336 genCtx, cancel := context.WithCancel(ctx)
4891337 a.activeRequests.Set(sessionID, cancel)
4901338 defer a.activeRequests.Del(sessionID)
4911339 defer cancel()
1340+ defer func() {
1341+ if flushErr := a.messages.FlushAll(ctx); flushErr != nil {
1342+ slog.Error("Failed to flush pending message updates after summarize", "error", flushErr)
1343+ }
1344+ }()
4921345
493− agent := fantasy.NewAgent(a.largeModel.Model,
1346+ agent := fantasy.NewAgent(
1347+ largeModel.Model,
4941348 fantasy.WithSystemPrompt(string(summaryPrompt)),
1349+ fantasy.WithUserAgent(userAgent),
4951350 )
4961351 summaryMessage, err := a.messages.Create(ctx, sessionID, message.CreateMessageParams{
4971352 Role: message.Assistant,
498− Model: a.largeModel.Model.Model(),
499− Provider: a.largeModel.Model.Provider(),
1353+ Model: largeModel.ModelCfg.Model,
1354+ Provider: largeModel.ModelCfg.Provider,
5001355 IsSummaryMessage: true,
5011356 })
5021357 if err != nil {
5031358 return err
5041359 }
5051360
1361+ summaryPromptText := buildSummaryPrompt(currentSession.Todos)
1362+
5061363 resp, err := agent.Stream(genCtx, fantasy.AgentStreamCall{
507− Prompt: "Provide a detailed summary of our conversation above.",
1364+ Prompt: summaryPromptText,
5081365 Messages: aiMsgs,
5091366 ProviderOptions: opts,
1367+ PrepareStep: func(callContext context.Context, options fantasy.PrepareStepFunctionOptions) (_ context.Context, prepared fantasy.PrepareStepResult, err error) {
1368+ prepared.Messages = options.Messages
1369+ if systemPromptPrefix != "" {
1370+ prepared.Messages = append([]fantasy.Message{fantasy.NewSystemMessage(systemPromptPrefix)}, prepared.Messages...)
1371+ }
1372+ return callContext, prepared, nil
1373+ },
5101374 OnReasoningDelta: func(id string, text string) error {
5111375 summaryMessage.AppendReasoningContent(text)
5121376 return a.messages.Update(genCtx, summaryMessage)
5131377 },
5141378 OnReasoningEnd: func(id string, reasoning fantasy.ReasoningContent) error {
515− // handle anthropic signature
1379+ // Handle anthropic signature.
5161380 if anthropicData, ok := reasoning.ProviderMetadata["anthropic"]; ok {
5171381 if signature, ok := anthropicData.(*anthropic.ReasoningOptionMetadata); ok && signature.Signature != "" {
5181382 summaryMessage.AppendReasoningSignature(signature.Signature)
@@ -529,10 +1393,16 @@ func (a *sessionAgent) Summarize(ctx context.Context, sessionID string, opts fan
5291393 if err != nil {
5301394 isCancelErr := errors.Is(err, context.Canceled)
5311395 if isCancelErr {
532− // User cancelled summarize we need to remove the summary message
1396+ // User cancelled summarize we need to remove the summary message.
5331397 deleteErr := a.messages.Delete(ctx, summaryMessage.ID)
5341398 return deleteErr
5351399 }
1400+ // Mark the summary message as finished with an error so the UI
1401+ // stops spinning.
1402+ summaryMessage.AddFinish(message.FinishReasonError, "Summarization Error", err.Error())
1403+ if updateErr := a.messages.Update(ctx, summaryMessage); updateErr != nil {
1404+ return updateErr
1405+ }
5361406 return err
5371407 }
5381408
@@ -542,18 +1412,52 @@ func (a *sessionAgent) Summarize(ctx context.Context, sessionID string, opts fan
5421412 return err
5431413 }
5441414
545− a.updateSessionUsage(a.largeModel, &currentSession, resp.TotalUsage)
1415+ var openrouterCost *float64
1416+ for _, step := range resp.Steps {
1417+ stepCost := a.openrouterCost(step.ProviderMetadata)
1418+ if stepCost != nil {
1419+ newCost := *stepCost
1420+ if openrouterCost != nil {
1421+ newCost += *openrouterCost
1422+ }
1423+ openrouterCost = &newCost
1424+ }
1425+ extractHyperCredits(step.ProviderMetadata)
1426+ }
1427+
1428+ a.updateSessionUsage(largeModel, &currentSession, resp.TotalUsage, openrouterCost, false)
5461429
547− // just in case get just the last usage
1430+ // Just in case, get just the last usage info.
5481431 usage := resp.Response.Usage
5491432 currentSession.SummaryMessageID = summaryMessage.ID
550− currentSession.CompletionTokens = usage.OutputTokens
1433+ currentSession.CompletionTokens = summaryCompletionTokens(usage, summaryMessage)
5511434 currentSession.PromptTokens = 0
1435+ currentSession.EstimatedUsage = usageIsZero(usage)
5521436 _, err = a.sessions.Save(genCtx, currentSession)
553− return err
1437+ if err != nil {
1438+ return err
1439+ }
1440+
1441+ // Release the active request before processing queued messages so that
1442+ // Run() does not see the session as busy.
1443+ a.activeRequests.Del(sessionID)
1444+ cancel()
1445+
1446+ // Process any messages that were queued while summarizing.
1447+ queuedMessages, ok := a.messageQueue.Get(sessionID)
1448+ if !ok || len(queuedMessages) == 0 {
1449+ return nil
1450+ }
1451+ firstQueuedMessage := queuedMessages[0]
1452+ a.messageQueue.Set(sessionID, queuedMessages[1:])
1453+ _, qErr := a.Run(ctx, firstQueuedMessage)
1454+ return qErr
5541455}
5551456
556−func (a *sessionAgent) getCacheControlOptions() fantasy.ProviderOptions {
1457+// cacheControlOptions is computed once for the process lifetime: the env check
1458+// is constant and callers only read (never mutate) the returned map, so the
1459+// same shared value can be reused across the ~3 calls per step.
1460+var cacheControlOptions = sync.OnceValue(func() fantasy.ProviderOptions {
5571461 if t, _ := strconv.ParseBool(os.Getenv("CRUSH_DISABLE_ANTHROPIC_CACHE")); t {
5581462 return fantasy.ProviderOptions{}
5591463 }
@@ -564,15 +1468,22 @@ func (a *sessionAgent) getCacheControlOptions() fantasy.ProviderOptions {
5641468 bedrock.Name: &anthropic.ProviderCacheControlOptions{
5651469 CacheControl: anthropic.CacheControl{Type: "ephemeral"},
5661470 },
1471+ vercel.Name: &anthropic.ProviderCacheControlOptions{
1472+ CacheControl: anthropic.CacheControl{Type: "ephemeral"},
1473+ },
5671474 }
1475+})
1476+
1477+func (a *sessionAgent) getCacheControlOptions() fantasy.ProviderOptions {
1478+ return cacheControlOptions()
5681479}
5691480
5701481func (a *sessionAgent) createUserMessage(ctx context.Context, call SessionAgentCall) (message.Message, error) {
1482+ parts := []message.ContentPart{message.TextContent{Text: call.Prompt}}
5711483 var attachmentParts []message.ContentPart
5721484 for _, attachment := range call.Attachments {
5731485 attachmentParts = append(attachmentParts, message.BinaryContent{Path: attachment.FilePath, MIMEType: attachment.MimeType, Data: attachment.Content})
5741486 }
575− parts := []message.ContentPart{message.TextContent{Text: call.Prompt}}
5761487 parts = append(parts, attachmentParts...)
5771488 msg, err := a.messages.Create(ctx, call.SessionID, message.CreateMessageParams{
5781489 Role: message.User,
@@ -584,21 +1495,73 @@ func (a *sessionAgent) createUserMessage(ctx context.Context, call SessionAgentC
5841495 return msg, nil
5851496}
5861497
587−func (a *sessionAgent) preparePrompt(msgs []message.Message, attachments ...message.Attachment) ([]fantasy.Message, []fantasy.FilePart) {
588− var history []fantasy.Message
1498+func (a *sessionAgent) preparePrompt(msgs []message.Message, supportsImages bool, attachments ...message.Attachment) ([]fantasy.Message, []fantasy.FilePart) {
1499+ history := make([]fantasy.Message, 0, len(msgs)+1)
1500+ if !a.isSubAgent {
1501+ history = append(history, fantasy.NewUserMessage(
1502+ fmt.Sprintf(
1503+ "<system_reminder>%s</system_reminder>",
1504+ `This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.
1505+If you are working on tasks that would benefit from a todo list please use the "todos" tool to create one.
1506+If not, please feel free to ignore. Again do not mention this message to the user.`,
1507+ ),
1508+ ))
1509+ }
1510+ // Collect all tool call IDs present in assistant messages and all tool
1511+ // result IDs present in tool messages. This lets us detect both orphaned
1512+ // tool results (result without a call) and orphaned tool calls (call
1513+ // without a result).
1514+ knownToolCallIDs := make(map[string]struct{})
1515+ knownToolResultIDs := make(map[string]struct{})
1516+ for _, m := range msgs {
1517+ switch m.Role {
1518+ case message.Assistant:
1519+ for _, tc := range m.ToolCalls() {
1520+ knownToolCallIDs[tc.ID] = struct{}{}
1521+ }
1522+ case message.Tool:
1523+ for _, tr := range m.ToolResults() {
1524+ knownToolResultIDs[tr.ToolCallID] = struct{}{}
1525+ }
1526+ }
1527+ }
1528+
5891529 for _, m := range msgs {
5901530 if len(m.Parts) == 0 {
5911531 continue
5921532 }
593− // Assistant message without content or tool calls (cancelled before it returned anything)
1533+ // Assistant message without content or tool calls (cancelled before it returned anything).
5941534 if m.Role == message.Assistant && len(m.ToolCalls()) == 0 && m.Content().Text == "" && m.ReasoningContent().String() == "" {
5951535 continue
5961536 }
597− history = append(history, m.ToAIMessage()...)
1537+ if m.Role == message.Tool {
1538+ if msg, ok := filterOrphanedToolResults(m, knownToolCallIDs); ok {
1539+ history = append(history, msg)
1540+ }
1541+ continue
1542+ }
1543+ aiMsgs := m.ToAIMessage()
1544+ if !supportsImages {
1545+ for i := range aiMsgs {
1546+ if aiMsgs[i].Role == fantasy.MessageRoleUser {
1547+ aiMsgs[i].Content = filterFileParts(aiMsgs[i].Content)
1548+ }
1549+ }
1550+ }
1551+ history = append(history, aiMsgs...)
1552+
1553+ if m.Role == message.Assistant {
1554+ if msg, ok := syntheticToolResultsForOrphanedCalls(m, knownToolResultIDs); ok {
1555+ history = append(history, msg)
1556+ }
1557+ }
5981558 }
5991559
6001560 var files []fantasy.FilePart
6011561 for _, attachment := range attachments {
1562+ if attachment.IsText() {
1563+ continue
1564+ }
6021565 files = append(files, fantasy.FilePart{
6031566 Filename: attachment.FileName,
6041567 Data: attachment.Content,
@@ -609,109 +1572,410 @@ func (a *sessionAgent) preparePrompt(msgs []message.Message, attachments ...mess
6091572 return history, files
6101573}
6111574
1575+// filterFileParts removes fantasy.FilePart entries from a slice of message
1576+// parts. Used to strip image attachments from historical user messages when
1577+// the current model does not support them.
1578+func filterFileParts(parts []fantasy.MessagePart) []fantasy.MessagePart {
1579+ filtered := make([]fantasy.MessagePart, 0, len(parts))
1580+ for _, part := range parts {
1581+ if _, ok := fantasy.AsMessagePart[fantasy.FilePart](part); ok {
1582+ continue
1583+ }
1584+ filtered = append(filtered, part)
1585+ }
1586+ return filtered
1587+}
1588+
1589+// filterOrphanedToolResults converts a tool message to a fantasy.Message,
1590+// dropping any tool result parts whose tool_call_id has no matching tool call
1591+// in the known set. An orphaned result causes API validation to fail on every
1592+// subsequent turn, permanently locking the session. Returns the filtered
1593+// message and true if at least one valid part remains.
1594+func filterOrphanedToolResults(m message.Message, knownToolCallIDs map[string]struct{}) (fantasy.Message, bool) {
1595+ aiMsgs := m.ToAIMessage()
1596+ if len(aiMsgs) == 0 {
1597+ return fantasy.Message{}, false
1598+ }
1599+ validParts := make([]fantasy.MessagePart, 0, len(aiMsgs[0].Content))
1600+ for _, part := range aiMsgs[0].Content {
1601+ tr, ok := fantasy.AsMessagePart[fantasy.ToolResultPart](part)
1602+ if !ok {
1603+ validParts = append(validParts, part)
1604+ continue
1605+ }
1606+ if _, known := knownToolCallIDs[tr.ToolCallID]; known {
1607+ validParts = append(validParts, part)
1608+ } else {
1609+ slog.Warn(
1610+ "Dropping orphaned tool result with no matching tool call",
1611+ "tool_call_id", tr.ToolCallID,
1612+ )
1613+ }
1614+ }
1615+ if len(validParts) == 0 {
1616+ return fantasy.Message{}, false
1617+ }
1618+ msg := aiMsgs[0]
1619+ msg.Content = validParts
1620+ return msg, true
1621+}
1622+
1623+// syntheticToolResultsForOrphanedCalls returns a tool message containing
1624+// synthetic tool results for any tool calls in the assistant message that
1625+// have no matching result in knownToolResultIDs. LLM APIs require every
1626+// tool_use to be immediately followed by a tool_result; an interrupted
1627+// session can leave orphaned tool_use blocks that permanently lock the
1628+// conversation. Returns the message and true if any synthetic results were
1629+// produced.
1630+func syntheticToolResultsForOrphanedCalls(m message.Message, knownToolResultIDs map[string]struct{}) (fantasy.Message, bool) {
1631+ syntheticParts := make([]fantasy.MessagePart, 0, len(m.ToolCalls()))
1632+ for _, tc := range m.ToolCalls() {
1633+ if _, hasResult := knownToolResultIDs[tc.ID]; hasResult {
1634+ continue
1635+ }
1636+ slog.Warn(
1637+ "Injecting synthetic tool result for orphaned tool call",
1638+ "tool_call_id", tc.ID,
1639+ "tool_name", tc.Name,
1640+ )
1641+ syntheticParts = append(syntheticParts, fantasy.ToolResultPart{
1642+ ToolCallID: tc.ID,
1643+ Output: fantasy.ToolResultOutputContentError{
1644+ Error: errors.New("tool call was interrupted and did not produce a result, you may retry this call if the result is still needed"),
1645+ },
1646+ })
1647+ }
1648+ if len(syntheticParts) == 0 {
1649+ return fantasy.Message{}, false
1650+ }
1651+ return fantasy.Message{
1652+ Role: fantasy.MessageRoleTool,
1653+ Content: syntheticParts,
1654+ }, true
1655+}
1656+
6121657func (a *sessionAgent) getSessionMessages(ctx context.Context, session session.Session) ([]message.Message, error) {
1658+ if session.SummaryMessageID != "" {
1659+ msgs, err := a.messages.ListAfter(ctx, session.ID, session.SummaryMessageID)
1660+ if err != nil {
1661+ return nil, fmt.Errorf("failed to list messages after summary: %w", err)
1662+ }
1663+ if len(msgs) > 0 {
1664+ msgs[0].Role = message.User
1665+ }
1666+ return msgs, nil
1667+ }
1668+
6131669 msgs, err := a.messages.List(ctx, session.ID)
6141670 if err != nil {
6151671 return nil, fmt.Errorf("failed to list messages: %w", err)
6161672 }
1673+ return msgs, nil
1674+}
6171675
618− if session.SummaryMessageID != "" {
619− summaryMsgInex := -1
620− for i, msg := range msgs {
621− if msg.ID == session.SummaryMessageID {
622− summaryMsgInex = i
623− break
624− }
1676+// hasUserTextMessage reports whether any user message in msgs contains
1677+// text content (as opposed to only shell commands or other non-text parts).
1678+func hasUserTextMessage(msgs []message.Message) bool {
1679+ for _, msg := range msgs {
1680+ if msg.Role != message.User {
1681+ continue
6251682 }
626− if summaryMsgInex != -1 {
627− msgs = msgs[summaryMsgInex:]
628− msgs[0].Role = message.User
1683+ for _, part := range msg.Parts {
1684+ if tc, ok := part.(message.TextContent); ok && tc.Text != "" {
1685+ return true
1686+ }
6291687 }
6301688 }
631− return msgs, nil
1689+ return false
6321690}
6331691
634−func (a *sessionAgent) generateTitle(ctx context.Context, session *session.Session, prompt string) {
635− if prompt == "" {
1692+// GenerateTitle generates a session title based on the initial prompt.
1693+func (a *sessionAgent) GenerateTitle(ctx context.Context, sessionID string, userPrompt string) {
1694+ if userPrompt == "" {
6361695 return
6371696 }
6381697
639− var maxOutput int64 = 40
640− if a.smallModel.CatwalkCfg.CanReason {
641− maxOutput = a.smallModel.CatwalkCfg.DefaultMaxTokens
1698+ // Ensure the session always gets a title even if every path below
1699+ // fails or the context is cancelled before we finish.
1700+ var titleSaved bool
1701+ defer func() {
1702+ if !titleSaved {
1703+ fallbackCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 5*time.Second)
1704+ defer cancel()
1705+ if err := a.sessions.Rename(fallbackCtx, sessionID, DefaultSessionName); err != nil {
1706+ slog.Error("Failed to save fallback session title", "error", err)
1707+ }
1708+ }
1709+ }()
1710+
1711+ smallModel := a.smallModel.Get()
1712+ largeModel := a.largeModel.Get()
1713+ systemPromptPrefix := a.systemPromptPrefix.Get()
1714+
1715+ newAgent := func(m fantasy.LanguageModel, p []byte, tok int64) fantasy.Agent {
1716+ return fantasy.NewAgent(
1717+ m,
1718+ fantasy.WithSystemPrompt(string(p)+"\n /no_think"),
1719+ fantasy.WithMaxOutputTokens(tok),
1720+ fantasy.WithUserAgent(userAgent),
1721+ )
6421722 }
6431723
644− agent := fantasy.NewAgent(a.smallModel.Model,
645− fantasy.WithSystemPrompt(string(titlePrompt)+"\n /no_think"),
646− fantasy.WithMaxOutputTokens(maxOutput),
647− )
1724+ streamCall := fantasy.AgentStreamCall{
1725+ Prompt: fmt.Sprintf("Generate a concise title for the following content:\n\n%s\n <think>\n\n</think>", userPrompt),
1726+ PrepareStep: func(callCtx context.Context, opts fantasy.PrepareStepFunctionOptions) (_ context.Context, prepared fantasy.PrepareStepResult, err error) {
1727+ prepared.Messages = opts.Messages
1728+ if systemPromptPrefix != "" {
1729+ prepared.Messages = append([]fantasy.Message{
1730+ fantasy.NewSystemMessage(systemPromptPrefix),
1731+ }, prepared.Messages...)
1732+ }
1733+ return callCtx, prepared, nil
1734+ },
1735+ }
6481736
649− resp, err := agent.Stream(ctx, fantasy.AgentStreamCall{
650− Prompt: fmt.Sprintf("Generate a concise title for the following content:\n\n%s\n <think>\n\n</think>", prompt),
651− })
652− if err != nil {
653− slog.Error("error generating title", "err", err)
654− return
1737+ type modelAttempt struct {
1738+ name string
1739+ model Model
1740+ }
1741+ attempts := []modelAttempt{
1742+ {"small", smallModel},
1743+ {"large", largeModel},
6551744 }
6561745
657− title := resp.Response.Content.Text()
1746+ var resp *fantasy.AgentResult
1747+ var err error
1748+ var model Model
1749+ var success bool
1750+ for _, attempt := range attempts {
1751+ tok := int64(40)
1752+ if attempt.model.CatwalkCfg.CanReason {
1753+ tok = attempt.model.CatwalkCfg.DefaultMaxTokens
1754+ }
1755+ agent := newAgent(attempt.model.Model, titlePrompt, tok)
1756+ resp, err = agent.Stream(ctx, streamCall)
1757+ if err == nil && resp.Response.FinishReason != fantasy.FinishReasonLength {
1758+ model = attempt.model
1759+ slog.Debug("Generated title with " + attempt.name + " model")
1760+ success = true
1761+ break
1762+ }
1763+ if err != nil {
1764+ slog.Error("Error generating title with "+attempt.name+" model; trying next", "err", err)
1765+ } else {
1766+ slog.Error("Title generation hit token limit with " + attempt.name + " model; trying next")
1767+ }
1768+ }
1769+ if !success {
1770+ // The deferred fallback will save the default session name.
1771+ return
1772+ }
6581773
659− title = strings.ReplaceAll(title, "\n", " ")
1774+ // Clean up title.
1775+ var title string
1776+ title = strings.ReplaceAll(resp.Response.Content.Text(), "\n", " ")
6601777
661− // remove thinking tags if present
662− if idx := strings.Index(title, "</think>"); idx > 0 {
663− title = title[idx+len("</think>"):]
664− }
1778+ // Remove thinking tags if present.
1779+ title = thinkTagRegex.ReplaceAllString(title, "")
1780+ title = orphanThinkTagRegex.ReplaceAllString(title, "")
6651781
6661782 title = strings.TrimSpace(title)
6671783 if title == "" {
668− slog.Warn("failed to generate title", "warn", "empty title")
669− return
1784+ // LLM returned empty content. Use the prompt itself as a
1785+ // fallback title, truncated to 50 chars, before resorting to
1786+ // the generic default.
1787+ fallback := strings.ReplaceAll(userPrompt, "\n", " ")
1788+ fallback = strings.TrimSpace(fallback)
1789+ if len(fallback) > 50 {
1790+ fallback = ansi.Truncate(fallback, 50, "…")
1791+ }
1792+ title = cmp.Or(fallback, DefaultSessionName)
1793+ }
1794+
1795+ // Calculate usage and cost.
1796+ var openrouterCost *float64
1797+ for _, step := range resp.Steps {
1798+ stepCost := a.openrouterCost(step.ProviderMetadata)
1799+ if stepCost != nil {
1800+ newCost := *stepCost
1801+ if openrouterCost != nil {
1802+ newCost += *openrouterCost
1803+ }
1804+ openrouterCost = &newCost
1805+ }
1806+ extractHyperCredits(step.ProviderMetadata)
1807+ }
1808+
1809+ modelConfig := model.CatwalkCfg
1810+ cost := modelConfig.CostPer1MInCached/1e6*float64(resp.TotalUsage.CacheCreationTokens) +
1811+ modelConfig.CostPer1MOutCached/1e6*float64(resp.TotalUsage.CacheReadTokens) +
1812+ modelConfig.CostPer1MIn/1e6*float64(resp.TotalUsage.InputTokens) +
1813+ modelConfig.CostPer1MOut/1e6*float64(resp.TotalUsage.OutputTokens)
1814+
1815+ // Use override cost if available (e.g., from OpenRouter).
1816+ if openrouterCost != nil {
1817+ cost = *openrouterCost
1818+ }
1819+
1820+ // Skip cost accumulation
1821+ if model.FlatRate {
1822+ cost = 0
6701823 }
6711824
672− session.Title = title
673− a.updateSessionUsage(a.smallModel, session, resp.TotalUsage)
674− _, saveErr := a.sessions.Save(ctx, *session)
1825+ promptTokens := resp.TotalUsage.InputTokens + resp.TotalUsage.CacheCreationTokens
1826+ completionTokens := resp.TotalUsage.OutputTokens
1827+
1828+ // Atomically update only title and usage fields to avoid overriding other
1829+ // concurrent session updates.
1830+ saveErr := a.sessions.UpdateTitleAndUsage(ctx, sessionID, title, promptTokens, completionTokens, cost)
6751831 if saveErr != nil {
676− slog.Error("failed to save session title & usage", "error", saveErr)
1832+ slog.Error("Failed to save session title and usage", "error", saveErr)
1833+ return
1834+ }
1835+ titleSaved = true
1836+}
1837+
1838+func (a *sessionAgent) openrouterCost(metadata fantasy.ProviderMetadata) *float64 {
1839+ openrouterMetadata, ok := metadata[openrouter.Name]
1840+ if !ok {
1841+ return nil
1842+ }
1843+
1844+ opts, ok := openrouterMetadata.(*openrouter.ProviderMetadata)
1845+ if !ok {
1846+ return nil
1847+ }
1848+ return &opts.Usage.Cost
1849+}
1850+
1851+// extractHyperCredits reads usage.remaining.hypercredits from OpenAI
1852+// provider metadata and stores it for the next FetchCredits call.
1853+func extractHyperCredits(metadata fantasy.ProviderMetadata) {
1854+ openaiMeta, ok := metadata[openai.Name]
1855+ if !ok {
1856+ return
1857+ }
1858+ pm, ok := openaiMeta.(*openai.ProviderMetadata)
1859+ if !ok {
6771860 return
6781861 }
1862+ var remaining struct {
1863+ Hypercredits float64 `json:"hypercredits"`
1864+ }
1865+ if pm.ExtraField("remaining", &remaining) && remaining.Hypercredits > 0 {
1866+ hyper.SetBalance(int(math.Round(remaining.Hypercredits)))
1867+ }
6791868}
6801869
681−func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session, usage fantasy.Usage) {
1870+func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session, usage fantasy.Usage, overrideCost *float64, estimated bool) {
1871+ if !usageIsZero(usage) {
1872+ session.EstimatedUsage = estimated
1873+ }
1874+
6821875 modelConfig := model.CatwalkCfg
6831876 cost := modelConfig.CostPer1MInCached/1e6*float64(usage.CacheCreationTokens) +
6841877 modelConfig.CostPer1MOutCached/1e6*float64(usage.CacheReadTokens) +
6851878 modelConfig.CostPer1MIn/1e6*float64(usage.InputTokens) +
6861879 modelConfig.CostPer1MOut/1e6*float64(usage.OutputTokens)
1880+
1881+ if !estimated {
1882+ a.eventTokensUsed(session.ID, model, usage, cost)
1883+ }
1884+
1885+ if estimated {
1886+ cost = 0
1887+ } else {
1888+ // Use override cost if available (e.g., from OpenRouter).
1889+ if overrideCost != nil {
1890+ cost = *overrideCost
1891+ }
1892+
1893+ // Skip cost accumulation
1894+ if model.FlatRate {
1895+ cost = 0
1896+ }
1897+ }
1898+
6871899 session.Cost += cost
688− session.CompletionTokens = usage.OutputTokens + usage.CacheReadTokens
689− session.PromptTokens = usage.InputTokens + usage.CacheCreationTokens
1900+ updateSessionTokenCounters(session, usage)
1901+}
1902+
1903+func updateSessionTokenCounters(session *session.Session, usage fantasy.Usage) {
1904+ if usage.OutputTokens != 0 {
1905+ session.CompletionTokens = usage.OutputTokens
1906+ }
1907+ if promptTokens := usage.InputTokens + usage.CacheReadTokens; promptTokens != 0 {
1908+ session.PromptTokens = promptTokens
1909+ }
1910+}
1911+
1912+func summaryCompletionTokens(usage fantasy.Usage, summaryMessage message.Message) int64 {
1913+ if usage.OutputTokens != 0 {
1914+ return usage.OutputTokens
1915+ }
1916+ return approxTokenCount(summaryMessage.Content().Text) + approxTokenCount(summaryMessage.ReasoningContent().String())
6901917}
6911918
6921919func (a *sessionAgent) Cancel(sessionID string) {
693− // Cancel regular requests
694− if cancel, ok := a.activeRequests.Take(sessionID); ok && cancel != nil {
695− slog.Info("Request cancellation initiated", "session_id", sessionID)
1920+ // Serialize against the dispatch handoff in Run so the accepted ->
1921+ // (cancel-on-entry | queued | active) transition is atomic against
1922+ // this cancel. Every cancel observes at least one of: an active
1923+ // request, an accepted run (recorded as a pending cancel), or a
1924+ // queue entry it then clears. If none of those hold, an idle Escape
1925+ // is a true no-op and must not poison the next prompt.
1926+ mu := a.sessionMu(sessionID)
1927+ mu.Lock()
1928+ defer mu.Unlock()
1929+
1930+ // Cancel regular requests. Don't use Take() here - we need the entry to
1931+ // remain in activeRequests so IsBusy() returns true until the goroutine
1932+ // fully completes (including error handling that may access the DB).
1933+ // The defer in processRequest will clean up the entry.
1934+ if cancel, ok := a.activeRequests.Get(sessionID); ok && cancel != nil {
1935+ slog.Debug("Request cancellation initiated", "session_id", sessionID)
6961936 cancel()
6971937 }
6981938
699− // Also check for summarize requests
700− if cancel, ok := a.activeRequests.Take(sessionID + "-summarize"); ok && cancel != nil {
701− slog.Info("Summarize cancellation initiated", "session_id", sessionID)
1939+ // Also check for summarize requests.
1940+ if cancel, ok := a.activeRequests.Get(sessionID + "-summarize"); ok && cancel != nil {
1941+ slog.Debug("Summarize cancellation initiated", "session_id", sessionID)
7021942 cancel()
7031943 }
7041944
1945+ // Record a pending cancel only when a dispatched-but-not-yet-active
1946+ // run exists. This catches runs still in the goroutine scheduler or
1947+ // about to enter Run's busy-queue branch, while leaving an idle
1948+ // session untouched. Active and accepted are not mutually exclusive:
1949+ // when a run is active and a follow-up has been accepted, both the
1950+ // cancel above and this pending record fire.
1951+ //
1952+ // Raise the session's cancel mark to the latest accept sequence
1953+ // assigned so far. Every prompt currently accepted-but-not-yet-
1954+ // active has a sequence at or below that value, so one cancel covers
1955+ // all of them; a prompt accepted after this cancel gets a strictly
1956+ // higher sequence and is never poisoned. Using max keeps repeated
1957+ // cancels idempotent while the same prompts are in flight and lets a
1958+ // later cancel extend coverage to prompts accepted since.
1959+ a.acceptedMu.Lock()
1960+ count, ok := a.acceptedRuns.Get(sessionID)
1961+ mark := a.acceptSeqGen
1962+ a.acceptedMu.Unlock()
1963+ if ok && count > 0 {
1964+ slog.Debug("Recording cancel mark for accepted runs", "session_id", sessionID, "count", count, "mark", mark)
1965+ existing, _ := a.cancelMark.Get(sessionID)
1966+ a.cancelMark.Set(sessionID, max(existing, mark))
1967+ }
1968+
7051969 if a.QueuedPrompts(sessionID) > 0 {
706− slog.Info("Clearing queued prompts", "session_id", sessionID)
707− a.messageQueue.Del(sessionID)
1970+ slog.Debug("Clearing queued prompts", "session_id", sessionID)
1971+ a.clearQueueAndNotify(sessionID)
7081972 }
7091973}
7101974
7111975func (a *sessionAgent) ClearQueue(sessionID string) {
7121976 if a.QueuedPrompts(sessionID) > 0 {
713− slog.Info("Clearing queued prompts", "session_id", sessionID)
714− a.messageQueue.Del(sessionID)
1977+ slog.Debug("Clearing queued prompts", "session_id", sessionID)
1978+ a.clearQueueAndNotify(sessionID)
7151979 }
7161980}
7171981
@@ -735,14 +1999,10 @@ func (a *sessionAgent) CancelAll() {
7351999}
7362000
7372001func (a *sessionAgent) IsBusy() bool {
738− var busy bool
739− for cancelFunc := range a.activeRequests.Seq() {
740− if cancelFunc != nil {
741− busy = true
742− break
743− }
744− }
745− return busy
2002+ // activeRequests only ever holds non-nil cancel funcs (Set with a
2003+ // real func, removed via Del), so a length check is exact — and it
2004+ // avoids cloning the whole map, which Seq() does on every call.
2005+ return a.activeRequests.Len() > 0
7462006}
7472007
7482008func (a *sessionAgent) IsSessionBusy(sessionID string) bool {
@@ -758,15 +2018,231 @@ func (a *sessionAgent) QueuedPrompts(sessionID string) int {
7582018 return len(l)
7592019}
7602020
2021+func (a *sessionAgent) QueuedPromptsList(sessionID string) []string {
2022+ l, ok := a.messageQueue.Get(sessionID)
2023+ if !ok {
2024+ return nil
2025+ }
2026+ prompts := make([]string, len(l))
2027+ for i, call := range l {
2028+ prompts[i] = call.Prompt
2029+ }
2030+ return prompts
2031+}
2032+
7612033func (a *sessionAgent) SetModels(large Model, small Model) {
762− a.largeModel = large
763− a.smallModel = small
2034+ a.largeModel.Set(large)
2035+ a.smallModel.Set(small)
7642036}
7652037
7662038func (a *sessionAgent) SetTools(tools []fantasy.AgentTool) {
767− a.tools = tools
2039+ a.tools.SetSlice(tools)
2040+ a.toolsGen.Add(1)
2041+}
2042+
2043+func (a *sessionAgent) SetSystemPrompt(systemPrompt string) {
2044+ a.systemPrompt.Set(systemPrompt)
7682045}
7692046
7702047func (a *sessionAgent) Model() Model {
771− return a.largeModel
2048+ return a.largeModel.Get()
2049+}
2050+
2051+// convertToToolResult converts a fantasy tool result to a message tool result.
2052+func (a *sessionAgent) convertToToolResult(result fantasy.ToolResultContent) message.ToolResult {
2053+ baseResult := message.ToolResult{
2054+ ToolCallID: result.ToolCallID,
2055+ Name: result.ToolName,
2056+ Metadata: result.ClientMetadata,
2057+ }
2058+
2059+ switch result.Result.GetType() {
2060+ case fantasy.ToolResultContentTypeText:
2061+ if r, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentText](result.Result); ok {
2062+ baseResult.Content = r.Text
2063+ }
2064+ case fantasy.ToolResultContentTypeError:
2065+ if r, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentError](result.Result); ok {
2066+ baseResult.Content = r.Error.Error()
2067+ baseResult.IsError = true
2068+ }
2069+ case fantasy.ToolResultContentTypeMedia:
2070+ if r, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentMedia](result.Result); ok {
2071+ if !stringext.IsValidBase64(r.Data) {
2072+ slog.Warn(
2073+ "Tool returned media with invalid base64 data, discarding image",
2074+ "tool", result.ToolName,
2075+ "tool_call_id", result.ToolCallID,
2076+ )
2077+ baseResult.Content = "Tool returned image data with invalid encoding"
2078+ baseResult.IsError = true
2079+ } else {
2080+ content := r.Text
2081+ if content == "" {
2082+ content = fmt.Sprintf("Loaded %s content", r.MediaType)
2083+ }
2084+ baseResult.Content = content
2085+ baseResult.Data = r.Data
2086+ baseResult.MIMEType = r.MediaType
2087+ }
2088+ }
2089+ }
2090+
2091+ return baseResult
2092+}
2093+
2094+// workaroundProviderMediaLimitations converts media content in tool results to
2095+// user messages for providers that don't natively support images in tool results.
2096+//
2097+// Problem: OpenAI, Google, OpenRouter, and other OpenAI-compatible providers
2098+// don't support sending images/media in tool result messages - they only accept
2099+// text in tool results. However, they DO support images in user messages.
2100+//
2101+// If we send media in tool results to these providers, the API returns an error.
2102+//
2103+// Solution: For these providers, we:
2104+// 1. Replace the media in the tool result with a text placeholder
2105+// 2. Inject a user message immediately after with the image as a file attachment
2106+// 3. This maintains the tool execution flow while working around API limitations
2107+//
2108+// Anthropic and Bedrock support images natively in tool results, so we skip
2109+// this workaround for them.
2110+//
2111+// Example transformation:
2112+//
2113+// BEFORE: [tool result: image data]
2114+// AFTER: [tool result: "Image loaded - see attached"], [user: image attachment]
2115+func (a *sessionAgent) workaroundProviderMediaLimitations(messages []fantasy.Message, largeModel Model) []fantasy.Message {
2116+ providerSupportsMedia := largeModel.ModelCfg.Provider == string(catwalk.InferenceProviderAnthropic) ||
2117+ largeModel.ModelCfg.Provider == string(catwalk.InferenceProviderBedrock) ||
2118+ largeModel.ModelCfg.Provider == string(catwalk.InferenceProviderBedrockEurope)
2119+
2120+ if providerSupportsMedia {
2121+ return messages
2122+ }
2123+
2124+ supportsImages := largeModel.CatwalkCfg.SupportsImages
2125+
2126+ convertedMessages := make([]fantasy.Message, 0, len(messages))
2127+
2128+ for _, msg := range messages {
2129+ if msg.Role != fantasy.MessageRoleTool {
2130+ convertedMessages = append(convertedMessages, msg)
2131+ continue
2132+ }
2133+
2134+ textParts := make([]fantasy.MessagePart, 0, len(msg.Content))
2135+ var mediaFiles []fantasy.FilePart
2136+
2137+ for _, part := range msg.Content {
2138+ toolResult, ok := fantasy.AsMessagePart[fantasy.ToolResultPart](part)
2139+ if !ok {
2140+ textParts = append(textParts, part)
2141+ continue
2142+ }
2143+
2144+ if media, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentMedia](toolResult.Output); ok {
2145+ if !supportsImages {
2146+ // Model cannot process images. Replace with a text
2147+ // placeholder and skip creating a synthetic user
2148+ // message with FilePart, which would brick the
2149+ // session on text-only models.
2150+ textParts = append(textParts, fantasy.ToolResultPart{
2151+ ToolCallID: toolResult.ToolCallID,
2152+ Output: fantasy.ToolResultOutputContentText{
2153+ Text: "[Image/media content not supported by this model]",
2154+ },
2155+ ProviderOptions: toolResult.ProviderOptions,
2156+ })
2157+ continue
2158+ }
2159+
2160+ decoded, err := base64.StdEncoding.DecodeString(media.Data)
2161+ if err != nil {
2162+ slog.Warn("Failed to decode media data", "error", err)
2163+ textParts = append(textParts, part)
2164+ continue
2165+ }
2166+
2167+ mediaFiles = append(mediaFiles, fantasy.FilePart{
2168+ Data: decoded,
2169+ MediaType: media.MediaType,
2170+ Filename: fmt.Sprintf("tool-result-%s", toolResult.ToolCallID),
2171+ })
2172+
2173+ textParts = append(textParts, fantasy.ToolResultPart{
2174+ ToolCallID: toolResult.ToolCallID,
2175+ Output: fantasy.ToolResultOutputContentText{
2176+ Text: "[Image/media content loaded - see attached file]",
2177+ },
2178+ ProviderOptions: toolResult.ProviderOptions,
2179+ })
2180+ } else {
2181+ textParts = append(textParts, part)
2182+ }
2183+ }
2184+
2185+ convertedMessages = append(convertedMessages, fantasy.Message{
2186+ Role: fantasy.MessageRoleTool,
2187+ Content: textParts,
2188+ })
2189+
2190+ if len(mediaFiles) > 0 {
2191+ convertedMessages = append(convertedMessages, fantasy.NewUserMessage(
2192+ "Here is the media content from the tool result:",
2193+ mediaFiles...,
2194+ ))
2195+ }
2196+ }
2197+
2198+ return convertedMessages
2199+}
2200+
2201+// buildSummaryPrompt constructs the prompt text for session summarization.
2202+func buildSummaryPrompt(todos []session.Todo) string {
2203+ var sb strings.Builder
2204+ sb.WriteString("Provide a detailed summary of our conversation above.")
2205+ if len(todos) > 0 {
2206+ sb.WriteString("\n\n## Current Todo List\n\n")
2207+ for _, t := range todos {
2208+ fmt.Fprintf(&sb, "- [%s] %s\n", t.Status, t.Content)
2209+ }
2210+ sb.WriteString("\nInclude these tasks and their statuses in your summary. ")
2211+ sb.WriteString("Instruct the resuming assistant to use the `todos` tool to continue tracking progress on these tasks.")
2212+ }
2213+ return sb.String()
2214+}
2215+
2216+func providerRetryLogFields(err *fantasy.ProviderError, delay time.Duration) []any {
2217+ fields := []any{
2218+ "retry_delay", delay.String(),
2219+ }
2220+ if err == nil {
2221+ return fields
2222+ }
2223+ fields = append(fields, "status_code", err.StatusCode)
2224+ if err.Title != "" {
2225+ fields = append(fields, "title", err.Title)
2226+ }
2227+ if err.Message != "" {
2228+ fields = append(fields, "message", err.Message)
2229+ }
2230+ return fields
2231+}
2232+
2233+// sanitizeToolInput validates tool call JSON from the provider.
2234+// Malformed input is replaced with an empty object to prevent
2235+// stuck conversations from truncated or malformed model output.
2236+// The second return value indicates whether sanitization occurred.
2237+func sanitizeToolInput(toolName, toolCallID, input string) (string, bool) {
2238+ if !json.Valid([]byte(input)) {
2239+ slog.Warn(
2240+ "Malformed tool call JSON from provider, replacing with empty object",
2241+ "tool", toolName,
2242+ "id", toolCallID,
2243+ "input_len", len(input),
2244+ )
2245+ return "{}", true
2246+ }
2247+ return input, false
7722248}
internal/agent/agent_test.go+417−16
@@ -1,30 +1,39 @@
11package agent
22
33import (
4+ "encoding/base64"
5+ "fmt"
6+ "log/slog"
47 "os"
58 "path/filepath"
9+ "runtime"
610 "strings"
711 "testing"
12+ "time"
813
14+ "charm.land/catwalk/pkg/catwalk"
915 "charm.land/fantasy"
16+ "charm.land/x/vcr"
1017 "github.com/charmbracelet/crush/internal/agent/tools"
18+ "github.com/charmbracelet/crush/internal/config"
1119 "github.com/charmbracelet/crush/internal/message"
12− "github.com/charmbracelet/crush/internal/shell"
20+ "github.com/charmbracelet/crush/internal/session"
1321 "github.com/stretchr/testify/assert"
1422 "github.com/stretchr/testify/require"
15− "gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
1623
1724 _ "github.com/joho/godotenv/autoload"
1825)
1926
27+func TestMain(m *testing.M) {
28+ slog.SetLogLoggerLevel(slog.LevelError)
29+ m.Run()
30+}
31+
2032var modelPairs = []modelPair{
21− {"anthropic-sonnet", anthropicBuilder("claude-sonnet-4-5-20250929"), anthropicBuilder("claude-3-5-haiku-20241022")},
22− {"openai-gpt-5", openaiBuilder("gpt-5"), openaiBuilder("gpt-4o")},
23− {"openrouter-kimi-k2", openRouterBuilder("moonshotai/kimi-k2-0905"), openRouterBuilder("qwen/qwen3-next-80b-a3b-instruct")},
24− {"zai-glm4.6", zAIBuilder("glm-4.6"), zAIBuilder("glm-4.5-air")},
33+ {"glm-5.1", hyperBuilder("glm-5.1"), hyperBuilder("gpt-oss-120b")},
2534}
2635
27−func getModels(t *testing.T, r *recorder.Recorder, pair modelPair) (fantasy.LanguageModel, fantasy.LanguageModel) {
36+func getModels(t *testing.T, r *vcr.Recorder, pair modelPair) (fantasy.LanguageModel, fantasy.LanguageModel) {
2837 large, err := pair.largeModel(t, r)
2938 require.NoError(t, err)
3039 small, err := pair.smallModel(t, r)
@@ -32,19 +41,22 @@ func getModels(t *testing.T, r *recorder.Recorder, pair modelPair) (fantasy.Lang
3241 return large, small
3342}
3443
35−func setupAgent(t *testing.T, pair modelPair) (SessionAgent, env) {
36− r := newRecorder(t)
44+func setupAgent(t *testing.T, pair modelPair) (SessionAgent, fakeEnv) {
45+ r := vcr.NewRecorder(t)
3746 large, small := getModels(t, r, pair)
3847 env := testEnv(t)
3948
4049 createSimpleGoProject(t, env.workingDir)
4150 agent, err := coderAgent(r, env, large, small)
42− shell.Reset(env.workingDir)
4351 require.NoError(t, err)
4452 return agent, env
4553}
4654
4755func TestCoderAgent(t *testing.T) {
56+ if runtime.GOOS == "windows" {
57+ t.Skip("skipping on windows for now")
58+ }
59+
4860 for _, pair := range modelPairs {
4961 t.Run(pair.name, func(t *testing.T) {
5062 t.Run("simple test", func(t *testing.T) {
@@ -165,7 +177,7 @@ func TestCoderAgent(t *testing.T) {
165177 require.NoError(t, err)
166178
167179 res, err := agent.Run(t.Context(), SessionAgentCall{
168− Prompt: "use bash to create a file named test.txt with content 'hello bash'",
180+ Prompt: "use bash to create a file named test.txt with content 'hello bash'. do not print its timestamp",
169181 SessionID: session.ID,
170182 MaxOutputTokens: 10000,
171183 })
@@ -209,7 +221,7 @@ func TestCoderAgent(t *testing.T) {
209221 require.NoError(t, err)
210222
211223 res, err := agent.Run(t.Context(), SessionAgentCall{
212− Prompt: "download the file from https://httpbin.org/robots.txt and save it as robots.txt",
224+ Prompt: "download the file from https://example-files.online-convert.com/document/txt/example.txt and save it as example.txt",
213225 SessionID: session.ID,
214226 MaxOutputTokens: 10000,
215227 })
@@ -241,9 +253,9 @@ func TestCoderAgent(t *testing.T) {
241253
242254 require.True(t, foundDownload, "Expected to find a download operation")
243255
244− robotsPath := filepath.Join(env.workingDir, "robots.txt")
245− _, err = os.Stat(robotsPath)
246− require.NoError(t, err, "Expected robots.txt file to exist")
256+ examplePath := filepath.Join(env.workingDir, "example.txt")
257+ _, err = os.Stat(examplePath)
258+ require.NoError(t, err, "Expected example.txt file to exist")
247259 })
248260 t.Run("fetch tool", func(t *testing.T) {
249261 agent, env := setupAgent(t, pair)
@@ -252,7 +264,7 @@ func TestCoderAgent(t *testing.T) {
252264 require.NoError(t, err)
253265
254266 res, err := agent.Run(t.Context(), SessionAgentCall{
255− Prompt: "fetch the content from https://httpbin.org/html and tell me if it contains the word 'Herman'",
267+ Prompt: "fetch the content from https://example-files.online-convert.com/website/html/example.html and tell me if it contains the word 'John Doe'",
256268 SessionID: session.ID,
257269 MaxOutputTokens: 10000,
258270 })
@@ -612,3 +624,392 @@ func TestCoderAgent(t *testing.T) {
612624 })
613625 }
614626}
627+
628+func makeTestTodos(n int) []session.Todo {
629+ todos := make([]session.Todo, n)
630+ for i := range n {
631+ todos[i] = session.Todo{
632+ Status: session.TodoStatusPending,
633+ Content: fmt.Sprintf("Task %d: Implement feature with some description that makes it realistic", i),
634+ }
635+ }
636+ return todos
637+}
638+
639+func BenchmarkBuildSummaryPrompt(b *testing.B) {
640+ cases := []struct {
641+ name string
642+ numTodos int
643+ }{
644+ {"0todos", 0},
645+ {"5todos", 5},
646+ {"10todos", 10},
647+ {"50todos", 50},
648+ }
649+
650+ for _, tc := range cases {
651+ todos := makeTestTodos(tc.numTodos)
652+
653+ b.Run(tc.name, func(b *testing.B) {
654+ b.ReportAllocs()
655+ for range b.N {
656+ _ = buildSummaryPrompt(todos)
657+ }
658+ })
659+ }
660+}
661+
662+func TestPreparePrompt_FiltersImageAttachments(t *testing.T) {
663+ env := testEnv(t)
664+ sa := testSessionAgent(env, nil, nil, "test prompt")
665+ agent := sa.(*sessionAgent)
666+
667+ ctx := t.Context()
668+ sess, err := env.sessions.Create(ctx, "test")
669+ require.NoError(t, err)
670+
671+ // User message with text, a text attachment, and an image attachment.
672+ _, err = env.messages.Create(ctx, sess.ID, message.CreateMessageParams{
673+ Role: message.User,
674+ Parts: []message.ContentPart{
675+ message.TextContent{Text: "hello world"},
676+ message.BinaryContent{Path: "notes.txt", MIMEType: "text/plain", Data: []byte("important notes")},
677+ message.BinaryContent{Path: "image.png", MIMEType: "image/png", Data: []byte("fake-image-data")},
678+ },
679+ })
680+ require.NoError(t, err)
681+
682+ msgs, err := env.messages.List(ctx, sess.ID)
683+ require.NoError(t, err)
684+
685+ // When supportsImages is false, image attachments should be stripped.
686+ history, _ := agent.preparePrompt(msgs, false)
687+ // First message is the system reminder, second is the user message.
688+ require.Len(t, history, 2)
689+ require.Len(t, history[1].Content, 1)
690+ text, ok := fantasy.AsMessagePart[fantasy.TextPart](history[1].Content[0])
691+ require.True(t, ok)
692+ require.Contains(t, text.Text, "hello world")
693+ require.Contains(t, text.Text, "important notes")
694+
695+ // When supportsImages is true, image attachments should remain.
696+ history, _ = agent.preparePrompt(msgs, true)
697+ require.Len(t, history, 2)
698+ require.Len(t, history[1].Content, 2)
699+ text, ok = fantasy.AsMessagePart[fantasy.TextPart](history[1].Content[0])
700+ require.True(t, ok)
701+ require.Contains(t, text.Text, "hello world")
702+ file, ok := fantasy.AsMessagePart[fantasy.FilePart](history[1].Content[1])
703+ require.True(t, ok)
704+ require.Equal(t, "image.png", file.Filename)
705+}
706+
707+func TestPreparePrompt_OrphanedToolUse(t *testing.T) {
708+ env := testEnv(t)
709+ sa := testSessionAgent(env, nil, nil, "test prompt")
710+ agent := sa.(*sessionAgent)
711+
712+ ctx := t.Context()
713+ sess, err := env.sessions.Create(ctx, "test")
714+ require.NoError(t, err)
715+
716+ // Create a user message.
717+ _, err = env.messages.Create(ctx, sess.ID, message.CreateMessageParams{
718+ Role: message.User,
719+ Parts: []message.ContentPart{
720+ message.TextContent{Text: "hello"},
721+ },
722+ })
723+ require.NoError(t, err)
724+
725+ // Create an assistant message with a tool call but no tool result —
726+ // this simulates a cancelled/interrupted agent tool call.
727+ _, err = env.messages.Create(ctx, sess.ID, message.CreateMessageParams{
728+ Role: message.Assistant,
729+ Parts: []message.ContentPart{
730+ message.TextContent{Text: "let me check"},
731+ message.ToolCall{
732+ ID: "call_orphaned_1",
733+ Name: "agent",
734+ Input: `{"prompt":"do something"}`,
735+ Finished: true,
736+ },
737+ },
738+ })
739+ require.NoError(t, err)
740+
741+ // Create the next user message (the one that interrupted the tool call).
742+ _, err = env.messages.Create(ctx, sess.ID, message.CreateMessageParams{
743+ Role: message.User,
744+ Parts: []message.ContentPart{
745+ message.TextContent{Text: "Fix #2"},
746+ },
747+ })
748+ require.NoError(t, err)
749+
750+ msgs, err := env.messages.List(ctx, sess.ID)
751+ require.NoError(t, err)
752+
753+ history, _ := agent.preparePrompt(msgs, true)
754+
755+ // The history must contain a synthetic tool result for the orphaned call.
756+ found := false
757+ for _, msg := range history {
758+ if msg.Role != fantasy.MessageRoleTool {
759+ continue
760+ }
761+ for _, part := range msg.Content {
762+ if tr, ok := fantasy.AsMessagePart[fantasy.ToolResultPart](part); ok {
763+ if tr.ToolCallID == "call_orphaned_1" {
764+ found = true
765+ _, isError := tr.Output.(fantasy.ToolResultOutputContentError)
766+ require.True(t, isError, "orphaned tool result should be an error")
767+ }
768+ }
769+ }
770+ }
771+ require.True(t, found, "expected synthetic tool result for orphaned tool call")
772+}
773+
774+func TestPreparePrompt_OrphanedToolUseMixed(t *testing.T) {
775+ env := testEnv(t)
776+ sa := testSessionAgent(env, nil, nil, "test prompt")
777+ agent := sa.(*sessionAgent)
778+
779+ ctx := t.Context()
780+ sess, err := env.sessions.Create(ctx, "test")
781+ require.NoError(t, err)
782+
783+ _, err = env.messages.Create(ctx, sess.ID, message.CreateMessageParams{
784+ Role: message.User,
785+ Parts: []message.ContentPart{
786+ message.TextContent{Text: "hello"},
787+ },
788+ })
789+ require.NoError(t, err)
790+
791+ // Assistant with 2 tool calls: one has a result, one is orphaned.
792+ _, err = env.messages.Create(ctx, sess.ID, message.CreateMessageParams{
793+ Role: message.Assistant,
794+ Parts: []message.ContentPart{
795+ message.ToolCall{
796+ ID: "call_ok",
797+ Name: "view",
798+ Input: `{"path":"/foo"}`,
799+ Finished: true,
800+ },
801+ message.ToolCall{
802+ ID: "call_orphaned",
803+ Name: "agent",
804+ Input: `{"prompt":"search"}`,
805+ Finished: true,
806+ },
807+ },
808+ })
809+ require.NoError(t, err)
810+
811+ // Only one tool result — for call_ok.
812+ _, err = env.messages.Create(ctx, sess.ID, message.CreateMessageParams{
813+ Role: message.Tool,
814+ Parts: []message.ContentPart{
815+ message.ToolResult{
816+ ToolCallID: "call_ok",
817+ Name: "view",
818+ Content: "file contents",
819+ },
820+ },
821+ })
822+ require.NoError(t, err)
823+
824+ msgs, err := env.messages.List(ctx, sess.ID)
825+ require.NoError(t, err)
826+
827+ history, _ := agent.preparePrompt(msgs, true)
828+
829+ // Should have a synthetic result only for the orphaned call.
830+ var syntheticCount int
831+ for _, msg := range history {
832+ if msg.Role != fantasy.MessageRoleTool {
833+ continue
834+ }
835+ for _, part := range msg.Content {
836+ if tr, ok := fantasy.AsMessagePart[fantasy.ToolResultPart](part); ok {
837+ if tr.ToolCallID == "call_orphaned" {
838+ syntheticCount++
839+ }
840+ }
841+ }
842+ }
843+ require.Equal(t, 1, syntheticCount, "expected exactly one synthetic result for the orphaned call")
844+}
845+
846+func TestWorkaroundProviderMediaLimitations_TextOnlyModel(t *testing.T) {
847+ env := testEnv(t)
848+ sa := testSessionAgent(env, nil, nil, "test prompt")
849+ agent := sa.(*sessionAgent)
850+
851+ pngBase64 := base64.StdEncoding.EncodeToString([]byte("fake-png-data"))
852+
853+ messages := []fantasy.Message{
854+ {
855+ Role: fantasy.MessageRoleTool,
856+ Content: []fantasy.MessagePart{
857+ fantasy.ToolResultPart{
858+ ToolCallID: "call_1",
859+ Output: fantasy.ToolResultOutputContentMedia{
860+ Data: pngBase64,
861+ MediaType: "image/png",
862+ },
863+ },
864+ },
865+ },
866+ }
867+
868+ // Non-Anthropic provider, no image support — should replace media with
869+ // a text placeholder and not create a synthetic user message.
870+ largeModel := Model{
871+ ModelCfg: config.SelectedModel{Provider: "openai"},
872+ CatwalkCfg: catwalk.Model{
873+ SupportsImages: false,
874+ },
875+ }
876+
877+ result := agent.workaroundProviderMediaLimitations(messages, largeModel)
878+
879+ // Should produce exactly one message: the tool message with a text
880+ // placeholder. No synthetic user message with FilePart.
881+ require.Len(t, result, 1)
882+ require.Equal(t, fantasy.MessageRoleTool, result[0].Role)
883+
884+ tr, ok := fantasy.AsMessagePart[fantasy.ToolResultPart](result[0].Content[0])
885+ require.True(t, ok)
886+ _, ok = fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentText](tr.Output)
887+ require.True(t, ok)
888+}
889+
890+func TestWorkaroundProviderMediaLimitations_VisionModel(t *testing.T) {
891+ env := testEnv(t)
892+ sa := testSessionAgent(env, nil, nil, "test prompt")
893+ agent := sa.(*sessionAgent)
894+
895+ pngBase64 := base64.StdEncoding.EncodeToString([]byte("fake-png-data"))
896+
897+ messages := []fantasy.Message{
898+ {
899+ Role: fantasy.MessageRoleTool,
900+ Content: []fantasy.MessagePart{
901+ fantasy.ToolResultPart{
902+ ToolCallID: "call_1",
903+ Output: fantasy.ToolResultOutputContentMedia{
904+ Data: pngBase64,
905+ MediaType: "image/png",
906+ },
907+ },
908+ },
909+ },
910+ }
911+
912+ // Non-Anthropic provider, image support — should create a synthetic
913+ // user message with FilePart.
914+ largeModel := Model{
915+ ModelCfg: config.SelectedModel{Provider: "openai"},
916+ CatwalkCfg: catwalk.Model{
917+ SupportsImages: true,
918+ },
919+ }
920+
921+ result := agent.workaroundProviderMediaLimitations(messages, largeModel)
922+
923+ // Should produce two messages: tool message with placeholder text,
924+ // and synthetic user message with FilePart.
925+ require.Len(t, result, 2)
926+ require.Equal(t, fantasy.MessageRoleTool, result[0].Role)
927+ require.Equal(t, fantasy.MessageRoleUser, result[1].Role)
928+
929+ // The tool message should have text placeholder.
930+ tr, ok := fantasy.AsMessagePart[fantasy.ToolResultPart](result[0].Content[0])
931+ require.True(t, ok)
932+ textOutput, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentText](tr.Output)
933+ require.True(t, ok)
934+ require.Contains(t, textOutput.Text, "see attached file")
935+
936+ // The synthetic user message should contain a TextPart and a FilePart.
937+ require.Len(t, result[1].Content, 2)
938+ file, ok := fantasy.AsMessagePart[fantasy.FilePart](result[1].Content[1])
939+ require.True(t, ok)
940+ require.Equal(t, "image/png", file.MediaType)
941+}
942+
943+func TestWorkaroundProviderMediaLimitations_AnthropicProvider(t *testing.T) {
944+ env := testEnv(t)
945+ sa := testSessionAgent(env, nil, nil, "test prompt")
946+ agent := sa.(*sessionAgent)
947+
948+ pngBase64 := base64.StdEncoding.EncodeToString([]byte("fake-png-data"))
949+
950+ messages := []fantasy.Message{
951+ {
952+ Role: fantasy.MessageRoleTool,
953+ Content: []fantasy.MessagePart{
954+ fantasy.ToolResultPart{
955+ ToolCallID: "call_1",
956+ Output: fantasy.ToolResultOutputContentMedia{
957+ Data: pngBase64,
958+ MediaType: "image/png",
959+ },
960+ },
961+ },
962+ },
963+ }
964+
965+ // Anthropic provider — should return messages unchanged regardless of
966+ // SupportsImages, since Anthropic handles media in tool results natively.
967+ largeModel := Model{
968+ ModelCfg: config.SelectedModel{Provider: string(catwalk.InferenceProviderAnthropic)},
969+ CatwalkCfg: catwalk.Model{
970+ SupportsImages: true,
971+ },
972+ }
973+
974+ result := agent.workaroundProviderMediaLimitations(messages, largeModel)
975+ require.Len(t, result, 1)
976+ require.Equal(t, fantasy.MessageRoleTool, result[0].Role)
977+
978+ // The media should still be in the tool result, untouched.
979+ tr, ok := fantasy.AsMessagePart[fantasy.ToolResultPart](result[0].Content[0])
980+ require.True(t, ok)
981+ media, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentMedia](tr.Output)
982+ require.True(t, ok)
983+ require.Equal(t, "image/png", media.MediaType)
984+}
985+
986+func TestProviderRetryLogFields(t *testing.T) {
987+ t.Run("nil provider error", func(t *testing.T) {
988+ fields := providerRetryLogFields(nil, 2*time.Second)
989+ require.Equal(t, []any{"retry_delay", "2s"}, fields)
990+ })
991+
992+ t.Run("provider error with title and message", func(t *testing.T) {
993+ fields := providerRetryLogFields(&fantasy.ProviderError{
994+ StatusCode: 429,
995+ Title: "rate limit",
996+ Message: "too many requests",
997+ }, 1500*time.Millisecond)
998+ require.Equal(t, []any{
999+ "retry_delay", "1.5s",
1000+ "status_code", 429,
1001+ "title", "rate limit",
1002+ "message", "too many requests",
1003+ }, fields)
1004+ })
1005+
1006+ t.Run("provider error without optional strings", func(t *testing.T) {
1007+ fields := providerRetryLogFields(&fantasy.ProviderError{
1008+ StatusCode: 503,
1009+ }, time.Second)
1010+ require.Equal(t, []any{
1011+ "retry_delay", "1s",
1012+ "status_code", 503,
1013+ }, fields)
1014+ })
1015+}
internal/agent/agent_tool.go+14−55
@@ -3,9 +3,7 @@ package agent
33import (
44 "context"
55 _ "embed"
6− "encoding/json"
76 "errors"
8− "fmt"
97
108 "charm.land/fantasy"
119
@@ -15,7 +13,7 @@ import (
1513)
1614
1715//go:embed templates/agent_tool.md
18−var agentToolDescription []byte
16+var agentToolDescription string
1917
2018type AgentParams struct {
2119 Prompt string `json:"prompt" description:"The task for the agent to perform"`
@@ -26,7 +24,7 @@ const (
2624)
2725
2826func (c *coordinator) agentTool(ctx context.Context) (fantasy.AgentTool, error) {
29− agentCfg, ok := c.cfg.Agents[config.AgentTask]
27+ agentCfg, ok := c.cfg.Config().Agents[config.AgentTask]
3028 if !ok {
3129 return nil, errors.New("task agent not configured")
3230 }
@@ -35,17 +33,14 @@ func (c *coordinator) agentTool(ctx context.Context) (fantasy.AgentTool, error)
3533 return nil, err
3634 }
3735
38− agent, err := c.buildAgent(ctx, prompt, agentCfg)
36+ agent, err := c.buildAgent(ctx, prompt, agentCfg, true)
3937 if err != nil {
4038 return nil, err
4139 }
42− return fantasy.NewAgentTool(
40+ return fantasy.NewParallelAgentTool(
4341 AgentToolName,
44− string(agentToolDescription),
42+ agentToolDescription,
4543 func(ctx context.Context, params AgentParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
46− if err := json.Unmarshal([]byte(call.Input), &params); err != nil {
47− return fantasy.NewTextErrorResponse(fmt.Sprintf("error parsing parameters: %s", err)), nil
48− }
4944 if params.Prompt == "" {
5045 return fantasy.NewTextErrorResponse("prompt is required"), nil
5146 }
@@ -60,50 +55,14 @@ func (c *coordinator) agentTool(ctx context.Context) (fantasy.AgentTool, error)
6055 return fantasy.ToolResponse{}, errors.New("agent message id missing from context")
6156 }
6257
63− agentToolSessionID := c.sessions.CreateAgentToolSessionID(agentMessageID, call.ID)
64− session, err := c.sessions.CreateTaskSession(ctx, agentToolSessionID, sessionID, "New Agent Session")
65− if err != nil {
66− return fantasy.ToolResponse{}, fmt.Errorf("error creating session: %s", err)
67− }
68− model := agent.Model()
69− maxTokens := model.CatwalkCfg.DefaultMaxTokens
70− if model.ModelCfg.MaxTokens != 0 {
71− maxTokens = model.ModelCfg.MaxTokens
72− }
73−
74− providerCfg, ok := c.cfg.Providers.Get(model.ModelCfg.Provider)
75− if !ok {
76− return fantasy.ToolResponse{}, errors.New("model provider not configured")
77− }
78− result, err := agent.Run(ctx, SessionAgentCall{
79− SessionID: session.ID,
80− Prompt: params.Prompt,
81− MaxOutputTokens: maxTokens,
82− ProviderOptions: getProviderOptions(model, providerCfg.Type),
83− Temperature: model.ModelCfg.Temperature,
84− TopP: model.ModelCfg.TopP,
85− TopK: model.ModelCfg.TopK,
86− FrequencyPenalty: model.ModelCfg.FrequencyPenalty,
87− PresencePenalty: model.ModelCfg.PresencePenalty,
58+ return c.runSubAgent(ctx, subAgentParams{
59+ Agent: agent,
60+ SessionID: sessionID,
61+ AgentMessageID: agentMessageID,
62+ ToolCallID: call.ID,
63+ Prompt: params.Prompt,
64+ SessionTitle: "New Agent Session",
8865 })
89− if err != nil {
90− return fantasy.NewTextErrorResponse("error generating response"), nil
91− }
92− updatedSession, err := c.sessions.Get(ctx, session.ID)
93− if err != nil {
94− return fantasy.ToolResponse{}, fmt.Errorf("error getting session: %s", err)
95− }
96− parentSession, err := c.sessions.Get(ctx, sessionID)
97− if err != nil {
98− return fantasy.ToolResponse{}, fmt.Errorf("error getting parent session: %s", err)
99− }
100−
101− parentSession.Cost += updatedSession.Cost
102−
103− _, err = c.sessions.Save(ctx, parentSession)
104− if err != nil {
105− return fantasy.ToolResponse{}, fmt.Errorf("error saving parent session: %s", err)
106− }
107− return fantasy.NewTextResponse(result.Response.Content.Text()), nil
108− }), nil
66+ },
67+ ), nil
10968}
internal/agent/agentic_fetch_tool.gonew file+206
@@ -0,0 +1,206 @@
1+package agent
2+
3+import (
4+ "context"
5+ _ "embed"
6+ "errors"
7+ "fmt"
8+ "net/http"
9+ "os"
10+ "time"
11+
12+ "charm.land/fantasy"
13+
14+ "github.com/charmbracelet/crush/internal/agent/prompt"
15+ "github.com/charmbracelet/crush/internal/agent/tools"
16+ "github.com/charmbracelet/crush/internal/permission"
17+)
18+
19+//go:embed templates/agentic_fetch.md
20+var agenticFetchToolDescription string
21+
22+// agenticFetchValidationResult holds the validated parameters from the tool call context.
23+type agenticFetchValidationResult struct {
24+ SessionID string
25+ AgentMessageID string
26+}
27+
28+// validateAgenticFetchParams validates the tool call parameters and extracts required context values.
29+func validateAgenticFetchParams(ctx context.Context, params tools.AgenticFetchParams) (agenticFetchValidationResult, error) {
30+ if params.Prompt == "" {
31+ return agenticFetchValidationResult{}, errors.New("prompt is required")
32+ }
33+
34+ sessionID := tools.GetSessionFromContext(ctx)
35+ if sessionID == "" {
36+ return agenticFetchValidationResult{}, errors.New("session id missing from context")
37+ }
38+
39+ agentMessageID := tools.GetMessageFromContext(ctx)
40+ if agentMessageID == "" {
41+ return agenticFetchValidationResult{}, errors.New("agent message id missing from context")
42+ }
43+
44+ return agenticFetchValidationResult{
45+ SessionID: sessionID,
46+ AgentMessageID: agentMessageID,
47+ }, nil
48+}
49+
50+//go:embed templates/agentic_fetch_prompt.md.tpl
51+var agenticFetchPromptTmpl []byte
52+
53+func (c *coordinator) agenticFetchTool(_ context.Context, client *http.Client) (fantasy.AgentTool, error) {
54+ if client == nil {
55+ transport := http.DefaultTransport.(*http.Transport).Clone()
56+ transport.MaxIdleConns = 100
57+ transport.MaxIdleConnsPerHost = 10
58+ transport.IdleConnTimeout = 90 * time.Second
59+
60+ client = &http.Client{
61+ Timeout: 30 * time.Second,
62+ Transport: transport,
63+ }
64+ }
65+
66+ return fantasy.NewParallelAgentTool(
67+ tools.AgenticFetchToolName,
68+ agenticFetchToolDescription,
69+ func(ctx context.Context, params tools.AgenticFetchParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
70+ validationResult, err := validateAgenticFetchParams(ctx, params)
71+ if err != nil {
72+ return fantasy.NewTextErrorResponse(err.Error()), nil
73+ }
74+
75+ // Determine description based on mode.
76+ var description string
77+ if params.URL != "" {
78+ description = fmt.Sprintf("Fetch and analyze content from URL: %s", params.URL)
79+ } else {
80+ description = "Search the web and analyze results"
81+ }
82+
83+ p, err := c.permissions.Request(
84+ ctx,
85+ permission.CreatePermissionRequest{
86+ SessionID: validationResult.SessionID,
87+ Path: c.cfg.WorkingDir(),
88+ ToolCallID: call.ID,
89+ ToolName: tools.AgenticFetchToolName,
90+ Action: "fetch",
91+ Description: description,
92+ Params: tools.AgenticFetchPermissionsParams(params),
93+ },
94+ )
95+ if err != nil {
96+ return fantasy.ToolResponse{}, err
97+ }
98+ if !p {
99+ return tools.NewPermissionDeniedResponse(), nil
100+ }
101+
102+ tmpDir, err := os.MkdirTemp(c.cfg.Config().Options.DataDirectory, "crush-fetch-*")
103+ if err != nil {
104+ return fantasy.NewTextErrorResponse(fmt.Sprintf("Failed to create temporary directory: %s", err)), nil
105+ }
106+ defer os.RemoveAll(tmpDir)
107+
108+ var fullPrompt string
109+
110+ if params.URL != "" {
111+ // URL mode: fetch the URL content first.
112+ content, err := tools.FetchURLAndConvert(ctx, client, params.URL)
113+ if err != nil {
114+ return fantasy.NewTextErrorResponse(fmt.Sprintf("Failed to fetch URL: %s", err)), nil
115+ }
116+
117+ hasLargeContent := len(content) > tools.LargeContentThreshold
118+
119+ if hasLargeContent {
120+ tempFile, err := os.CreateTemp(tmpDir, "page-*.md")
121+ if err != nil {
122+ return fantasy.NewTextErrorResponse(fmt.Sprintf("Failed to create temporary file: %s", err)), nil
123+ }
124+ tempFilePath := tempFile.Name()
125+
126+ if _, err := tempFile.WriteString(content); err != nil {
127+ tempFile.Close()
128+ return fantasy.NewTextErrorResponse(fmt.Sprintf("Failed to write content to file: %s", err)), nil
129+ }
130+ tempFile.Close()
131+
132+ fullPrompt = fmt.Sprintf("%s\n\nThe web page from %s has been saved to: %s\n\nUse the view and grep tools to analyze this file and extract the requested information.", params.Prompt, params.URL, tempFilePath)
133+ } else {
134+ fullPrompt = fmt.Sprintf("%s\n\nWeb page URL: %s\n\n<webpage_content>\n%s\n</webpage_content>", params.Prompt, params.URL, content)
135+ }
136+ } else {
137+ // Search mode: let the sub-agent search and fetch as needed.
138+ fullPrompt = fmt.Sprintf("%s\n\nUse the web_search tool to find relevant information. Break down the question into smaller, focused searches if needed. After searching, use web_fetch to get detailed content from the most relevant results.", params.Prompt)
139+ }
140+
141+ promptOpts := []prompt.Option{
142+ prompt.WithWorkingDir(tmpDir),
143+ }
144+
145+ promptTemplate, err := prompt.NewPrompt("agentic_fetch", string(agenticFetchPromptTmpl), promptOpts...)
146+ if err != nil {
147+ return fantasy.ToolResponse{}, fmt.Errorf("error creating prompt: %s", err)
148+ }
149+
150+ _, small, err := c.buildAgentModels(ctx, true)
151+ if err != nil {
152+ return fantasy.ToolResponse{}, fmt.Errorf("error building models: %s", err)
153+ }
154+
155+ systemPrompt, err := promptTemplate.Build(ctx, small.Model.Provider(), small.Model.Model(), c.cfg)
156+ if err != nil {
157+ return fantasy.ToolResponse{}, fmt.Errorf("error building system prompt: %s", err)
158+ }
159+
160+ smallProviderCfg, ok := c.cfg.Config().Providers.Get(small.ModelCfg.Provider)
161+ if !ok {
162+ return fantasy.ToolResponse{}, errors.New("small model provider not configured")
163+ }
164+
165+ webFetchTool := tools.NewWebFetchTool(tmpDir, client)
166+ webSearchTool := tools.NewWebSearchTool(client)
167+ fetchTools := []fantasy.AgentTool{
168+ webFetchTool,
169+ webSearchTool,
170+ tools.NewGlobTool(tmpDir, c.cfg.Config().Tools.Glob),
171+ tools.NewGrepTool(tmpDir, c.cfg.Config().Tools.Grep),
172+ tools.NewSourcegraphTool(client),
173+ tools.NewViewTool(c.lspManager, c.permissions, c.filetracker, nil, tmpDir),
174+ }
175+
176+ // Sub-agent tools run without hook interception. The top-level
177+ // `agentic_fetch` call itself is already wrapped from the coder's
178+ // side; firing hooks again for every inner tool call would run
179+ // the user's hooks N times per delegated turn.
180+
181+ agent := NewSessionAgent(SessionAgentOptions{
182+ LargeModel: small, // Use small model for both (fetch doesn't need large)
183+ SmallModel: small,
184+ SystemPromptPrefix: smallProviderCfg.SystemPromptPrefix,
185+ SystemPrompt: systemPrompt,
186+ DisableAutoSummarize: c.cfg.Config().Options.DisableAutoSummarize,
187+ IsYolo: c.permissions.SkipRequests(),
188+ Sessions: c.sessions,
189+ Messages: c.messages,
190+ Tools: fetchTools,
191+ })
192+
193+ return c.runSubAgent(ctx, subAgentParams{
194+ Agent: agent,
195+ SessionID: validationResult.SessionID,
196+ AgentMessageID: validationResult.AgentMessageID,
197+ ToolCallID: call.ID,
198+ Prompt: fullPrompt,
199+ SessionTitle: "Fetch Analysis",
200+ SessionSetup: func(sessionID string) {
201+ c.permissions.AutoApproveSession(sessionID)
202+ },
203+ })
204+ },
205+ ), nil
206+}
internal/agent/agenttest/coordinator.gonew file+80
@@ -0,0 +1,80 @@
1+// Package agenttest provides test-only constructors for wiring a real
2+// production agent.Coordinator without booting a full app.App. It is
3+// imported only from _test.go files (e.g. internal/backend integration
4+// tests) and is never referenced by production code, so it is compiled
5+// only under tests and never ships in the production binary or API.
6+package agenttest
7+
8+import (
9+ "context"
10+
11+ "charm.land/catwalk/pkg/catwalk"
12+ "charm.land/fantasy/providers/openaicompat"
13+ "github.com/charmbracelet/crush/internal/agent"
14+ "github.com/charmbracelet/crush/internal/config"
15+ "github.com/charmbracelet/crush/internal/message"
16+ "github.com/charmbracelet/crush/internal/permission"
17+ "github.com/charmbracelet/crush/internal/session"
18+)
19+
20+// NewCoordinator builds a real agent.Coordinator through the production
21+// agent.NewCoordinator constructor so the RunAccepted / BeginAccepted /
22+// run path (including UpdateModels) is the actual code under test.
23+//
24+// It installs a minimal config with a single openai-compatible provider
25+// whose model resolves offline. run rebuilds the model on every call, so
26+// the provider must construct without network I/O; the cancel-on-entry
27+// path this helper is built to exercise returns before any model call,
28+// so no request is ever issued. The coder agent's allowed-tools list is
29+// cleared to keep tool construction cheap and free of sub-agent wiring.
30+//
31+// The optional coordinator dependencies (history, filetracker, LSP,
32+// notify, runComplete, skills) are nil: run guards the publisher fields
33+// and the cancel-on-entry path never touches the others.
34+func NewCoordinator(
35+ ctx context.Context,
36+ workingDir string,
37+ sessions session.Service,
38+ messages message.Service,
39+) (agent.Coordinator, error) {
40+ cfg, err := config.Init(workingDir, "", false)
41+ if err != nil {
42+ return nil, err
43+ }
44+
45+ const (
46+ providerID = "test-openai-compat"
47+ modelID = "test-model"
48+ )
49+ cfg.Config().Providers.Set(providerID, config.ProviderConfig{
50+ ID: providerID,
51+ Name: "Test",
52+ Type: openaicompat.Name,
53+ BaseURL: "http://127.0.0.1:0/v1",
54+ APIKey: "test",
55+ Models: []catwalk.Model{{ID: modelID, DefaultMaxTokens: 4096}},
56+ })
57+ selected := config.SelectedModel{Provider: providerID, Model: modelID}
58+ cfg.OverridePreferredModel(config.SelectedModelTypeLarge, selected)
59+ cfg.OverridePreferredModel(config.SelectedModelTypeSmall, selected)
60+ cfg.SetupAgents()
61+
62+ // Keep buildTools light: no sub-agent or agentic-fetch construction.
63+ coderCfg := cfg.Config().Agents[config.AgentCoder]
64+ coderCfg.AllowedTools = nil
65+ cfg.Config().Agents[config.AgentCoder] = coderCfg
66+
67+ return agent.NewCoordinator(
68+ ctx,
69+ cfg,
70+ sessions,
71+ messages,
72+ permission.NewPermissionService(workingDir, true, nil),
73+ nil,
74+ nil,
75+ nil,
76+ nil,
77+ nil,
78+ nil,
79+ )
80+}
internal/agent/common_test.go+72−73
@@ -1,44 +1,45 @@
11package agent
22
33import (
4+ "context"
45 "net/http"
56 "os"
67 "path/filepath"
78 "testing"
89 "time"
910
11+ "charm.land/catwalk/pkg/catwalk"
1012 "charm.land/fantasy"
11− "charm.land/fantasy/providers/anthropic"
12− "charm.land/fantasy/providers/openai"
1313 "charm.land/fantasy/providers/openaicompat"
14− "charm.land/fantasy/providers/openrouter"
15− "github.com/charmbracelet/catwalk/pkg/catwalk"
14+ "charm.land/x/vcr"
1615 "github.com/charmbracelet/crush/internal/agent/prompt"
1716 "github.com/charmbracelet/crush/internal/agent/tools"
1817 "github.com/charmbracelet/crush/internal/config"
1918 "github.com/charmbracelet/crush/internal/csync"
2019 "github.com/charmbracelet/crush/internal/db"
20+ "github.com/charmbracelet/crush/internal/filetracker"
2121 "github.com/charmbracelet/crush/internal/history"
2222 "github.com/charmbracelet/crush/internal/lsp"
2323 "github.com/charmbracelet/crush/internal/message"
2424 "github.com/charmbracelet/crush/internal/permission"
2525 "github.com/charmbracelet/crush/internal/session"
2626 "github.com/stretchr/testify/require"
27− "gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
2827
2928 _ "github.com/joho/godotenv/autoload"
3029)
3130
32−type env struct {
31+// fakeEnv is an environment for testing.
32+type fakeEnv struct {
3333 workingDir string
3434 sessions session.Service
3535 messages message.Service
3636 permissions permission.Service
3737 history history.Service
38+ filetracker *filetracker.Service
3839 lspClients *csync.Map[string, *lsp.Client]
3940}
4041
41−type builderFunc func(t *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error)
42+type builderFunc func(t *testing.T, r *vcr.Recorder) (fantasy.LanguageModel, error)
4243
4344type modelPair struct {
4445 name string
@@ -46,50 +47,11 @@ type modelPair struct {
4647 smallModel builderFunc
4748}
4849
49−func anthropicBuilder(model string) builderFunc {
50− return func(t *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
51− provider, err := anthropic.New(
52− anthropic.WithAPIKey(os.Getenv("CRUSH_ANTHROPIC_API_KEY")),
53− anthropic.WithHTTPClient(&http.Client{Transport: r}),
54− )
55− if err != nil {
56− return nil, err
57− }
58− return provider.LanguageModel(t.Context(), model)
59− }
60−}
61−
62−func openaiBuilder(model string) builderFunc {
63− return func(t *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
64− provider, err := openai.New(
65− openai.WithAPIKey(os.Getenv("CRUSH_OPENAI_API_KEY")),
66− openai.WithHTTPClient(&http.Client{Transport: r}),
67− )
68− if err != nil {
69− return nil, err
70− }
71− return provider.LanguageModel(t.Context(), model)
72− }
73−}
74−
75−func openRouterBuilder(model string) builderFunc {
76− return func(t *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
77− provider, err := openrouter.New(
78− openrouter.WithAPIKey(os.Getenv("CRUSH_OPENROUTER_API_KEY")),
79− openrouter.WithHTTPClient(&http.Client{Transport: r}),
80− )
81− if err != nil {
82− return nil, err
83− }
84− return provider.LanguageModel(t.Context(), model)
85− }
86−}
87−
88−func zAIBuilder(model string) builderFunc {
89− return func(t *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
50+func hyperBuilder(model string) builderFunc {
51+ return func(t *testing.T, r *vcr.Recorder) (fantasy.LanguageModel, error) {
9052 provider, err := openaicompat.New(
91− openaicompat.WithBaseURL("https://api.z.ai/api/coding/paas/v4"),
92− openaicompat.WithAPIKey(os.Getenv("CRUSH_ZAI_API_KEY")),
53+ openaicompat.WithBaseURL("https://hyper.charm.land/v1"),
54+ openaicompat.WithAPIKey(os.Getenv("CRUSH_HYPER_API_KEY")),
9355 openaicompat.WithHTTPClient(&http.Client{Transport: r}),
9456 )
9557 if err != nil {
@@ -99,34 +61,42 @@ func zAIBuilder(model string) builderFunc {
9961 }
10062}
10163
102−func testEnv(t *testing.T) env {
103− testDir := filepath.Join("/tmp/crush-test/", t.Name())
104− os.RemoveAll(testDir)
105− err := os.MkdirAll(testDir, 0o755)
106− t.Cleanup(func() {
107− os.RemoveAll(testDir)
108− })
64+func testEnv(t *testing.T) fakeEnv {
65+ workingDir := filepath.Join("/tmp/crush-test/", t.Name())
66+ os.RemoveAll(workingDir)
67+
68+ err := os.MkdirAll(workingDir, 0o755)
10969 require.NoError(t, err)
110− workingDir := testDir
70+
11171 conn, err := db.Connect(t.Context(), t.TempDir())
11272 require.NoError(t, err)
73+
11374 q := db.New(conn)
114− sessions := session.NewService(q)
75+ sessions := session.NewService(q, conn)
11576 messages := message.NewService(q)
77+
11678 permissions := permission.NewPermissionService(workingDir, true, []string{})
11779 history := history.NewService(q, conn)
80+ filetrackerService := filetracker.NewService(q)
11881 lspClients := csync.NewMap[string, *lsp.Client]()
119− return env{
82+
83+ t.Cleanup(func() {
84+ conn.Close()
85+ os.RemoveAll(workingDir)
86+ })
87+
88+ return fakeEnv{
12089 workingDir,
12190 sessions,
12291 messages,
12392 permissions,
12493 history,
94+ &filetrackerService,
12595 lspClients,
12696 }
12797}
12898
129−func testSessionAgent(env env, large, small fantasy.LanguageModel, systemPrompt string, tools ...fantasy.AgentTool) SessionAgent {
99+func testSessionAgent(env fakeEnv, large, small fantasy.LanguageModel, systemPrompt string, tools ...fantasy.AgentTool) SessionAgent {
130100 largeModel := Model{
131101 Model: large,
132102 CatwalkCfg: catwalk.Model{
@@ -141,11 +111,19 @@ func testSessionAgent(env env, large, small fantasy.LanguageModel, systemPrompt
141111 DefaultMaxTokens: 10000,
142112 },
143113 }
144− agent := NewSessionAgent(SessionAgentOptions{largeModel, smallModel, systemPrompt, false, env.sessions, env.messages, tools})
114+ agent := NewSessionAgent(SessionAgentOptions{
115+ LargeModel: largeModel,
116+ SmallModel: smallModel,
117+ SystemPrompt: systemPrompt,
118+ IsYolo: true,
119+ Sessions: env.sessions,
120+ Messages: env.messages,
121+ Tools: tools,
122+ })
145123 return agent
146124}
147125
148−func coderAgent(r *recorder.Recorder, env env, large, small fantasy.LanguageModel) (SessionAgent, error) {
126+func coderAgent(r *vcr.Recorder, env fakeEnv, large, small fantasy.LanguageModel) (SessionAgent, error) {
149127 fixedTime := func() time.Time {
150128 t, _ := time.Parse("1/2/2006", "1/1/2025")
151129 return t
@@ -153,7 +131,7 @@ func coderAgent(r *recorder.Recorder, env env, large, small fantasy.LanguageMode
153131 prompt, err := coderPrompt(
154132 prompt.WithTimeFunc(fixedTime),
155133 prompt.WithPlatform("linux"),
156− prompt.WithWorkingDir(env.workingDir),
134+ prompt.WithWorkingDir(filepath.ToSlash(env.workingDir)),
157135 )
158136 if err != nil {
159137 return nil, err
@@ -163,22 +141,43 @@ func coderAgent(r *recorder.Recorder, env env, large, small fantasy.LanguageMode
163141 return nil, err
164142 }
165143
166− systemPrompt, err := prompt.Build(large.Provider(), large.Model(), *cfg)
144+ // NOTE(@andreynering): Set a fixed config to ensure cassettes match
145+ // independently of user config on `$HOME/.config/crush/crush.json`.
146+ cfg.Config().Options.Attribution = &config.Attribution{
147+ TrailerStyle: "co-authored-by",
148+ GeneratedWith: true,
149+ }
150+
151+ // Clear some fields to avoid issues with VCR cassette matching.
152+ cfg.Config().Options.SkillsPaths = nil
153+ cfg.Config().Options.DisabledSkills = []string{"crush-config"}
154+ cfg.Config().Options.ContextPaths = nil
155+ cfg.Config().Options.GlobalContextPaths = nil
156+ cfg.Config().LSP = nil
157+
158+ systemPrompt, err := prompt.Build(context.TODO(), large.Provider(), large.Model(), cfg)
167159 if err != nil {
168160 return nil, err
169161 }
162+
163+ // Get the model name for the bash tool
164+ modelName := large.Model() // fallback to ID if Name not available
165+ if model := cfg.Config().GetModel(large.Provider(), large.Model()); model != nil {
166+ modelName = model.Name
167+ }
168+
170169 allTools := []fantasy.AgentTool{
171− tools.NewBashTool(env.permissions, env.workingDir, cfg.Options.Attribution),
170+ tools.NewBashTool(env.permissions, env.workingDir, cfg.Config().Options.Attribution, modelName),
172171 tools.NewDownloadTool(env.permissions, env.workingDir, r.GetDefaultClient()),
173− tools.NewEditTool(env.lspClients, env.permissions, env.history, env.workingDir),
174− tools.NewMultiEditTool(env.lspClients, env.permissions, env.history, env.workingDir),
172+ tools.NewEditTool(nil, env.permissions, env.history, *env.filetracker, env.workingDir),
173+ tools.NewMultiEditTool(nil, env.permissions, env.history, *env.filetracker, env.workingDir),
175174 tools.NewFetchTool(env.permissions, env.workingDir, r.GetDefaultClient()),
176− tools.NewGlobTool(env.workingDir),
177− tools.NewGrepTool(env.workingDir),
178− tools.NewLsTool(env.permissions, env.workingDir, cfg.Tools.Ls),
175+ tools.NewGlobTool(env.workingDir, cfg.Config().Tools.Glob),
176+ tools.NewGrepTool(env.workingDir, cfg.Config().Tools.Grep),
177+ tools.NewLsTool(env.permissions, env.workingDir, cfg.Config().Tools.Ls),
179178 tools.NewSourcegraphTool(r.GetDefaultClient()),
180− tools.NewViewTool(env.lspClients, env.permissions, env.workingDir),
181− tools.NewWriteTool(env.lspClients, env.permissions, env.history, env.workingDir),
179+ tools.NewViewTool(nil, env.permissions, *env.filetracker, nil, env.workingDir),
180+ tools.NewWriteTool(nil, env.permissions, env.history, *env.filetracker, env.workingDir),
182181 }
183182
184183 return testSessionAgent(env, large, small, systemPrompt, allTools...), nil
internal/agent/convert_test.gonew file+94
@@ -0,0 +1,94 @@
1+package agent
2+
3+import (
4+ "encoding/base64"
5+ "testing"
6+
7+ "charm.land/fantasy"
8+ "github.com/stretchr/testify/require"
9+)
10+
11+func TestConvertToToolResult_InvalidBase64(t *testing.T) {
12+ t.Parallel()
13+
14+ a := &sessionAgent{}
15+ result := fantasy.ToolResultContent{
16+ ToolCallID: "call_123",
17+ ToolName: "test_tool",
18+ Result: fantasy.ToolResultOutputContentMedia{
19+ Data: "abc\x80def",
20+ MediaType: "image/png",
21+ },
22+ }
23+
24+ tr := a.convertToToolResult(result)
25+ require.True(t, tr.IsError)
26+ require.Empty(t, tr.Data)
27+ require.Contains(t, tr.Content, "invalid encoding")
28+ require.Equal(t, "call_123", tr.ToolCallID)
29+ require.Equal(t, "test_tool", tr.Name)
30+}
31+
32+func TestConvertToToolResult_ValidMedia(t *testing.T) {
33+ t.Parallel()
34+
35+ a := &sessionAgent{}
36+ validData := base64.StdEncoding.EncodeToString([]byte("test image data"))
37+
38+ result := fantasy.ToolResultContent{
39+ ToolCallID: "call_456",
40+ ToolName: "screenshot",
41+ Result: fantasy.ToolResultOutputContentMedia{
42+ Data: validData,
43+ MediaType: "image/png",
44+ Text: "Screenshot captured",
45+ },
46+ }
47+
48+ tr := a.convertToToolResult(result)
49+ require.False(t, tr.IsError)
50+ require.Equal(t, validData, tr.Data)
51+ require.Equal(t, "image/png", tr.MIMEType)
52+ require.Equal(t, "Screenshot captured", tr.Content)
53+}
54+
55+func TestConvertToToolResult_ValidMediaNoText(t *testing.T) {
56+ t.Parallel()
57+
58+ a := &sessionAgent{}
59+ validData := base64.StdEncoding.EncodeToString([]byte("test image data"))
60+
61+ result := fantasy.ToolResultContent{
62+ ToolCallID: "call_789",
63+ ToolName: "view",
64+ Result: fantasy.ToolResultOutputContentMedia{
65+ Data: validData,
66+ MediaType: "image/jpeg",
67+ },
68+ }
69+
70+ tr := a.convertToToolResult(result)
71+ require.False(t, tr.IsError)
72+ require.Equal(t, validData, tr.Data)
73+ require.Equal(t, "image/jpeg", tr.MIMEType)
74+ require.Equal(t, "Loaded image/jpeg content", tr.Content)
75+}
76+
77+func TestConvertToToolResult_ASCIIButInvalidBase64(t *testing.T) {
78+ t.Parallel()
79+
80+ a := &sessionAgent{}
81+ result := fantasy.ToolResultContent{
82+ ToolCallID: "call_abc",
83+ ToolName: "mcp_tool",
84+ Result: fantasy.ToolResultOutputContentMedia{
85+ Data: "not-valid-base64!!!",
86+ MediaType: "image/png",
87+ },
88+ }
89+
90+ tr := a.convertToToolResult(result)
91+ require.True(t, tr.IsError)
92+ require.Empty(t, tr.Data)
93+ require.Contains(t, tr.Content, "invalid encoding")
94+}
internal/agent/coordinator.go+1164−170
@@ -6,82 +6,203 @@ import (
66 "context"
77 "encoding/json"
88 "errors"
9+ "fmt"
910 "io"
1011 "log/slog"
12+ "maps"
13+ "net/http"
14+ "os"
15+ "path/filepath"
1116 "slices"
1217 "strings"
18+ "sync"
19+ "sync/atomic"
1320
21+ "charm.land/catwalk/pkg/catwalk"
1422 "charm.land/fantasy"
15− "github.com/charmbracelet/catwalk/pkg/catwalk"
23+ "github.com/charmbracelet/crush/internal/agent/hyper"
24+ "github.com/charmbracelet/crush/internal/agent/notify"
1625 "github.com/charmbracelet/crush/internal/agent/prompt"
1726 "github.com/charmbracelet/crush/internal/agent/tools"
27+ "github.com/charmbracelet/crush/internal/agent/tools/mcp"
1828 "github.com/charmbracelet/crush/internal/config"
1929 "github.com/charmbracelet/crush/internal/csync"
30+ "github.com/charmbracelet/crush/internal/discover"
31+ "github.com/charmbracelet/crush/internal/event"
32+ "github.com/charmbracelet/crush/internal/filetracker"
2033 "github.com/charmbracelet/crush/internal/history"
34+ "github.com/charmbracelet/crush/internal/hooks"
2135 "github.com/charmbracelet/crush/internal/log"
2236 "github.com/charmbracelet/crush/internal/lsp"
2337 "github.com/charmbracelet/crush/internal/message"
38+ "github.com/charmbracelet/crush/internal/oauth/copilot"
2439 "github.com/charmbracelet/crush/internal/permission"
40+ "github.com/charmbracelet/crush/internal/pubsub"
2541 "github.com/charmbracelet/crush/internal/session"
42+ "github.com/charmbracelet/crush/internal/skills"
43+ "golang.org/x/sync/errgroup"
2644
2745 "charm.land/fantasy/providers/anthropic"
2846 "charm.land/fantasy/providers/azure"
47+ "charm.land/fantasy/providers/bedrock"
2948 "charm.land/fantasy/providers/google"
3049 "charm.land/fantasy/providers/openai"
3150 "charm.land/fantasy/providers/openaicompat"
3251 "charm.land/fantasy/providers/openrouter"
52+ "charm.land/fantasy/providers/vercel"
53+ openaisdk "github.com/charmbracelet/openai-go/option"
3354 "github.com/qjebbs/go-jsons"
3455)
3556
57+// Coordinator errors.
58+var (
59+ errCoderAgentNotConfigured = errors.New("coder agent not configured")
60+ errModelProviderNotConfigured = errors.New("model provider not configured")
61+ errLargeModelNotSelected = errors.New("large model not selected")
62+ errSmallModelNotSelected = errors.New("small model not selected")
63+ errLargeModelProviderNotConfigured = errors.New("large model provider not configured")
64+ errSmallModelProviderNotConfigured = errors.New("small model provider not configured")
65+ errLargeModelNotFound = errors.New("large model not found in provider config")
66+ errSmallModelNotFound = errors.New("small model not found in provider config")
67+)
68+
69+// Copilot models that use the Responses API instead of Chat Completions.
70+var copilotResponsesModels = map[string]bool{
71+ "gpt-5.2": true,
72+ "gpt-5.2-codex": true,
73+ "gpt-5.3-codex": true,
74+ "gpt-5.4": true,
75+ "gpt-5.4-mini": true,
76+ "gpt-5.5": true,
77+ "gpt-5-mini": true,
78+}
79+
80+// OpenCode models that user Anthropic Messages API instead of Chat Completions.
81+var opencodeMessagesModels = map[string]bool{
82+ "qwen3.7-max": true,
83+}
84+
3685type Coordinator interface {
3786 // INFO: (kujtim) this is not used yet we will use this when we have multiple agents
3887 // SetMainAgent(string)
3988 Run(ctx context.Context, sessionID, prompt string, attachments ...message.Attachment) (*fantasy.AgentResult, error)
89+ // RunAccepted runs a call that was already accepted via
90+ // BeginAccepted on the fire-and-forget dispatch path. The handle is
91+ // the only carrier of accept-state across the backend.runAgent /
92+ // Coordinator / sessionAgent.Run layers: it reaches
93+ // sessionAgent.Run as SessionAgentCall.Accepted, where it is
94+ // consumed under dispatchMu once the accepted -> (cancel-on-entry |
95+ // queued | active) transition is chosen.
96+ RunAccepted(ctx context.Context, accept *AcceptedRun, sessionID, prompt string, attachments ...message.Attachment) (*fantasy.AgentResult, error)
97+ BeginAccepted(sessionID string) *AcceptedRun
4098 Cancel(sessionID string)
4199 CancelAll()
42100 IsSessionBusy(sessionID string) bool
43101 IsBusy() bool
44102 QueuedPrompts(sessionID string) int
103+ QueuedPromptsList(sessionID string) []string
45104 ClearQueue(sessionID string)
46105 Summarize(context.Context, string) error
47106 Model() Model
48107 UpdateModels(ctx context.Context) error
108+ GenerateTitle(ctx context.Context, sessionID, prompt string)
49109}
50110
51111type coordinator struct {
52− cfg *config.Config
112+ cfg *config.ConfigStore
53113 sessions session.Service
54114 messages message.Service
55115 permissions permission.Service
56116 history history.Service
57− lspClients *csync.Map[string, *lsp.Client]
117+ filetracker filetracker.Service
118+ lspManager *lsp.Manager
119+ notify pubsub.Publisher[notify.Notification]
120+ runComplete pubsub.Publisher[notify.RunComplete]
58121
59122 currentAgent SessionAgent
60123 agents map[string]SessionAgent
124+
125+ // Skills discovery results (session-start snapshot).
126+ allSkills []*skills.Skill // Pre-filter: all discovered after dedup.
127+ activeSkills []*skills.Skill // Post-filter: active skills only.
128+ skillTracker *skills.Tracker
129+
130+ // providerClients caches built provider clients keyed by their fully
131+ // resolved configuration. UpdateModels rebuilds models every turn;
132+ // without this, each turn discards the provider's HTTP client and its
133+ // keep-alive connection pool, forcing a fresh TLS handshake. The key
134+ // captures every input buildProvider depends on, so any config/model/
135+ // credential change misses the cache and rebuilds.
136+ providerClients *csync.Map[string, fantasy.Provider]
137+
138+ // toolsCache avoids rebuilding the tool set on every UpdateModels call.
139+ // The cache is invalidated when the config pointer changes (reload or
140+ // mutation) or when mcpToolsGen is bumped (MCP server connect/disconnect
141+ // or tools/list_changed notification).
142+ toolsCacheMu sync.Mutex
143+ toolsCache []fantasy.AgentTool
144+ toolsCacheCfg *config.Config
145+ toolsCacheMCP uint64
146+ mcpToolsGen atomic.Uint64
147+
148+ // providerOptsCache avoids repeating the 3× JSON marshal + merge +
149+ // unmarshal in getProviderOptions on every turn when the model and
150+ // config have not changed. Keyed by config pointer + model CatwalkCfg
151+ // ID + provider name.
152+ providerOptsCacheMu sync.Mutex
153+ providerOptsCache fantasy.ProviderOptions
154+ providerOptsCacheKey string
155+
156+ readyWg errgroup.Group
61157}
62158
63159func NewCoordinator(
64160 ctx context.Context,
65− cfg *config.Config,
161+ cfg *config.ConfigStore,
66162 sessions session.Service,
67163 messages message.Service,
68164 permissions permission.Service,
69165 history history.Service,
70− lspClients *csync.Map[string, *lsp.Client],
166+ filetracker filetracker.Service,
167+ lspManager *lsp.Manager,
168+ notify pubsub.Publisher[notify.Notification],
169+ runComplete pubsub.Publisher[notify.RunComplete],
170+ skillsMgr *skills.Manager,
71171) (Coordinator, error) {
72− c := &coordinator{
73− cfg: cfg,
74− sessions: sessions,
75− messages: messages,
76− permissions: permissions,
77− history: history,
78− lspClients: lspClients,
79− agents: make(map[string]SessionAgent),
80− }
172+ // Skills are pre-discovered by the caller (see app.New /
173+ // backend.CreateWorkspace) and passed in via the manager. If no
174+ // manager was provided (legacy callers), fall back to an in-line
175+ // discovery so the coordinator still works.
176+ var allSkills, activeSkills []*skills.Skill
177+ if skillsMgr != nil {
178+ allSkills = skillsMgr.AllSkills()
179+ activeSkills = skillsMgr.ActiveSkills()
180+ } else {
181+ allSkills, activeSkills = discoverSkills(cfg)
182+ }
183+ skillTracker := skills.NewTracker(activeSkills)
81184
82− agentCfg, ok := cfg.Agents[config.AgentCoder]
185+ c := &coordinator{
186+ cfg: cfg,
187+ sessions: sessions,
188+ messages: messages,
189+ permissions: permissions,
190+ history: history,
191+ filetracker: filetracker,
192+ lspManager: lspManager,
193+ notify: notify,
194+ runComplete: runComplete,
195+ agents: make(map[string]SessionAgent),
196+ allSkills: allSkills,
197+ activeSkills: activeSkills,
198+ skillTracker: skillTracker,
199+
200+ providerClients: csync.NewMap[string, fantasy.Provider](),
201+ }
202+
203+ agentCfg, ok := cfg.Config().Agents[config.AgentCoder]
83204 if !ok {
84− return nil, errors.New("coder agent not configured")
205+ return nil, errCoderAgentNotConfigured
85206 }
86207
87208 // TODO: make this dynamic when we support multiple agents
@@ -90,17 +211,51 @@ func NewCoordinator(
90211 return nil, err
91212 }
92213
93− agent, err := c.buildAgent(ctx, prompt, agentCfg)
214+ agent, err := c.buildAgent(ctx, prompt, agentCfg, false)
94215 if err != nil {
95216 return nil, err
96217 }
97218 c.currentAgent = agent
98219 c.agents[config.AgentCoder] = agent
220+
221+ // Subscribe to MCP tool-list changes so the tools cache is invalidated
222+ // when MCP servers connect/disconnect or announce new tools.
223+ go func() {
224+ for ev := range mcp.SubscribeEvents(ctx) {
225+ if ev.Payload.Type == mcp.EventToolsListChanged || ev.Payload.Type == mcp.EventStateChanged {
226+ c.mcpToolsGen.Add(1)
227+ }
228+ }
229+ }()
230+
99231 return c, nil
100232}
101233
102234// Run implements Coordinator.
103235func (c *coordinator) Run(ctx context.Context, sessionID string, prompt string, attachments ...message.Attachment) (*fantasy.AgentResult, error) {
236+ return c.run(ctx, nil, sessionID, prompt, attachments...)
237+}
238+
239+// RunAccepted implements Coordinator.
240+func (c *coordinator) RunAccepted(ctx context.Context, accept *AcceptedRun, sessionID string, prompt string, attachments ...message.Attachment) (*fantasy.AgentResult, error) {
241+ return c.run(ctx, accept, sessionID, prompt, attachments...)
242+}
243+
244+// run is the shared implementation behind Run and RunAccepted. When
245+// accept is non-nil it is threaded onto the SessionAgentCall as
246+// Accepted so sessionAgent.Run can consume the accept reservation under
247+// dispatchMu; when nil (the in-process/local path) no accept tracking
248+// applies.
249+func (c *coordinator) run(ctx context.Context, accept *AcceptedRun, sessionID string, prompt string, attachments ...message.Attachment) (*fantasy.AgentResult, error) {
250+ if err := c.readyWg.Wait(); err != nil {
251+ return nil, err
252+ }
253+
254+ // refresh models before each run
255+ if err := c.UpdateModels(ctx); err != nil {
256+ return nil, fmt.Errorf("failed to update models: %w", err)
257+ }
258+
104259 model := c.currentAgent.Model()
105260 maxTokens := model.CatwalkCfg.DefaultMaxTokens
106261 if model.ModelCfg.MaxTokens != 0 {
@@ -108,34 +263,124 @@ func (c *coordinator) Run(ctx context.Context, sessionID string, prompt string,
108263 }
109264
110265 if !model.CatwalkCfg.SupportsImages && attachments != nil {
111− attachments = nil
266+ // filter out image attachments
267+ filteredAttachments := make([]message.Attachment, 0, len(attachments))
268+ for _, att := range attachments {
269+ if att.IsText() {
270+ filteredAttachments = append(filteredAttachments, att)
271+ }
272+ }
273+ attachments = filteredAttachments
112274 }
113275
114− providerCfg, ok := c.cfg.Providers.Get(model.ModelCfg.Provider)
276+ providerCfg, ok := c.cfg.Config().Providers.Get(model.ModelCfg.Provider)
115277 if !ok {
116− return nil, errors.New("model provider not configured")
117− }
118−
119− mergedOptions, temp, topP, topK, freqPenalty, presPenalty := mergeCallOptions(model, providerCfg.Type)
120−
121− return c.currentAgent.Run(ctx, SessionAgentCall{
122− SessionID: sessionID,
123− Prompt: prompt,
124− Attachments: attachments,
125− MaxOutputTokens: maxTokens,
126− ProviderOptions: mergedOptions,
127− Temperature: temp,
128− TopP: topP,
129− TopK: topK,
130− FrequencyPenalty: freqPenalty,
131− PresencePenalty: presPenalty,
278+ return nil, errModelProviderNotConfigured
279+ }
280+
281+ mergedOptions, temp, topP, topK, freqPenalty, presPenalty := c.cachedMergeCallOptions(model, providerCfg)
282+
283+ if err := c.refreshTokenIfExpired(ctx, providerCfg); err != nil {
284+ // NOTE(@andreynering): We don't return here because the event handling to ask the user to reauthenticate
285+ // depends on the flow below. If refresh fails, proceed with the token we have.
286+ slog.Error("Failed to refresh OAuth2 token. Proceeding with existing token.", "error", err)
287+ }
288+
289+ // Coalesce per-attempt RunComplete payloads so only the final
290+ // outcome reaches subscribers. Without this, the first attempt's
291+ // failed RunComplete (unauthorized) would race ahead of the
292+ // retry's success, and `crush run` would exit on the stale error
293+ // before ever seeing the retry result. Each attempt's
294+ // SessionAgentCall.OnComplete hook overwrites latest; we publish
295+ // exactly once after retries resolve, via PublishMustDeliver, so
296+ // a momentarily-full subscriber buffer can't silently drop the
297+ // terminal event.
298+ var (
299+ latest notify.RunComplete
300+ hasLatest bool
301+ )
302+ onComplete := func(rc notify.RunComplete) {
303+ latest = rc
304+ hasLatest = true
305+ }
306+ // Propagate the caller-supplied RunID (set via agent.WithRunID
307+ // at the HTTP boundary in backend.SendMessage) onto the
308+ // SessionAgentCall so the terminal RunComplete event echoes it
309+ // back. Both attempts in the retry chain reuse the same RunID;
310+ // the coalesce closure publishes the final outcome under that
311+ // same correlator.
312+ runID := RunIDFromContext(ctx)
313+ run := func() (*fantasy.AgentResult, error) {
314+ return c.currentAgent.Run(ctx, SessionAgentCall{
315+ SessionID: sessionID,
316+ RunID: runID,
317+ Prompt: prompt,
318+ Attachments: attachments,
319+ MaxOutputTokens: maxTokens,
320+ ProviderOptions: mergedOptions,
321+ Temperature: temp,
322+ TopP: topP,
323+ TopK: topK,
324+ FrequencyPenalty: freqPenalty,
325+ PresencePenalty: presPenalty,
326+ OnComplete: onComplete,
327+ Accepted: accept,
328+ })
329+ }
330+ beforeLoaded := c.skillTracker.LoadedNames()
331+ var result *fantasy.AgentResult
332+ originalErr := c.runWithUnauthorizedRetry(ctx, providerCfg, func() error {
333+ var err error
334+ result, err = run()
335+ return err
132336 })
337+ logTurnSkillUsage(sessionID, prompt, c.activeSkills, c.skillTracker, beforeLoaded)
338+
339+ // Notify only if still unauthorized after retry — a successful
340+ // retry means the user doesn't need to re-authenticate.
341+ if originalErr != nil && c.isUnauthorized(originalErr) && c.notify != nil && model.ModelCfg.Provider == hyper.Name {
342+ c.notify.Publish(pubsub.CreatedEvent, notify.Notification{
343+ Type: notify.TypeReAuthenticate,
344+ ProviderID: model.ModelCfg.Provider,
345+ })
346+ }
347+
348+ if hasLatest && c.runComplete != nil {
349+ c.runComplete.PublishMustDeliver(ctx, pubsub.UpdatedEvent, latest)
350+ // Signal to the dispatcher (backend.runAgent) that the
351+ // authoritative terminal RunComplete for this run was already
352+ // emitted, so it does not publish a duplicate fallback for the
353+ // error it is about to receive.
354+ MarkRunCompletePublished(ctx)
355+ }
356+ return result, originalErr
357+}
358+
359+// effectiveReasoningEffort returns the reasoning effort to apply for provider calls.
360+// It prefers the user-selected effort when valid, otherwise the model default when
361+// valid, and finally falls back to the first configured reasoning level.
362+func effectiveReasoningEffort(model Model) string {
363+ if !model.CatwalkCfg.CanReason {
364+ return ""
365+ }
366+
367+ if effort := model.ModelCfg.ReasoningEffort; effort != "" && slices.Contains(model.CatwalkCfg.ReasoningLevels, effort) {
368+ return effort
369+ }
370+ if effort := model.CatwalkCfg.DefaultReasoningEffort; effort != "" && slices.Contains(model.CatwalkCfg.ReasoningLevels, effort) {
371+ return effort
372+ }
373+ if len(model.CatwalkCfg.ReasoningLevels) > 0 {
374+ return model.CatwalkCfg.ReasoningLevels[0]
375+ }
376+ return ""
133377}
134378
135−func getProviderOptions(model Model, tp catwalk.Type) fantasy.ProviderOptions {
379+func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.ProviderOptions {
136380 options := fantasy.ProviderOptions{}
137381
138382 cfgOpts := []byte("{}")
383+ providerCfgOpts := []byte("{}")
139384 catwalkOpts := []byte("{}")
140385
141386 if model.ModelCfg.ProviderOptions != nil {
@@ -145,6 +390,13 @@ func getProviderOptions(model Model, tp catwalk.Type) fantasy.ProviderOptions {
145390 }
146391 }
147392
393+ if providerCfg.ProviderOptions != nil {
394+ data, err := json.Marshal(providerCfg.ProviderOptions)
395+ if err == nil {
396+ providerCfgOpts = data
397+ }
398+ }
399+
148400 if model.CatwalkCfg.Options.ProviderOptions != nil {
149401 data, err := json.Marshal(model.CatwalkCfg.Options.ProviderOptions)
150402 if err == nil {
@@ -154,6 +406,7 @@ func getProviderOptions(model Model, tp catwalk.Type) fantasy.ProviderOptions {
154406
155407 readers := []io.Reader{
156408 bytes.NewReader(catwalkOpts),
409+ bytes.NewReader(providerCfgOpts),
157410 bytes.NewReader(cfgOpts),
158411 }
159412
@@ -171,11 +424,16 @@ func getProviderOptions(model Model, tp catwalk.Type) fantasy.ProviderOptions {
171424 return options
172425 }
173426
174− switch tp {
175− case openai.Name:
427+ reasoningEffort := effectiveReasoningEffort(model)
428+ shouldSetEffort := model.CatwalkCfg.CanReason &&
429+ reasoningEffort != "" &&
430+ slices.Contains(model.CatwalkCfg.ReasoningLevels, reasoningEffort)
431+
432+ switch providerCfg.Type {
433+ case openai.Name, azure.Name:
176434 _, hasReasoningEffort := mergedOptions["reasoning_effort"]
177− if !hasReasoningEffort && model.ModelCfg.ReasoningEffort != "" {
178− mergedOptions["reasoning_effort"] = model.ModelCfg.ReasoningEffort
435+ if !hasReasoningEffort && shouldSetEffort {
436+ mergedOptions["reasoning_effort"] = reasoningEffort
179437 }
180438 if openai.IsResponsesModel(model.CatwalkCfg.ID) {
181439 if openai.IsResponsesReasoningModel(model.CatwalkCfg.ID) {
@@ -192,14 +450,37 @@ func getProviderOptions(model Model, tp catwalk.Type) fantasy.ProviderOptions {
192450 options[openai.Name] = parsed
193451 }
194452 }
195− case anthropic.Name:
196− _, hasThink := mergedOptions["thinking"]
197− if !hasThink && model.ModelCfg.Think {
198− mergedOptions["thinking"] = map[string]any{
199− // TODO: kujtim see if we need to make this dynamic
200− "budget_tokens": 2000,
453+
454+ case anthropic.Name, bedrock.Name:
455+ var (
456+ _, hasEffort = mergedOptions["effort"]
457+ _, hasThink = mergedOptions["thinking"]
458+ extraBody = make(map[string]any)
459+ )
460+
461+ switch providerCfg.ID {
462+ case string(catwalk.InferenceProviderAlibabaSingapore), string(catwalk.InferenceProviderAlibabaUS):
463+ switch {
464+ case !hasEffort && shouldSetEffort:
465+ extraBody["reasoning_effort"] = reasoningEffort
466+ case !hasThink && model.CatwalkCfg.CanReason:
467+ if model.ModelCfg.Think {
468+ extraBody["thinking"] = map[string]any{"type": "enabled"}
469+ } else {
470+ extraBody["thinking"] = map[string]any{"type": "disabled"}
471+ }
472+ }
473+ mergedOptions["extra_body"] = extraBody
474+
475+ default:
476+ switch {
477+ case !hasEffort && shouldSetEffort:
478+ mergedOptions["effort"] = reasoningEffort
479+ case !hasThink && model.ModelCfg.Think:
480+ mergedOptions["thinking"] = map[string]any{"budget_tokens": 2000}
201481 }
202482 }
483+
203484 parsed, err := anthropic.ParseOptions(mergedOptions)
204485 if err == nil {
205486 options[anthropic.Name] = parsed
@@ -207,54 +488,130 @@ func getProviderOptions(model Model, tp catwalk.Type) fantasy.ProviderOptions {
207488
208489 case openrouter.Name:
209490 _, hasReasoning := mergedOptions["reasoning"]
210− if !hasReasoning && model.ModelCfg.ReasoningEffort != "" {
491+ if !hasReasoning && shouldSetEffort {
211492 mergedOptions["reasoning"] = map[string]any{
212493 "enabled": true,
213− "effort": model.ModelCfg.ReasoningEffort,
494+ "effort": reasoningEffort,
214495 }
215496 }
216497 parsed, err := openrouter.ParseOptions(mergedOptions)
217498 if err == nil {
218499 options[openrouter.Name] = parsed
219500 }
501+
502+ case vercel.Name:
503+ _, hasReasoning := mergedOptions["reasoning"]
504+ if !hasReasoning && shouldSetEffort {
505+ mergedOptions["reasoning"] = map[string]any{
506+ "enabled": true,
507+ "effort": reasoningEffort,
508+ }
509+ }
510+ parsed, err := vercel.ParseOptions(mergedOptions)
511+ if err == nil {
512+ options[vercel.Name] = parsed
513+ }
514+
220515 case google.Name:
221516 _, hasReasoning := mergedOptions["thinking_config"]
222517 if !hasReasoning {
223− mergedOptions["thinking_config"] = map[string]any{
224− "thinking_budget": 2000,
225− "include_thoughts": true,
518+ if strings.HasPrefix(model.CatwalkCfg.ID, "gemini-2") {
519+ mergedOptions["thinking_config"] = map[string]any{
520+ "thinking_budget": 2000,
521+ "include_thoughts": true,
522+ }
523+ } else {
524+ mergedOptions["thinking_config"] = map[string]any{
525+ "thinking_level": reasoningEffort,
526+ "include_thoughts": true,
527+ }
226528 }
227529 }
228530 parsed, err := google.ParseOptions(mergedOptions)
229531 if err == nil {
230532 options[google.Name] = parsed
231533 }
232− case azure.Name:
534+
535+ case openaicompat.Name, hyper.Name:
536+ extraBody := make(map[string]any)
537+
233538 _, hasReasoningEffort := mergedOptions["reasoning_effort"]
234− if !hasReasoningEffort && model.ModelCfg.ReasoningEffort != "" {
235− mergedOptions["reasoning_effort"] = model.ModelCfg.ReasoningEffort
236− }
237− // azure uses the same options as openaicompat
238− parsed, err := openaicompat.ParseOptions(mergedOptions)
239− if err == nil {
240− options[azure.Name] = parsed
539+ if !hasReasoningEffort && shouldSetEffort {
540+ switch providerCfg.ID {
541+ case string(catwalk.InferenceProviderIoNet):
542+ extraBody["reasoning"] = map[string]string{"effort": reasoningEffort}
543+ default:
544+ mergedOptions["reasoning_effort"] = reasoningEffort
545+ }
241546 }
242− case openaicompat.Name:
243− _, hasReasoningEffort := mergedOptions["reasoning_effort"]
244− if !hasReasoningEffort && model.ModelCfg.ReasoningEffort != "" {
245− mergedOptions["reasoning_effort"] = model.ModelCfg.ReasoningEffort
547+
548+ // "reasoning effort" is a standard OpenAI field, but "thinking" is not.
549+ // Setting it in the right way for each provider.
550+ // TODO: Abstract this in Fantasy somehow?
551+ // TODO: Allow custom providers to specify how to set this?
552+ switch providerCfg.ID {
553+ case hyper.Name:
554+ extraBody["thinking"] = model.ModelCfg.Think
555+ case string(catwalk.InferenceProviderIoNet):
556+ if _, ok := extraBody["reasoning"]; !ok && model.CatwalkCfg.CanReason {
557+ if model.ModelCfg.Think {
558+ extraBody["reasoning"] = map[string]string{"effort": "medium"}
559+ } else {
560+ extraBody["reasoning"] = map[string]string{"effort": "none"}
561+ }
562+ }
563+
564+ case string(catwalk.InferenceProviderZAI), string(catwalk.InferenceProviderDeepSeek):
565+ if model.ModelCfg.Think || reasoningEffort != "" {
566+ extraBody["thinking"] = map[string]any{"type": "enabled"}
567+ } else {
568+ extraBody["thinking"] = map[string]any{"type": "disabled"}
569+ }
570+
571+ case string(catwalk.InferenceProviderFireworks):
572+ // NOTE: Fireworks break if we set both `reasoning_effort` and `thinking`.
573+ if reasoningEffort == "" {
574+ if model.ModelCfg.Think {
575+ extraBody["thinking"] = map[string]any{"type": "enabled"}
576+ } else {
577+ extraBody["thinking"] = map[string]any{"type": "disabled"}
578+ }
579+ }
580+
581+ case string(catwalk.InferenceProviderBaseten):
582+ extraBody["chat_template_args"] = map[string]any{
583+ "enable_thinking": model.ModelCfg.Think || reasoningEffort != "",
584+ }
585+
586+ case string(catwalk.InferenceProviderAlibabaSingapore), string(catwalk.InferenceProviderAlibabaUS):
587+ if model.CatwalkCfg.CanReason {
588+ extraBody["enable_thinking"] = model.ModelCfg.Think || reasoningEffort != ""
589+ }
246590 }
591+
592+ mergedOptions["extra_body"] = extraBody
593+
247594 parsed, err := openaicompat.ParseOptions(mergedOptions)
248595 if err == nil {
249596 options[openaicompat.Name] = parsed
250597 }
598+
599+ default:
600+ // Known custom providers (litellm, ollama, omlx) are
601+ // openai-compat under the hood.
602+ if discover.IsKnownCustomProvider(string(providerCfg.Type)) {
603+ parsed, err := openaicompat.ParseOptions(mergedOptions)
604+ if err == nil {
605+ options[openaicompat.Name] = parsed
606+ }
607+ }
251608 }
252609
253610 return options
254611}
255612
256−func mergeCallOptions(model Model, tp catwalk.Type) (fantasy.ProviderOptions, *float64, *float64, *int64, *float64, *float64) {
257− modelOptions := getProviderOptions(model, tp)
613+func mergeCallOptions(model Model, cfg config.ProviderConfig) (fantasy.ProviderOptions, *float64, *float64, *int64, *float64, *float64) {
614+ modelOptions := getProviderOptions(model, cfg)
258615 temp := cmp.Or(model.ModelCfg.Temperature, model.CatwalkCfg.Options.Temperature)
259616 topP := cmp.Or(model.ModelCfg.TopP, model.CatwalkCfg.Options.TopP)
260617 topK := cmp.Or(model.ModelCfg.TopK, model.CatwalkCfg.Options.TopK)
@@ -263,25 +620,83 @@ func mergeCallOptions(model Model, tp catwalk.Type) (fantasy.ProviderOptions, *f
263620 return modelOptions, temp, topP, topK, freqPenalty, presPenalty
264621}
265622
266−func (c *coordinator) buildAgent(ctx context.Context, prompt *prompt.Prompt, agent config.Agent) (SessionAgent, error) {
267− large, small, err := c.buildAgentModels(ctx)
268− if err != nil {
269− return nil, err
270− }
623+// cachedMergeCallOptions wraps mergeCallOptions with a memoization cache.
624+// The provider options JSON merge is expensive (3× marshal + merge +
625+// unmarshal) and the inputs rarely change between turns. The cache key
626+// combines the config pointer identity with the model's catwalk ID and
627+// provider name so any config reload or model switch misses the cache.
628+func (c *coordinator) cachedMergeCallOptions(model Model, cfg config.ProviderConfig) (fantasy.ProviderOptions, *float64, *float64, *int64, *float64, *float64) {
629+ key := fmt.Sprintf("%p|%s|%s", c.cfg.Config(), model.CatwalkCfg.ID, model.ModelCfg.Provider)
630+
631+ c.providerOptsCacheMu.Lock()
632+ if c.providerOptsCacheKey == key {
633+ opts := c.providerOptsCache
634+ c.providerOptsCacheMu.Unlock()
635+ // Recompute the scalar overrides (cheap) since they don't need
636+ // the JSON merge — they're just cmp.Or calls.
637+ temp := cmp.Or(model.ModelCfg.Temperature, model.CatwalkCfg.Options.Temperature)
638+ topP := cmp.Or(model.ModelCfg.TopP, model.CatwalkCfg.Options.TopP)
639+ topK := cmp.Or(model.ModelCfg.TopK, model.CatwalkCfg.Options.TopK)
640+ freqPenalty := cmp.Or(model.ModelCfg.FrequencyPenalty, model.CatwalkCfg.Options.FrequencyPenalty)
641+ presPenalty := cmp.Or(model.ModelCfg.PresencePenalty, model.CatwalkCfg.Options.PresencePenalty)
642+ return opts, temp, topP, topK, freqPenalty, presPenalty
643+ }
644+ c.providerOptsCacheMu.Unlock()
645+
646+ opts, temp, topP, topK, freqPenalty, presPenalty := mergeCallOptions(model, cfg)
647+
648+ c.providerOptsCacheMu.Lock()
649+ c.providerOptsCache = opts
650+ c.providerOptsCacheKey = key
651+ c.providerOptsCacheMu.Unlock()
652+
653+ return opts, temp, topP, topK, freqPenalty, presPenalty
654+}
271655
272− systemPrompt, err := prompt.Build(large.Model.Provider(), large.Model.Model(), *c.cfg)
656+func (c *coordinator) buildAgent(ctx context.Context, prompt *prompt.Prompt, agent config.Agent, isSubAgent bool) (SessionAgent, error) {
657+ large, small, err := c.buildAgentModels(ctx, isSubAgent)
273658 if err != nil {
274659 return nil, err
275660 }
276661
277− tools, err := c.buildTools(ctx, agent)
278− if err != nil {
279− return nil, err
280− }
281− return NewSessionAgent(SessionAgentOptions{large, small, systemPrompt, c.cfg.Options.DisableAutoSummarize, c.sessions, c.messages, tools}), nil
662+ largeProviderCfg, _ := c.cfg.Config().Providers.Get(large.ModelCfg.Provider)
663+ result := NewSessionAgent(SessionAgentOptions{
664+ LargeModel: large,
665+ SmallModel: small,
666+ SystemPromptPrefix: largeProviderCfg.SystemPromptPrefix,
667+ SystemPrompt: "",
668+ IsSubAgent: isSubAgent,
669+ DisableAutoSummarize: c.cfg.Config().Options.DisableAutoSummarize,
670+ IsYolo: c.permissions.SkipRequests(),
671+ Sessions: c.sessions,
672+ Messages: c.messages,
673+ Tools: nil,
674+ Notify: c.notify,
675+ RunComplete: c.runComplete,
676+ })
677+
678+ c.readyWg.Go(func() error {
679+ systemPrompt, err := prompt.Build(ctx, large.Model.Provider(), large.Model.Model(), c.cfg)
680+ if err != nil {
681+ return err
682+ }
683+ result.SetSystemPrompt(systemPrompt)
684+ return nil
685+ })
686+
687+ c.readyWg.Go(func() error {
688+ tools, err := c.buildTools(ctx, agent, isSubAgent)
689+ if err != nil {
690+ return err
691+ }
692+ result.SetTools(tools)
693+ return nil
694+ })
695+
696+ return result, nil
282697}
283698
284−func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fantasy.AgentTool, error) {
699+func (c *coordinator) buildTools(ctx context.Context, agent config.Agent, isSubAgent bool) ([]fantasy.AgentTool, error) {
285700 var allTools []fantasy.AgentTool
286701 if slices.Contains(agent.AllowedTools, AgentToolName) {
287702 agentTool, err := c.agentTool(ctx)
@@ -291,22 +706,61 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan
291706 allTools = append(allTools, agentTool)
292707 }
293708
294− allTools = append(allTools,
295− tools.NewBashTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Options.Attribution),
709+ if slices.Contains(agent.AllowedTools, tools.AgenticFetchToolName) {
710+ agenticFetchTool, err := c.agenticFetchTool(ctx, nil)
711+ if err != nil {
712+ return nil, err
713+ }
714+ allTools = append(allTools, agenticFetchTool)
715+ }
716+
717+ // Get the model name for the agent
718+ modelID := ""
719+ if modelCfg, ok := c.cfg.Config().Models[agent.Model]; ok {
720+ if model := c.cfg.Config().GetModel(modelCfg.Provider, modelCfg.Model); model != nil {
721+ modelID = model.ID
722+ }
723+ }
724+
725+ logFile := filepath.Join(c.cfg.Config().Options.DataDirectory, "logs", "crush.log")
726+
727+ // Build hook runner if PreToolUse hooks are configured.
728+ var hookRunner *hooks.Runner
729+ if preToolHooks := c.cfg.Config().Hooks[hooks.EventPreToolUse]; len(preToolHooks) > 0 {
730+ hookRunner = hooks.NewRunner(preToolHooks, c.cfg.WorkingDir(), c.cfg.WorkingDir())
731+ }
732+
733+ allTools = append(
734+ allTools,
735+ tools.NewBashTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Config().Options.Attribution, modelID),
736+ tools.NewCrushInfoTool(c.cfg, c.lspManager, c.allSkills, c.activeSkills, c.skillTracker),
737+ tools.NewCrushLogsTool(logFile),
738+ tools.NewJobOutputTool(),
739+ tools.NewJobKillTool(),
296740 tools.NewDownloadTool(c.permissions, c.cfg.WorkingDir(), nil),
297− tools.NewEditTool(c.lspClients, c.permissions, c.history, c.cfg.WorkingDir()),
298− tools.NewMultiEditTool(c.lspClients, c.permissions, c.history, c.cfg.WorkingDir()),
741+ tools.NewEditTool(c.lspManager, c.permissions, c.history, c.filetracker, c.cfg.WorkingDir()),
742+ tools.NewMultiEditTool(c.lspManager, c.permissions, c.history, c.filetracker, c.cfg.WorkingDir()),
299743 tools.NewFetchTool(c.permissions, c.cfg.WorkingDir(), nil),
300− tools.NewGlobTool(c.cfg.WorkingDir()),
301− tools.NewGrepTool(c.cfg.WorkingDir()),
302− tools.NewLsTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Tools.Ls),
744+ tools.NewGlobTool(c.cfg.WorkingDir(), c.cfg.Config().Tools.Glob),
745+ tools.NewGrepTool(c.cfg.WorkingDir(), c.cfg.Config().Tools.Grep),
746+ tools.NewLsTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Config().Tools.Ls),
303747 tools.NewSourcegraphTool(nil),
304− tools.NewViewTool(c.lspClients, c.permissions, c.cfg.WorkingDir()),
305− tools.NewWriteTool(c.lspClients, c.permissions, c.history, c.cfg.WorkingDir()),
748+ tools.NewTodosTool(c.sessions),
749+ tools.NewViewTool(c.lspManager, c.permissions, c.filetracker, c.skillTracker, c.cfg.WorkingDir(), c.cfg.Config().Options.SkillsPaths...),
750+ tools.NewWriteTool(c.lspManager, c.permissions, c.history, c.filetracker, c.cfg.WorkingDir()),
306751 )
307752
308− if len(c.cfg.LSP) > 0 {
309− allTools = append(allTools, tools.NewDiagnosticsTool(c.lspClients), tools.NewReferencesTool(c.lspClients))
753+ // Add LSP tools if user has configured LSPs or auto_lsp is enabled (nil or true).
754+ if len(c.cfg.Config().LSP) > 0 || c.cfg.Config().Options.AutoLSP == nil || *c.cfg.Config().Options.AutoLSP {
755+ allTools = append(allTools, tools.NewDiagnosticsTool(c.lspManager), tools.NewReferencesTool(c.lspManager), tools.NewLSPRestartTool(c.lspManager))
756+ }
757+
758+ if len(c.cfg.Config().MCP) > 0 {
759+ allTools = append(
760+ allTools,
761+ tools.NewListMCPResourcesTool(c.cfg, c.permissions),
762+ tools.NewReadMCPResourceTool(c.cfg, c.permissions),
763+ )
310764 }
311765
312766 var filteredTools []fantasy.AgentTool
@@ -316,64 +770,70 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan
316770 }
317771 }
318772
319− mcpTools := tools.GetMCPTools(context.Background(), c.permissions, c.cfg)
320−
321− for _, mcpTool := range mcpTools {
773+ for _, tool := range tools.GetMCPTools(c.permissions, c.cfg, c.cfg.WorkingDir()) {
322774 if agent.AllowedMCP == nil {
323775 // No MCP restrictions
324− filteredTools = append(filteredTools, mcpTool)
325− } else if len(agent.AllowedMCP) == 0 {
326− // no mcps allowed
776+ filteredTools = append(filteredTools, tool)
777+ continue
778+ }
779+ if len(agent.AllowedMCP) == 0 {
780+ // No MCPs allowed
781+ slog.Debug("No MCPs allowed", "tool", tool.Name(), "agent", agent.Name)
327782 break
328783 }
329784
330785 for mcp, tools := range agent.AllowedMCP {
331− if mcp == mcpTool.MCP() {
332− if len(tools) == 0 {
333− filteredTools = append(filteredTools, mcpTool)
334− }
335− for _, t := range tools {
336− if t == mcpTool.MCPToolName() {
337− filteredTools = append(filteredTools, mcpTool)
338− }
339− }
786+ if mcp != tool.MCP() {
787+ continue
788+ }
789+ if len(tools) == 0 || slices.Contains(tools, tool.MCPToolName()) {
790+ filteredTools = append(filteredTools, tool)
340791 break
341792 }
793+ slog.Debug("MCP not allowed", "tool", tool.Name(), "agent", agent.Name)
342794 }
343795 }
344796 slices.SortFunc(filteredTools, func(a, b fantasy.AgentTool) int {
345797 return strings.Compare(a.Info().Name, b.Info().Name)
346798 })
799+
800+ // Wrap tools with hook interception for the top-level agent only.
801+ // Sub-agents (the `agent` task tool, `agentic_fetch`, etc.) run
802+ // without hook interception to avoid firing the user's hook N times
803+ // per delegated turn. The top-level invocation of the sub-agent tool
804+ // itself is still wrapped from the coder's side.
805+ filteredTools = wrapToolsWithHooks(filteredTools, hookRunner, isSubAgent)
806+
347807 return filteredTools, nil
348808}
349809
350810// TODO: when we support multiple agents we need to change this so that we pass in the agent specific model config
351−func (c *coordinator) buildAgentModels(ctx context.Context) (Model, Model, error) {
352− largeModelCfg, ok := c.cfg.Models[config.SelectedModelTypeLarge]
811+func (c *coordinator) buildAgentModels(ctx context.Context, isSubAgent bool) (Model, Model, error) {
812+ largeModelCfg, ok := c.cfg.Config().Models[config.SelectedModelTypeLarge]
353813 if !ok {
354− return Model{}, Model{}, errors.New("large model not selected")
814+ return Model{}, Model{}, errLargeModelNotSelected
355815 }
356− smallModelCfg, ok := c.cfg.Models[config.SelectedModelTypeSmall]
816+ smallModelCfg, ok := c.cfg.Config().Models[config.SelectedModelTypeSmall]
357817 if !ok {
358− return Model{}, Model{}, errors.New("small model not selected")
818+ return Model{}, Model{}, errSmallModelNotSelected
359819 }
360820
361− largeProviderCfg, ok := c.cfg.Providers.Get(largeModelCfg.Provider)
821+ largeProviderCfg, ok := c.cfg.Config().Providers.Get(largeModelCfg.Provider)
362822 if !ok {
363− return Model{}, Model{}, errors.New("large model provider not configured")
823+ return Model{}, Model{}, errLargeModelProviderNotConfigured
364824 }
365825
366− largeProvider, err := c.buildProvider(largeProviderCfg, largeModelCfg)
826+ largeProvider, err := c.buildProvider(largeProviderCfg, largeModelCfg, isSubAgent)
367827 if err != nil {
368828 return Model{}, Model{}, err
369829 }
370830
371− smallProviderCfg, ok := c.cfg.Providers.Get(smallModelCfg.Provider)
831+ smallProviderCfg, ok := c.cfg.Config().Providers.Get(smallModelCfg.Provider)
372832 if !ok {
373− return Model{}, Model{}, errors.New("large model provider not configured")
833+ return Model{}, Model{}, errSmallModelProviderNotConfigured
374834 }
375835
376− smallProvider, err := c.buildProvider(smallProviderCfg, largeModelCfg)
836+ smallProvider, err := c.buildProvider(smallProviderCfg, smallModelCfg, true)
377837 if err != nil {
378838 return Model{}, Model{}, err
379839 }
@@ -393,18 +853,29 @@ func (c *coordinator) buildAgentModels(ctx context.Context) (Model, Model, error
393853 }
394854
395855 if largeCatwalkModel == nil {
396− return Model{}, Model{}, errors.New("large model not found in provider config")
856+ return Model{}, Model{}, errLargeModelNotFound
397857 }
398858
399859 if smallCatwalkModel == nil {
400− return Model{}, Model{}, errors.New("snall model not found in provider config")
860+ return Model{}, Model{}, errSmallModelNotFound
401861 }
402862
403− largeModel, err := largeProvider.LanguageModel(ctx, largeModelCfg.Model)
863+ largeModelID := largeModelCfg.Model
864+ smallModelID := smallModelCfg.Model
865+
866+ if largeModelCfg.Provider == openrouter.Name && isExactoSupported(largeModelID) {
867+ largeModelID += ":exacto"
868+ }
869+
870+ if smallModelCfg.Provider == openrouter.Name && isExactoSupported(smallModelID) {
871+ smallModelID += ":exacto"
872+ }
873+
874+ largeModel, err := largeProvider.LanguageModel(ctx, largeModelID)
404875 if err != nil {
405876 return Model{}, Model{}, err
406877 }
407− smallModel, err := smallProvider.LanguageModel(ctx, smallModelCfg.Model)
878+ smallModel, err := smallProvider.LanguageModel(ctx, smallModelID)
408879 if err != nil {
409880 return Model{}, Model{}, err
410881 }
@@ -413,29 +884,29 @@ func (c *coordinator) buildAgentModels(ctx context.Context) (Model, Model, error
413884 Model: largeModel,
414885 CatwalkCfg: *largeCatwalkModel,
415886 ModelCfg: largeModelCfg,
887+ FlatRate: largeProviderCfg.FlatRate,
416888 }, Model{
417889 Model: smallModel,
418890 CatwalkCfg: *smallCatwalkModel,
419891 ModelCfg: smallModelCfg,
892+ FlatRate: smallProviderCfg.FlatRate,
420893 }, nil
421894}
422895
423−func (c *coordinator) buildAnthropicProvider(baseURL, apiKey string, headers map[string]string) (fantasy.Provider, error) {
424− hasBearerAuth := false
425− for key := range headers {
426− if strings.ToLower(key) == "authorization" {
427− hasBearerAuth = true
428− break
429− }
430− }
431− if hasBearerAuth {
432− apiKey = "" // clear apiKey to avoid using X-Api-Key header
433− }
434−
896+func (c *coordinator) buildAnthropicProvider(baseURL, apiKey string, headers map[string]string, providerID string) (fantasy.Provider, error) {
435897 var opts []anthropic.Option
436898
437− if apiKey != "" {
438− // Use standard X-Api-Key header
899+ switch {
900+ case strings.HasPrefix(apiKey, "Bearer "):
901+ // NOTE: Prevent the SDK from picking up the API key from env.
902+ os.Setenv("ANTHROPIC_API_KEY", "")
903+ headers["Authorization"] = apiKey
904+ case providerID == string(catwalk.InferenceProviderMiniMax) || providerID == string(catwalk.InferenceProviderMiniMaxChina):
905+ // NOTE: Prevent the SDK from picking up the API key from env.
906+ os.Setenv("ANTHROPIC_API_KEY", "")
907+ headers["Authorization"] = "Bearer " + apiKey
908+ case apiKey != "":
909+ // X-Api-Key header
439910 opts = append(opts, anthropic.WithAPIKey(apiKey))
440911 }
441912
@@ -447,11 +918,10 @@ func (c *coordinator) buildAnthropicProvider(baseURL, apiKey string, headers map
447918 opts = append(opts, anthropic.WithBaseURL(baseURL))
448919 }
449920
450− if c.cfg.Options.Debug {
921+ if c.cfg.Config().Options.Debug {
451922 httpClient := log.NewHTTPClient()
452923 opts = append(opts, anthropic.WithHTTPClient(httpClient))
453924 }
454−
455925 return anthropic.New(opts...)
456926}
457927
@@ -460,7 +930,7 @@ func (c *coordinator) buildOpenaiProvider(baseURL, apiKey string, headers map[st
460930 openai.WithAPIKey(apiKey),
461931 openai.WithUseResponsesAPI(),
462932 }
463− if c.cfg.Options.Debug {
933+ if c.cfg.Config().Options.Debug {
464934 httpClient := log.NewHTTPClient()
465935 opts = append(opts, openai.WithHTTPClient(httpClient))
466936 }
@@ -477,7 +947,7 @@ func (c *coordinator) buildOpenrouterProvider(_, apiKey string, headers map[stri
477947 opts := []openrouter.Option{
478948 openrouter.WithAPIKey(apiKey),
479949 }
480− if c.cfg.Options.Debug {
950+ if c.cfg.Config().Options.Debug {
481951 httpClient := log.NewHTTPClient()
482952 opts = append(opts, openrouter.WithHTTPClient(httpClient))
483953 }
@@ -487,19 +957,54 @@ func (c *coordinator) buildOpenrouterProvider(_, apiKey string, headers map[stri
487957 return openrouter.New(opts...)
488958}
489959
490−func (c *coordinator) buildOpenaiCompatProvider(baseURL, apiKey string, headers map[string]string) (fantasy.Provider, error) {
960+func (c *coordinator) buildVercelProvider(_, apiKey string, headers map[string]string) (fantasy.Provider, error) {
961+ opts := []vercel.Option{
962+ vercel.WithAPIKey(apiKey),
963+ }
964+ if c.cfg.Config().Options.Debug {
965+ httpClient := log.NewHTTPClient()
966+ opts = append(opts, vercel.WithHTTPClient(httpClient))
967+ }
968+ if len(headers) > 0 {
969+ opts = append(opts, vercel.WithHeaders(headers))
970+ }
971+ return vercel.New(opts...)
972+}
973+
974+func (c *coordinator) buildOpenaiCompatProvider(baseURL, apiKey string, headers map[string]string, extraBody map[string]any, providerID string, isSubAgent bool) (fantasy.Provider, error) {
491975 opts := []openaicompat.Option{
492976 openaicompat.WithBaseURL(baseURL),
493977 openaicompat.WithAPIKey(apiKey),
494978 }
495− if c.cfg.Options.Debug {
496− httpClient := log.NewHTTPClient()
979+
980+ // Set HTTP client based on provider and debug mode.
981+ var httpClient *http.Client
982+ switch providerID {
983+ case string(catwalk.InferenceProviderCopilot):
984+ opts = append(
985+ opts,
986+ openaicompat.WithUseResponsesAPI(),
987+ openaicompat.WithResponsesAPIFunc(func(modelID string) bool {
988+ return copilotResponsesModels[modelID]
989+ }),
990+ )
991+ httpClient = copilot.NewClient(isSubAgent, c.cfg.Config().Options.Debug)
992+ }
993+ if httpClient == nil && c.cfg.Config().Options.Debug {
994+ httpClient = log.NewHTTPClient()
995+ }
996+ if httpClient != nil {
497997 opts = append(opts, openaicompat.WithHTTPClient(httpClient))
498998 }
999+
4991000 if len(headers) > 0 {
5001001 opts = append(opts, openaicompat.WithHeaders(headers))
5011002 }
5021003
1004+ for extraKey, extraValue := range extraBody {
1005+ opts = append(opts, openaicompat.WithSDKOptions(openaisdk.WithJSONSet(extraKey, extraValue)))
1006+ }
1007+
5031008 return openaicompat.New(opts...)
5041009}
5051010
@@ -507,8 +1012,9 @@ func (c *coordinator) buildAzureProvider(baseURL, apiKey string, headers map[str
5071012 opts := []azure.Option{
5081013 azure.WithBaseURL(baseURL),
5091014 azure.WithAPIKey(apiKey),
1015+ azure.WithUseResponsesAPI(),
5101016 }
511− if c.cfg.Options.Debug {
1017+ if c.cfg.Config().Options.Debug {
5121018 httpClient := log.NewHTTPClient()
5131019 opts = append(opts, azure.WithHTTPClient(httpClient))
5141020 }
@@ -525,12 +1031,41 @@ func (c *coordinator) buildAzureProvider(baseURL, apiKey string, headers map[str
5251031 return azure.New(opts...)
5261032}
5271033
1034+func (c *coordinator) buildBedrockProvider(apiKey string, headers map[string]string, providerID string) (fantasy.Provider, error) {
1035+ var opts []bedrock.Option
1036+ if c.cfg.Config().Options.Debug {
1037+ httpClient := log.NewHTTPClient()
1038+ opts = append(opts, bedrock.WithHTTPClient(httpClient))
1039+ }
1040+ if len(headers) > 0 {
1041+ opts = append(opts, bedrock.WithHeaders(headers))
1042+ }
1043+
1044+ switch {
1045+ case apiKey != "":
1046+ opts = append(opts, bedrock.WithAPIKey(apiKey))
1047+ case os.Getenv("AWS_BEARER_TOKEN_BEDROCK") != "":
1048+ opts = append(opts, bedrock.WithAPIKey(os.Getenv("AWS_BEARER_TOKEN_BEDROCK")))
1049+ default:
1050+ // Skip, let the SDK do authentication.
1051+ }
1052+
1053+ switch providerID {
1054+ case string(catwalk.InferenceProviderBedrockEurope):
1055+ opts = append(opts, bedrock.WithRegion("eu-west-1"))
1056+ default:
1057+ opts = append(opts, bedrock.WithRegion("us-east-1"))
1058+ }
1059+
1060+ return bedrock.New(opts...)
1061+}
1062+
5281063func (c *coordinator) buildGoogleProvider(baseURL, apiKey string, headers map[string]string) (fantasy.Provider, error) {
5291064 opts := []google.Option{
5301065 google.WithBaseURL(baseURL),
5311066 google.WithGeminiAPIKey(apiKey),
5321067 }
533− if c.cfg.Options.Debug {
1068+ if c.cfg.Config().Options.Debug {
5341069 httpClient := log.NewHTTPClient()
5351070 opts = append(opts, google.WithHTTPClient(httpClient))
5361071 }
@@ -542,7 +1077,7 @@ func (c *coordinator) buildGoogleProvider(baseURL, apiKey string, headers map[st
5421077
5431078func (c *coordinator) buildGoogleVertexProvider(headers map[string]string, options map[string]string) (fantasy.Provider, error) {
5441079 opts := []google.Option{}
545− if c.cfg.Options.Debug {
1080+ if c.cfg.Config().Options.Debug {
5461081 httpClient := log.NewHTTPClient()
5471082 opts = append(opts, google.WithHTTPClient(httpClient))
5481083 }
@@ -562,51 +1097,161 @@ func (c *coordinator) isAnthropicThinking(model config.SelectedModel) bool {
5621097 if model.Think {
5631098 return true
5641099 }
565−
566− if model.ProviderOptions == nil {
567− return false
568− }
569−
5701100 opts, err := anthropic.ParseOptions(model.ProviderOptions)
571− if err != nil {
572− return false
573− }
574− if opts.Thinking != nil {
575− return true
576− }
577− return false
1101+ return err == nil && opts.Thinking != nil
5781102}
5791103
580−func (c *coordinator) buildProvider(providerCfg config.ProviderConfig, model config.SelectedModel) (fantasy.Provider, error) {
581− headers := providerCfg.ExtraHeaders
1104+func (c *coordinator) buildProvider(providerCfg config.ProviderConfig, model config.SelectedModel, isSubAgent bool) (fantasy.Provider, error) {
1105+ headers := maps.Clone(providerCfg.ExtraHeaders)
1106+ if headers == nil {
1107+ headers = make(map[string]string)
1108+ }
5821109
5831110 // handle special headers for anthropic
5841111 if providerCfg.Type == anthropic.Name && c.isAnthropicThinking(model) {
585− headers["anthropic-beta"] = "interleaved-thinking-2025-05-14"
1112+ if v, ok := headers["anthropic-beta"]; ok {
1113+ headers["anthropic-beta"] = v + ",interleaved-thinking-2025-05-14"
1114+ } else {
1115+ headers["anthropic-beta"] = "interleaved-thinking-2025-05-14"
1116+ }
5861117 }
5871118
588− // TODO: make sure we have
5891119 apiKey, _ := c.cfg.Resolve(providerCfg.APIKey)
5901120 baseURL, _ := c.cfg.Resolve(providerCfg.BaseURL)
5911121
1122+ // Reuse a previously built client when nothing that affects it has
1123+ // changed, so the HTTP keep-alive pool survives across turns. The key
1124+ // is derived from the resolved inputs above (plus the debug flag); the
1125+ // per-provider adjustments inside the switch below are deterministic
1126+ // functions of these, so identical inputs always yield an identical
1127+ // client.
1128+ cacheKey := c.providerCacheKey(providerCfg, model, apiKey, baseURL, headers, isSubAgent)
1129+ if p, ok := c.providerClients.Get(cacheKey); ok {
1130+ return p, nil
1131+ }
1132+ provider, err := c.buildProviderUncached(providerCfg, model, apiKey, baseURL, headers, isSubAgent)
1133+ if err != nil {
1134+ return nil, err
1135+ }
1136+ c.providerClients.Set(cacheKey, provider)
1137+ return provider, nil
1138+}
1139+
1140+// providerCacheKey builds a stable key from every input buildProvider's
1141+// switch consumes, so any credential, endpoint, header, or option change
1142+// produces a distinct key (and thus a rebuilt client).
1143+func (c *coordinator) providerCacheKey(providerCfg config.ProviderConfig, model config.SelectedModel, apiKey, baseURL string, headers map[string]string, isSubAgent bool) string {
1144+ var b strings.Builder
1145+ b.WriteString(providerCfg.ID)
1146+ b.WriteByte(0)
1147+ b.WriteString(string(providerCfg.Type))
1148+ b.WriteByte(0)
1149+ // The opencode providers pick their client type from the model, so the
1150+ // model must participate in the key.
1151+ b.WriteString(model.Model)
1152+ b.WriteByte(0)
1153+ b.WriteString(apiKey)
1154+ b.WriteByte(0)
1155+ // Bedrock falls back to AWS_BEARER_TOKEN_BEDROCK when no apiKey is
1156+ // configured, and that token is baked into the built client. Fold it
1157+ // into the key so a rotated token rebuilds the client instead of
1158+ // reusing a stale one.
1159+ if apiKey == "" && providerCfg.Type == bedrock.Name {
1160+ b.WriteString(os.Getenv("AWS_BEARER_TOKEN_BEDROCK"))
1161+ }
1162+ b.WriteByte(0)
1163+ b.WriteString(baseURL)
1164+ b.WriteByte(0)
1165+ for _, k := range slices.Sorted(maps.Keys(headers)) {
1166+ b.WriteString(k)
1167+ b.WriteByte('=')
1168+ b.WriteString(headers[k])
1169+ b.WriteByte(1)
1170+ }
1171+ b.WriteByte(0)
1172+ if extra, err := json.Marshal(providerCfg.ExtraBody); err == nil {
1173+ b.Write(extra)
1174+ }
1175+ b.WriteByte(0)
1176+ if extra, err := json.Marshal(providerCfg.ExtraParams); err == nil {
1177+ b.Write(extra)
1178+ }
1179+ b.WriteByte(0)
1180+ if isSubAgent {
1181+ b.WriteByte('s')
1182+ }
1183+ if c.cfg.Config().Options.Debug {
1184+ b.WriteByte('d')
1185+ }
1186+ return b.String()
1187+}
1188+
1189+func (c *coordinator) buildProviderUncached(providerCfg config.ProviderConfig, model config.SelectedModel, apiKey, baseURL string, headers map[string]string, isSubAgent bool) (fantasy.Provider, error) {
1190+ switch providerCfg.ID {
1191+ case string(catwalk.InferenceProviderOpenCodeGo), string(catwalk.InferenceProviderOpenCodeZen):
1192+ if opencodeMessagesModels[model.Model] {
1193+ baseURL = strings.TrimSuffix(baseURL, "/v1")
1194+ return c.buildAnthropicProvider(baseURL, apiKey, headers, providerCfg.ID)
1195+ }
1196+ }
1197+
5921198 switch providerCfg.Type {
5931199 case openai.Name:
5941200 return c.buildOpenaiProvider(baseURL, apiKey, headers)
5951201 case anthropic.Name:
596− return c.buildAnthropicProvider(baseURL, apiKey, headers)
1202+ return c.buildAnthropicProvider(baseURL, apiKey, headers, providerCfg.ID)
5971203 case openrouter.Name:
5981204 return c.buildOpenrouterProvider(baseURL, apiKey, headers)
1205+ case vercel.Name:
1206+ return c.buildVercelProvider(baseURL, apiKey, headers)
5991207 case azure.Name:
6001208 return c.buildAzureProvider(baseURL, apiKey, headers, providerCfg.ExtraParams)
1209+ case bedrock.Name:
1210+ return c.buildBedrockProvider(apiKey, headers, providerCfg.ID)
6011211 case google.Name:
6021212 return c.buildGoogleProvider(baseURL, apiKey, headers)
603− case "vertexai":
1213+ case "google-vertex":
6041214 return c.buildGoogleVertexProvider(headers, providerCfg.ExtraParams)
605− case openaicompat.Name:
606− return c.buildOpenaiCompatProvider(baseURL, apiKey, headers)
1215+ case openaicompat.Name, hyper.Name:
1216+ switch providerCfg.ID {
1217+ case hyper.Name:
1218+ baseURL = hyper.BaseURL() + "/v1"
1219+ headers["x-crush-id"] = event.GetID()
1220+ case string(catwalk.InferenceProviderZAI):
1221+ if providerCfg.ExtraBody == nil {
1222+ providerCfg.ExtraBody = map[string]any{}
1223+ }
1224+ providerCfg.ExtraBody["tool_stream"] = true
1225+ }
1226+ return c.buildOpenaiCompatProvider(baseURL, apiKey, headers, providerCfg.ExtraBody, providerCfg.ID, isSubAgent)
6071227 default:
608− return nil, errors.New("provider type not supported")
1228+ // Known custom providers (litellm, ollama, omlx) are
1229+ // openai-compat under the hood.
1230+ if discover.IsKnownCustomProvider(string(providerCfg.Type)) {
1231+ return c.buildOpenaiCompatProvider(baseURL, apiKey, headers, providerCfg.ExtraBody, providerCfg.ID, isSubAgent)
1232+ }
1233+ return nil, fmt.Errorf("provider type not supported: %q", providerCfg.Type)
1234+ }
1235+}
1236+
1237+func isExactoSupported(modelID string) bool {
1238+ supportedModels := []string{
1239+ "moonshotai/kimi-k2-0905",
1240+ "deepseek/deepseek-v3.1-terminus",
1241+ "z-ai/glm-4.6",
1242+ "openai/gpt-oss-120b",
1243+ "qwen/qwen3-coder",
6091244 }
1245+ return slices.Contains(supportedModels, modelID)
1246+}
1247+
1248+// BeginAccepted reserves an accept slot for sessionID on the active
1249+// agent and returns the ownership handle. It is the fire-and-forget
1250+// dispatch path's only way to mark a run as accepted-but-not-yet-active
1251+// so a cancel arriving before the run registers in activeRequests is not
1252+// lost.
1253+func (c *coordinator) BeginAccepted(sessionID string) *AcceptedRun {
1254+ return c.currentAgent.BeginAccepted(sessionID)
6101255}
6111256
6121257func (c *coordinator) Cancel(sessionID string) {
@@ -635,21 +1280,40 @@ func (c *coordinator) Model() Model {
6351280
6361281func (c *coordinator) UpdateModels(ctx context.Context) error {
6371282 // build the models again so we make sure we get the latest config
638− large, small, err := c.buildAgentModels(ctx)
1283+ large, small, err := c.buildAgentModels(ctx, false)
6391284 if err != nil {
6401285 return err
6411286 }
6421287 c.currentAgent.SetModels(large, small)
6431288
644− agentCfg, ok := c.cfg.Agents[config.AgentCoder]
1289+ cfg := c.cfg.Config()
1290+ agentCfg, ok := cfg.Agents[config.AgentCoder]
6451291 if !ok {
646− return errors.New("coder agent not configured")
1292+ return errCoderAgentNotConfigured
6471293 }
6481294
649− tools, err := c.buildTools(ctx, agentCfg)
1295+ // Fast path: reuse cached tools when neither the config nor the MCP
1296+ // tool set has changed since the last build.
1297+ mcpGen := c.mcpToolsGen.Load()
1298+ c.toolsCacheMu.Lock()
1299+ if c.toolsCache != nil && c.toolsCacheCfg == cfg && c.toolsCacheMCP == mcpGen {
1300+ c.currentAgent.SetTools(c.toolsCache)
1301+ c.toolsCacheMu.Unlock()
1302+ return nil
1303+ }
1304+ c.toolsCacheMu.Unlock()
1305+
1306+ tools, err := c.buildTools(ctx, agentCfg, false)
6501307 if err != nil {
6511308 return err
6521309 }
1310+
1311+ c.toolsCacheMu.Lock()
1312+ c.toolsCache = tools
1313+ c.toolsCacheCfg = cfg
1314+ c.toolsCacheMCP = mcpGen
1315+ c.toolsCacheMu.Unlock()
1316+
6531317 c.currentAgent.SetTools(tools)
6541318 return nil
6551319}
@@ -658,10 +1322,340 @@ func (c *coordinator) QueuedPrompts(sessionID string) int {
6581322 return c.currentAgent.QueuedPrompts(sessionID)
6591323}
6601324
1325+func (c *coordinator) QueuedPromptsList(sessionID string) []string {
1326+ return c.currentAgent.QueuedPromptsList(sessionID)
1327+}
1328+
6611329func (c *coordinator) Summarize(ctx context.Context, sessionID string) error {
662− providerCfg, ok := c.cfg.Providers.Get(c.currentAgent.Model().ModelCfg.Provider)
1330+ providerCfg, ok := c.cfg.Config().Providers.Get(c.currentAgent.Model().ModelCfg.Provider)
6631331 if !ok {
664− return errors.New("model provider not configured")
1332+ return errModelProviderNotConfigured
1333+ }
1334+
1335+ if err := c.refreshTokenIfExpired(ctx, providerCfg); err != nil {
1336+ slog.Error("Failed to refresh OAuth2 token before summarize. Proceeding with existing token.", "error", err)
6651337 }
666− return c.currentAgent.Summarize(ctx, sessionID, getProviderOptions(c.currentAgent.Model(), providerCfg.Type))
1338+
1339+ summarize := func() error {
1340+ return c.currentAgent.Summarize(ctx, sessionID, getProviderOptions(c.currentAgent.Model(), providerCfg))
1341+ }
1342+
1343+ return c.runWithUnauthorizedRetry(ctx, providerCfg, summarize)
1344+}
1345+
1346+// GenerateTitle generates a session title using the current agent.
1347+func (c *coordinator) GenerateTitle(ctx context.Context, sessionID, prompt string) {
1348+ if c.currentAgent == nil {
1349+ return
1350+ }
1351+ c.currentAgent.GenerateTitle(ctx, sessionID, prompt)
1352+}
1353+
1354+// refreshTokenIfExpired proactively refreshes the OAuth token if it has expired.
1355+func (c *coordinator) refreshTokenIfExpired(ctx context.Context, providerCfg config.ProviderConfig) error {
1356+ if providerCfg.OAuthToken == nil || !providerCfg.OAuthToken.IsExpired() {
1357+ return nil
1358+ }
1359+ slog.Debug("Token needs to be refreshed", "provider", providerCfg.ID)
1360+ return c.refreshOAuth2Token(ctx, providerCfg)
1361+}
1362+
1363+// runWithUnauthorizedRetry executes fn. If fn returns a 401 error, it
1364+// attempts to refresh credentials and re-runs fn once. Returns the
1365+// final error: from the retry if a retry was attempted, otherwise from
1366+// the original run. Callers that need to notify the user on persistent
1367+// failure should check isUnauthorized on the returned error.
1368+func (c *coordinator) runWithUnauthorizedRetry(ctx context.Context, providerCfg config.ProviderConfig, fn func() error) error {
1369+ err := fn()
1370+ if err != nil && c.isUnauthorized(err) {
1371+ if retryErr := c.retryAfterUnauthorized(ctx, providerCfg); retryErr == nil {
1372+ return fn()
1373+ }
1374+ }
1375+ return err
1376+}
1377+
1378+// retryAfterUnauthorized attempts to refresh credentials after receiving a 401
1379+// and returns nil if retry should be attempted.
1380+func (c *coordinator) retryAfterUnauthorized(ctx context.Context, providerCfg config.ProviderConfig) error {
1381+ switch {
1382+ case providerCfg.OAuthToken != nil:
1383+ slog.Debug("Received 401. Refreshing token and retrying", "provider", providerCfg.ID)
1384+ return c.refreshOAuth2Token(ctx, providerCfg)
1385+ case strings.Contains(providerCfg.APIKeyTemplate, "$"):
1386+ slog.Debug("Received 401. Refreshing API Key template and retrying", "provider", providerCfg.ID)
1387+ return c.refreshApiKeyTemplate(ctx, providerCfg)
1388+ default:
1389+ return nil
1390+ }
1391+}
1392+
1393+func (c *coordinator) isUnauthorized(err error) bool {
1394+ var providerErr *fantasy.ProviderError
1395+ return errors.As(err, &providerErr) && providerErr.StatusCode == http.StatusUnauthorized
1396+}
1397+
1398+func (c *coordinator) refreshOAuth2Token(ctx context.Context, providerCfg config.ProviderConfig) error {
1399+ if err := c.cfg.RefreshOAuthToken(ctx, config.ScopeGlobal, providerCfg.ID); err != nil {
1400+ slog.Error("Failed to refresh OAuth token after 401 error", "provider", providerCfg.ID, "error", err)
1401+ return err
1402+ }
1403+ if err := c.UpdateModels(ctx); err != nil {
1404+ return err
1405+ }
1406+ return nil
1407+}
1408+
1409+func (c *coordinator) refreshApiKeyTemplate(ctx context.Context, providerCfg config.ProviderConfig) error {
1410+ newAPIKey, err := c.cfg.Resolve(providerCfg.APIKeyTemplate)
1411+ if err != nil {
1412+ slog.Error("Failed to re-resolve API key after 401 error", "provider", providerCfg.ID, "error", err)
1413+ return err
1414+ }
1415+
1416+ providerCfg.APIKey = newAPIKey
1417+ c.cfg.Config().Providers.Set(providerCfg.ID, providerCfg)
1418+
1419+ if err := c.UpdateModels(ctx); err != nil {
1420+ return err
1421+ }
1422+ return nil
1423+}
1424+
1425+// subAgentParams holds the parameters for running a sub-agent.
1426+type subAgentParams struct {
1427+ Agent SessionAgent
1428+ SessionID string
1429+ AgentMessageID string
1430+ ToolCallID string
1431+ Prompt string
1432+ SessionTitle string
1433+ // SessionSetup is an optional callback invoked after session creation
1434+ // but before agent execution, for custom session configuration.
1435+ SessionSetup func(sessionID string)
1436+}
1437+
1438+// runSubAgent runs a sub-agent and handles session management and cost accumulation.
1439+// It creates a sub-session, runs the agent with the given prompt, and propagates
1440+// the cost to the parent session.
1441+func (c *coordinator) runSubAgent(ctx context.Context, params subAgentParams) (fantasy.ToolResponse, error) {
1442+ // Create sub-session
1443+ agentToolSessionID := c.sessions.CreateAgentToolSessionID(params.AgentMessageID, params.ToolCallID)
1444+ session, err := c.sessions.CreateTaskSession(ctx, agentToolSessionID, params.SessionID, params.SessionTitle)
1445+ if err != nil {
1446+ return fantasy.ToolResponse{}, fmt.Errorf("create session: %w", err)
1447+ }
1448+
1449+ // Call session setup function if provided
1450+ if params.SessionSetup != nil {
1451+ params.SessionSetup(session.ID)
1452+ }
1453+
1454+ // Get model configuration
1455+ model := params.Agent.Model()
1456+ maxTokens := model.CatwalkCfg.DefaultMaxTokens
1457+ if model.ModelCfg.MaxTokens != 0 {
1458+ maxTokens = model.ModelCfg.MaxTokens
1459+ }
1460+
1461+ providerCfg, ok := c.cfg.Config().Providers.Get(model.ModelCfg.Provider)
1462+ if !ok {
1463+ return fantasy.ToolResponse{}, errModelProviderNotConfigured
1464+ }
1465+
1466+ // Run the agent
1467+ run := func() (*fantasy.AgentResult, error) {
1468+ return params.Agent.Run(ctx, SessionAgentCall{
1469+ SessionID: session.ID,
1470+ Prompt: params.Prompt,
1471+ MaxOutputTokens: maxTokens,
1472+ ProviderOptions: getProviderOptions(model, providerCfg),
1473+ Temperature: model.ModelCfg.Temperature,
1474+ TopP: model.ModelCfg.TopP,
1475+ TopK: model.ModelCfg.TopK,
1476+ FrequencyPenalty: model.ModelCfg.FrequencyPenalty,
1477+ PresencePenalty: model.ModelCfg.PresencePenalty,
1478+ NonInteractive: true,
1479+ })
1480+ }
1481+ var result *fantasy.AgentResult
1482+ err = c.runWithUnauthorizedRetry(ctx, providerCfg, func() error {
1483+ var runErr error
1484+ result, runErr = run()
1485+ return runErr
1486+ })
1487+ // Notify only if still unauthorized after retry.
1488+ if err != nil && c.isUnauthorized(err) && c.notify != nil && model.ModelCfg.Provider == hyper.Name {
1489+ c.notify.Publish(pubsub.CreatedEvent, notify.Notification{
1490+ Type: notify.TypeReAuthenticate,
1491+ ProviderID: model.ModelCfg.Provider,
1492+ })
1493+ }
1494+ if err != nil {
1495+ return fantasy.NewTextErrorResponse(fmt.Sprintf("Failed to generate response: %s", err)), nil
1496+ }
1497+
1498+ // Update parent session cost on a best-effort basis. A failure here must
1499+ // not discard the sub-agent output that was already produced.
1500+ if err := c.updateParentSessionCost(ctx, session.ID, params.SessionID); err != nil {
1501+ slog.Warn(
1502+ "Failed to update parent session cost",
1503+ "child_session", session.ID,
1504+ "parent_session", params.SessionID,
1505+ "error", err,
1506+ )
1507+ }
1508+
1509+ output := subAgentOutput(result)
1510+ if output == "" {
1511+ return fantasy.NewTextErrorResponse("Sub-agent completed but produced no text output."), nil
1512+ }
1513+ return fantasy.NewTextResponse(output), nil
1514+}
1515+
1516+func subAgentOutput(result *fantasy.AgentResult) string {
1517+ if result == nil {
1518+ return ""
1519+ }
1520+ return result.Response.Content.Text()
1521+}
1522+
1523+// updateParentSessionCost accumulates the cost from a child session to its parent session.
1524+func (c *coordinator) updateParentSessionCost(ctx context.Context, childSessionID, parentSessionID string) error {
1525+ childSession, err := c.sessions.Get(ctx, childSessionID)
1526+ if err != nil {
1527+ return fmt.Errorf("get child session: %w", err)
1528+ }
1529+
1530+ parentSession, err := c.sessions.Get(ctx, parentSessionID)
1531+ if err != nil {
1532+ return fmt.Errorf("get parent session: %w", err)
1533+ }
1534+
1535+ parentSession.Cost += childSession.Cost
1536+
1537+ if _, err := c.sessions.Save(ctx, parentSession); err != nil {
1538+ return fmt.Errorf("save parent session: %w", err)
1539+ }
1540+
1541+ return nil
1542+}
1543+
1544+// discoverSkills is a thin fallback wrapper used only when no
1545+// skills.Manager has been threaded through to the coordinator. All
1546+// production call sites (backend.CreateWorkspace, setupLocalWorkspace)
1547+// run discovery in advance and pass the results via the manager;
1548+// reaching this path means a caller bypassed both. It deliberately does
1549+// NOT publish to the package-level broker — there are no subscribers in
1550+// that case, so doing so would be misleading without delivering the
1551+// snapshot anywhere useful.
1552+func discoverSkills(cfg *config.ConfigStore) (allSkills, activeSkills []*skills.Skill) {
1553+ opts := cfg.Config().Options
1554+ var paths, disabled []string
1555+ if opts != nil {
1556+ paths = opts.SkillsPaths
1557+ disabled = opts.DisabledSkills
1558+ }
1559+ var resolver func(string) (string, error)
1560+ if r := cfg.Resolver(); r != nil {
1561+ resolver = r.ResolveValue
1562+ }
1563+ allSkills, activeSkills, states := skills.DiscoverFromConfig(skills.DiscoveryConfig{
1564+ SkillsPaths: paths,
1565+ DisabledSkills: disabled,
1566+ Resolver: resolver,
1567+ })
1568+ logDiscoveryStats(states, paths, allSkills, activeSkills, disabled)
1569+ return allSkills, activeSkills
1570+}
1571+
1572+// logTurnSkillUsage emits a per-turn diagnostic line showing which skills
1573+// (if any) were loaded during this turn and which looked relevant based on
1574+// a cheap keyword match against the user prompt. The goal is to surface
1575+// "should-have-loaded but didn't" situations for later analysis.
1576+//
1577+// Logged at Info level under component=skills; heavy fields are elided when
1578+// there is nothing interesting to report.
1579+func logTurnSkillUsage(
1580+ sessionID string,
1581+ prompt string,
1582+ activeSkills []*skills.Skill,
1583+ tracker *skills.Tracker,
1584+ before []string,
1585+) {
1586+ if tracker == nil || len(activeSkills) == 0 {
1587+ return
1588+ }
1589+
1590+ after := tracker.LoadedNames()
1591+
1592+ beforeSet := make(map[string]bool, len(before))
1593+ for _, n := range before {
1594+ beforeSet[n] = true
1595+ }
1596+ var loadedThisTurn []string
1597+ for _, n := range after {
1598+ if !beforeSet[n] {
1599+ loadedThisTurn = append(loadedThisTurn, n)
1600+ }
1601+ }
1602+
1603+ slog.Info(
1604+ "Skill turn summary",
1605+ "component", "skills",
1606+ "session_id", sessionID,
1607+ "prompt_len", len(prompt),
1608+ "active_total", len(activeSkills),
1609+ "loaded_total", len(after),
1610+ "loaded_this_turn", loadedThisTurn,
1611+ )
1612+}
1613+
1614+// logDiscoveryStats emits a single structured log line summarising skill
1615+// discovery for the current session. It is intentionally low-volume: one
1616+// line per session start. Builtin vs user counts are derived from the
1617+// SkillState.Path — builtin states use the "builtin/" embed prefix.
1618+func logDiscoveryStats(
1619+ states []*skills.SkillState,
1620+ userPaths []string,
1621+ allSkills, activeSkills []*skills.Skill,
1622+ disabled []string,
1623+) {
1624+ var builtinOK, builtinErr, userOK, userErr int
1625+ for _, s := range states {
1626+ isBuiltin := strings.HasPrefix(s.Path, "builtin/")
1627+ switch {
1628+ case isBuiltin && s.State == skills.StateNormal:
1629+ builtinOK++
1630+ case isBuiltin && s.State == skills.StateError:
1631+ builtinErr++
1632+ case !isBuiltin && s.State == skills.StateNormal:
1633+ userOK++
1634+ case !isBuiltin && s.State == skills.StateError:
1635+ userErr++
1636+ }
1637+ }
1638+
1639+ activeNames := make([]string, 0, len(activeSkills))
1640+ for _, s := range activeSkills {
1641+ activeNames = append(activeNames, s.Name)
1642+ }
1643+
1644+ xml := skills.ToPromptXML(activeSkills)
1645+
1646+ slog.Info(
1647+ "Skill discovery complete",
1648+ "component", "skills",
1649+ "builtin_ok", builtinOK,
1650+ "builtin_errors", builtinErr,
1651+ "user_ok", userOK,
1652+ "user_errors", userErr,
1653+ "user_paths", len(userPaths),
1654+ "deduped_total", len(allSkills),
1655+ "active", len(activeSkills),
1656+ "disabled", len(disabled),
1657+ "prompt_bytes", len(xml),
1658+ "prompt_tok_est", skills.ApproxTokenCount(xml),
1659+ "active_names", activeNames,
1660+ )
6671661}
internal/agent/coordinator_test.gonew file+554
@@ -0,0 +1,554 @@
1+package agent
2+
3+import (
4+ "context"
5+ "errors"
6+ "testing"
7+
8+ "charm.land/catwalk/pkg/catwalk"
9+ "charm.land/fantasy"
10+ "charm.land/fantasy/providers/anthropic"
11+ "charm.land/fantasy/providers/bedrock"
12+ "charm.land/fantasy/providers/openaicompat"
13+ "github.com/charmbracelet/crush/internal/config"
14+ "github.com/stretchr/testify/assert"
15+ "github.com/stretchr/testify/require"
16+)
17+
18+// mockSessionAgent is a minimal mock for the SessionAgent interface.
19+type mockSessionAgent struct {
20+ model Model
21+ runFunc func(ctx context.Context, call SessionAgentCall) (*fantasy.AgentResult, error)
22+ cancelled []string
23+}
24+
25+func (m *mockSessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy.AgentResult, error) {
26+ return m.runFunc(ctx, call)
27+}
28+
29+func (m *mockSessionAgent) BeginAccepted(sessionID string) *AcceptedRun {
30+ return &AcceptedRun{sessionID: sessionID}
31+}
32+
33+func (m *mockSessionAgent) Model() Model { return m.model }
34+func (m *mockSessionAgent) SetModels(large, small Model) {}
35+func (m *mockSessionAgent) SetTools(tools []fantasy.AgentTool) {}
36+func (m *mockSessionAgent) SetSystemPrompt(systemPrompt string) {}
37+func (m *mockSessionAgent) Cancel(sessionID string) {
38+ m.cancelled = append(m.cancelled, sessionID)
39+}
40+func (m *mockSessionAgent) CancelAll() {}
41+func (m *mockSessionAgent) IsSessionBusy(sessionID string) bool { return false }
42+func (m *mockSessionAgent) IsBusy() bool { return false }
43+func (m *mockSessionAgent) QueuedPrompts(sessionID string) int { return 0 }
44+func (m *mockSessionAgent) QueuedPromptsList(sessionID string) []string { return nil }
45+func (m *mockSessionAgent) ClearQueue(sessionID string) {}
46+func (m *mockSessionAgent) Summarize(context.Context, string, fantasy.ProviderOptions) error {
47+ return nil
48+}
49+func (m *mockSessionAgent) GenerateTitle(context.Context, string, string) {}
50+
51+// newTestCoordinator creates a minimal coordinator for unit testing runSubAgent.
52+func newTestCoordinator(t *testing.T, env fakeEnv, providerID string, providerCfg config.ProviderConfig) *coordinator {
53+ cfg, err := config.Init(env.workingDir, "", false)
54+ require.NoError(t, err)
55+ cfg.Config().Providers.Set(providerID, providerCfg)
56+ return &coordinator{
57+ cfg: cfg,
58+ sessions: env.sessions,
59+ messages: env.messages,
60+ }
61+}
62+
63+// newMockAgent creates a mockSessionAgent with the given provider and run function.
64+func newMockAgent(providerID string, maxTokens int64, runFunc func(context.Context, SessionAgentCall) (*fantasy.AgentResult, error)) *mockSessionAgent {
65+ return &mockSessionAgent{
66+ model: Model{
67+ CatwalkCfg: catwalk.Model{
68+ DefaultMaxTokens: maxTokens,
69+ },
70+ ModelCfg: config.SelectedModel{
71+ Provider: providerID,
72+ },
73+ },
74+ runFunc: runFunc,
75+ }
76+}
77+
78+// agentResultWithText creates a minimal AgentResult with the given text response.
79+func agentResultWithText(text string) *fantasy.AgentResult {
80+ return &fantasy.AgentResult{
81+ Response: fantasy.Response{
82+ Content: fantasy.ResponseContent{
83+ fantasy.TextContent{Text: text},
84+ },
85+ },
86+ }
87+}
88+
89+func TestRunSubAgent(t *testing.T) {
90+ const providerID = "test-provider"
91+ providerCfg := config.ProviderConfig{ID: providerID}
92+
93+ t.Run("happy path", func(t *testing.T) {
94+ env := testEnv(t)
95+ coord := newTestCoordinator(t, env, providerID, providerCfg)
96+
97+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
98+ require.NoError(t, err)
99+
100+ agent := newMockAgent(providerID, 4096, func(_ context.Context, call SessionAgentCall) (*fantasy.AgentResult, error) {
101+ assert.Equal(t, "do something", call.Prompt)
102+ assert.Equal(t, int64(4096), call.MaxOutputTokens)
103+ return agentResultWithText("done"), nil
104+ })
105+
106+ resp, err := coord.runSubAgent(t.Context(), subAgentParams{
107+ Agent: agent,
108+ SessionID: parentSession.ID,
109+ AgentMessageID: "msg-1",
110+ ToolCallID: "call-1",
111+ Prompt: "do something",
112+ SessionTitle: "Test Session",
113+ })
114+ require.NoError(t, err)
115+ assert.Equal(t, "done", resp.Content)
116+ assert.False(t, resp.IsError)
117+ })
118+
119+ t.Run("cost update failure preserves output", func(t *testing.T) {
120+ env := testEnv(t)
121+ coord := newTestCoordinator(t, env, providerID, providerCfg)
122+
123+ agent := newMockAgent(providerID, 4096, func(_ context.Context, _ SessionAgentCall) (*fantasy.AgentResult, error) {
124+ return agentResultWithText("output before cost failure"), nil
125+ })
126+
127+ resp, err := coord.runSubAgent(t.Context(), subAgentParams{
128+ Agent: agent,
129+ SessionID: "missing-parent-session",
130+ AgentMessageID: "msg-1",
131+ ToolCallID: "call-1",
132+ Prompt: "test",
133+ SessionTitle: "Test",
134+ })
135+ require.NoError(t, err)
136+ assert.False(t, resp.IsError)
137+ assert.Equal(t, "output before cost failure", resp.Content)
138+ })
139+
140+ t.Run("response with text returns it", func(t *testing.T) {
141+ env := testEnv(t)
142+ coord := newTestCoordinator(t, env, providerID, providerCfg)
143+
144+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
145+ require.NoError(t, err)
146+
147+ agent := newMockAgent(providerID, 4096, func(_ context.Context, _ SessionAgentCall) (*fantasy.AgentResult, error) {
148+ return agentResultWithText("the answer"), nil
149+ })
150+
151+ resp, err := coord.runSubAgent(t.Context(), subAgentParams{
152+ Agent: agent,
153+ SessionID: parentSession.ID,
154+ AgentMessageID: "msg-1",
155+ ToolCallID: "call-1",
156+ Prompt: "test",
157+ SessionTitle: "Test",
158+ })
159+ require.NoError(t, err)
160+ assert.False(t, resp.IsError)
161+ assert.Equal(t, "the answer", resp.Content)
162+ })
163+
164+ t.Run("nil result returns error response", func(t *testing.T) {
165+ env := testEnv(t)
166+ coord := newTestCoordinator(t, env, providerID, providerCfg)
167+
168+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
169+ require.NoError(t, err)
170+
171+ agent := newMockAgent(providerID, 4096, func(_ context.Context, _ SessionAgentCall) (*fantasy.AgentResult, error) {
172+ return nil, nil
173+ })
174+
175+ resp, err := coord.runSubAgent(t.Context(), subAgentParams{
176+ Agent: agent,
177+ SessionID: parentSession.ID,
178+ AgentMessageID: "msg-1",
179+ ToolCallID: "call-1",
180+ Prompt: "test",
181+ SessionTitle: "Test",
182+ })
183+ require.NoError(t, err)
184+ assert.True(t, resp.IsError)
185+ assert.Equal(t, "Sub-agent completed but produced no text output.", resp.Content)
186+ })
187+
188+ t.Run("empty result returns error response", func(t *testing.T) {
189+ env := testEnv(t)
190+ coord := newTestCoordinator(t, env, providerID, providerCfg)
191+
192+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
193+ require.NoError(t, err)
194+
195+ agent := newMockAgent(providerID, 4096, func(_ context.Context, _ SessionAgentCall) (*fantasy.AgentResult, error) {
196+ return &fantasy.AgentResult{}, nil
197+ })
198+
199+ resp, err := coord.runSubAgent(t.Context(), subAgentParams{
200+ Agent: agent,
201+ SessionID: parentSession.ID,
202+ AgentMessageID: "msg-1",
203+ ToolCallID: "call-1",
204+ Prompt: "test",
205+ SessionTitle: "Test",
206+ })
207+ require.NoError(t, err)
208+ assert.True(t, resp.IsError)
209+ assert.Equal(t, "Sub-agent completed but produced no text output.", resp.Content)
210+ })
211+
212+ t.Run("ModelCfg.MaxTokens overrides default", func(t *testing.T) {
213+ env := testEnv(t)
214+ coord := newTestCoordinator(t, env, providerID, providerCfg)
215+
216+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
217+ require.NoError(t, err)
218+
219+ agent := &mockSessionAgent{
220+ model: Model{
221+ CatwalkCfg: catwalk.Model{
222+ DefaultMaxTokens: 4096,
223+ },
224+ ModelCfg: config.SelectedModel{
225+ Provider: providerID,
226+ MaxTokens: 8192,
227+ },
228+ },
229+ runFunc: func(_ context.Context, call SessionAgentCall) (*fantasy.AgentResult, error) {
230+ assert.Equal(t, int64(8192), call.MaxOutputTokens)
231+ return agentResultWithText("ok"), nil
232+ },
233+ }
234+
235+ resp, err := coord.runSubAgent(t.Context(), subAgentParams{
236+ Agent: agent,
237+ SessionID: parentSession.ID,
238+ AgentMessageID: "msg-1",
239+ ToolCallID: "call-1",
240+ Prompt: "test",
241+ SessionTitle: "Test",
242+ })
243+ require.NoError(t, err)
244+ assert.Equal(t, "ok", resp.Content)
245+ })
246+
247+ t.Run("session creation failure with canceled context", func(t *testing.T) {
248+ env := testEnv(t)
249+ coord := newTestCoordinator(t, env, providerID, providerCfg)
250+
251+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
252+ require.NoError(t, err)
253+
254+ agent := newMockAgent(providerID, 4096, nil)
255+
256+ // Use a canceled context to trigger CreateTaskSession failure.
257+ ctx, cancel := context.WithCancel(t.Context())
258+ cancel()
259+
260+ _, err = coord.runSubAgent(ctx, subAgentParams{
261+ Agent: agent,
262+ SessionID: parentSession.ID,
263+ AgentMessageID: "msg-1",
264+ ToolCallID: "call-1",
265+ Prompt: "test",
266+ SessionTitle: "Test",
267+ })
268+ require.Error(t, err)
269+ })
270+
271+ t.Run("provider not configured", func(t *testing.T) {
272+ env := testEnv(t)
273+ coord := newTestCoordinator(t, env, providerID, providerCfg)
274+
275+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
276+ require.NoError(t, err)
277+
278+ // Agent references a provider that doesn't exist in config.
279+ agent := newMockAgent("unknown-provider", 4096, nil)
280+
281+ _, err = coord.runSubAgent(t.Context(), subAgentParams{
282+ Agent: agent,
283+ SessionID: parentSession.ID,
284+ AgentMessageID: "msg-1",
285+ ToolCallID: "call-1",
286+ Prompt: "test",
287+ SessionTitle: "Test",
288+ })
289+ require.Error(t, err)
290+ assert.Contains(t, err.Error(), "model provider not configured")
291+ })
292+
293+ t.Run("agent run error returns error response", func(t *testing.T) {
294+ env := testEnv(t)
295+ coord := newTestCoordinator(t, env, providerID, providerCfg)
296+
297+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
298+ require.NoError(t, err)
299+
300+ agent := newMockAgent(providerID, 4096, func(_ context.Context, _ SessionAgentCall) (*fantasy.AgentResult, error) {
301+ return nil, errors.New("provider request failed")
302+ })
303+
304+ resp, err := coord.runSubAgent(t.Context(), subAgentParams{
305+ Agent: agent,
306+ SessionID: parentSession.ID,
307+ AgentMessageID: "msg-1",
308+ ToolCallID: "call-1",
309+ Prompt: "test",
310+ SessionTitle: "Test",
311+ })
312+ // runSubAgent returns (errorResponse, nil) when agent.Run fails — not a Go error.
313+ require.NoError(t, err)
314+ assert.True(t, resp.IsError)
315+ assert.Equal(t, "Failed to generate response: provider request failed", resp.Content)
316+ })
317+
318+ t.Run("session setup callback is invoked", func(t *testing.T) {
319+ env := testEnv(t)
320+ coord := newTestCoordinator(t, env, providerID, providerCfg)
321+
322+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
323+ require.NoError(t, err)
324+
325+ var setupCalledWith string
326+ agent := newMockAgent(providerID, 4096, func(_ context.Context, _ SessionAgentCall) (*fantasy.AgentResult, error) {
327+ return agentResultWithText("ok"), nil
328+ })
329+
330+ _, err = coord.runSubAgent(t.Context(), subAgentParams{
331+ Agent: agent,
332+ SessionID: parentSession.ID,
333+ AgentMessageID: "msg-1",
334+ ToolCallID: "call-1",
335+ Prompt: "test",
336+ SessionTitle: "Test",
337+ SessionSetup: func(sessionID string) {
338+ setupCalledWith = sessionID
339+ },
340+ })
341+ require.NoError(t, err)
342+ assert.NotEmpty(t, setupCalledWith, "SessionSetup should have been called")
343+ })
344+
345+ t.Run("cost propagation to parent session", func(t *testing.T) {
346+ env := testEnv(t)
347+ coord := newTestCoordinator(t, env, providerID, providerCfg)
348+
349+ parentSession, err := env.sessions.Create(t.Context(), "Parent")
350+ require.NoError(t, err)
351+
352+ agent := newMockAgent(providerID, 4096, func(ctx context.Context, call SessionAgentCall) (*fantasy.AgentResult, error) {
353+ // Simulate the agent incurring cost by updating the child session.
354+ childSession, err := env.sessions.Get(ctx, call.SessionID)
355+ if err != nil {
356+ return nil, err
357+ }
358+ childSession.Cost = 0.05
359+ _, err = env.sessions.Save(ctx, childSession)
360+ if err != nil {
361+ return nil, err
362+ }
363+ return agentResultWithText("ok"), nil
364+ })
365+
366+ _, err = coord.runSubAgent(t.Context(), subAgentParams{
367+ Agent: agent,
368+ SessionID: parentSession.ID,
369+ AgentMessageID: "msg-1",
370+ ToolCallID: "call-1",
371+ Prompt: "test",
372+ SessionTitle: "Test",
373+ })
374+ require.NoError(t, err)
375+
376+ updated, err := env.sessions.Get(t.Context(), parentSession.ID)
377+ require.NoError(t, err)
378+ assert.InDelta(t, 0.05, updated.Cost, 1e-9)
379+ })
380+}
381+
382+func TestUpdateParentSessionCost(t *testing.T) {
383+ t.Run("accumulates cost correctly", func(t *testing.T) {
384+ env := testEnv(t)
385+ cfg, err := config.Init(env.workingDir, "", false)
386+ require.NoError(t, err)
387+ coord := &coordinator{cfg: cfg, sessions: env.sessions}
388+
389+ parent, err := env.sessions.Create(t.Context(), "Parent")
390+ require.NoError(t, err)
391+
392+ child, err := env.sessions.CreateTaskSession(t.Context(), "tool-1", parent.ID, "Child")
393+ require.NoError(t, err)
394+
395+ // Set child cost.
396+ child.Cost = 0.10
397+ _, err = env.sessions.Save(t.Context(), child)
398+ require.NoError(t, err)
399+
400+ err = coord.updateParentSessionCost(t.Context(), child.ID, parent.ID)
401+ require.NoError(t, err)
402+
403+ updated, err := env.sessions.Get(t.Context(), parent.ID)
404+ require.NoError(t, err)
405+ assert.InDelta(t, 0.10, updated.Cost, 1e-9)
406+ })
407+
408+ t.Run("accumulates multiple child costs", func(t *testing.T) {
409+ env := testEnv(t)
410+ cfg, err := config.Init(env.workingDir, "", false)
411+ require.NoError(t, err)
412+ coord := &coordinator{cfg: cfg, sessions: env.sessions}
413+
414+ parent, err := env.sessions.Create(t.Context(), "Parent")
415+ require.NoError(t, err)
416+
417+ child1, err := env.sessions.CreateTaskSession(t.Context(), "tool-1", parent.ID, "Child1")
418+ require.NoError(t, err)
419+ child1.Cost = 0.05
420+ _, err = env.sessions.Save(t.Context(), child1)
421+ require.NoError(t, err)
422+
423+ child2, err := env.sessions.CreateTaskSession(t.Context(), "tool-2", parent.ID, "Child2")
424+ require.NoError(t, err)
425+ child2.Cost = 0.03
426+ _, err = env.sessions.Save(t.Context(), child2)
427+ require.NoError(t, err)
428+
429+ err = coord.updateParentSessionCost(t.Context(), child1.ID, parent.ID)
430+ require.NoError(t, err)
431+ err = coord.updateParentSessionCost(t.Context(), child2.ID, parent.ID)
432+ require.NoError(t, err)
433+
434+ updated, err := env.sessions.Get(t.Context(), parent.ID)
435+ require.NoError(t, err)
436+ assert.InDelta(t, 0.08, updated.Cost, 1e-9)
437+ })
438+
439+ t.Run("child session not found", func(t *testing.T) {
440+ env := testEnv(t)
441+ cfg, err := config.Init(env.workingDir, "", false)
442+ require.NoError(t, err)
443+ coord := &coordinator{cfg: cfg, sessions: env.sessions}
444+
445+ parent, err := env.sessions.Create(t.Context(), "Parent")
446+ require.NoError(t, err)
447+
448+ err = coord.updateParentSessionCost(t.Context(), "non-existent", parent.ID)
449+ require.Error(t, err)
450+ assert.Contains(t, err.Error(), "get child session")
451+ })
452+
453+ t.Run("parent session not found", func(t *testing.T) {
454+ env := testEnv(t)
455+ cfg, err := config.Init(env.workingDir, "", false)
456+ require.NoError(t, err)
457+ coord := &coordinator{cfg: cfg, sessions: env.sessions}
458+
459+ parent, err := env.sessions.Create(t.Context(), "Parent")
460+ require.NoError(t, err)
461+ child, err := env.sessions.CreateTaskSession(t.Context(), "tool-1", parent.ID, "Child")
462+ require.NoError(t, err)
463+
464+ err = coord.updateParentSessionCost(t.Context(), child.ID, "non-existent")
465+ require.Error(t, err)
466+ assert.Contains(t, err.Error(), "get parent session")
467+ })
468+
469+ t.Run("zero cost handled correctly", func(t *testing.T) {
470+ env := testEnv(t)
471+ cfg, err := config.Init(env.workingDir, "", false)
472+ require.NoError(t, err)
473+ coord := &coordinator{cfg: cfg, sessions: env.sessions}
474+
475+ parent, err := env.sessions.Create(t.Context(), "Parent")
476+ require.NoError(t, err)
477+ child, err := env.sessions.CreateTaskSession(t.Context(), "tool-1", parent.ID, "Child")
478+ require.NoError(t, err)
479+
480+ err = coord.updateParentSessionCost(t.Context(), child.ID, parent.ID)
481+ require.NoError(t, err)
482+
483+ updated, err := env.sessions.Get(t.Context(), parent.ID)
484+ require.NoError(t, err)
485+ assert.InDelta(t, 0.0, updated.Cost, 1e-9)
486+ })
487+}
488+
489+func TestGetProviderOptionsReasoningEffort(t *testing.T) {
490+ // Bedrock is Fantasy's Anthropic under a different provider name; options
491+ // must land under anthropic.Name so the Anthropic language model picks them up.
492+ tests := []struct {
493+ name string
494+ providerType catwalk.Type
495+ }{
496+ {"anthropic honors reasoning_effort", catwalk.Type(anthropic.Name)},
497+ {"bedrock honors reasoning_effort", catwalk.Type(bedrock.Name)},
498+ }
499+ for _, tc := range tests {
500+ t.Run(tc.name, func(t *testing.T) {
501+ model := Model{
502+ CatwalkCfg: catwalk.Model{
503+ ID: "claude-opus-4-7",
504+ CanReason: true,
505+ ReasoningLevels: []string{"max"},
506+ },
507+ ModelCfg: config.SelectedModel{
508+ Provider: "test",
509+ ReasoningEffort: "max",
510+ },
511+ }
512+ providerCfg := config.ProviderConfig{ID: "test", Type: tc.providerType}
513+
514+ opts := getProviderOptions(model, providerCfg)
515+
516+ raw, ok := opts[anthropic.Name]
517+ require.True(t, ok, "options should be keyed under anthropic.Name for type %q", tc.providerType)
518+ parsed, ok := raw.(*anthropic.ProviderOptions)
519+ require.True(t, ok)
520+ require.NotNil(t, parsed.Effort)
521+ assert.Equal(t, anthropic.Effort("max"), *parsed.Effort)
522+ })
523+ }
524+}
525+
526+func TestGetProviderOptionsReasoningEffortFallback(t *testing.T) {
527+ model := Model{
528+ CatwalkCfg: catwalk.Model{
529+ ID: "glm-5.2",
530+ CanReason: true,
531+ ReasoningLevels: []string{"high", "max"},
532+ },
533+ ModelCfg: config.SelectedModel{
534+ Provider: "zai",
535+ },
536+ }
537+ providerCfg := config.ProviderConfig{
538+ ID: string(catwalk.InferenceProviderZAI),
539+ Type: openaicompat.Name,
540+ }
541+
542+ opts := getProviderOptions(model, providerCfg)
543+
544+ raw, ok := opts[openaicompat.Name]
545+ require.True(t, ok)
546+ parsed, ok := raw.(*openaicompat.ProviderOptions)
547+ require.True(t, ok)
548+ require.NotNil(t, parsed.ReasoningEffort)
549+ assert.Equal(t, "high", string(*parsed.ReasoningEffort))
550+
551+ thinking, ok := parsed.ExtraBody["thinking"].(map[string]any)
552+ require.True(t, ok)
553+ assert.Equal(t, "enabled", thinking["type"])
554+}
internal/agent/dispatch_cancel_test.gonew file+447
@@ -0,0 +1,447 @@
1+package agent
2+
3+import (
4+ "context"
5+ "errors"
6+ "sync/atomic"
7+ "testing"
8+ "time"
9+
10+ "charm.land/fantasy"
11+ "github.com/charmbracelet/crush/internal/agent/notify"
12+ "github.com/charmbracelet/crush/internal/message"
13+ "github.com/charmbracelet/crush/internal/pubsub"
14+ "github.com/stretchr/testify/assert"
15+ "github.com/stretchr/testify/require"
16+)
17+
18+// finishStreamModel is a minimal fantasy.LanguageModel that streams a
19+// single text part followed by a normal (FinishReasonStop) finish. It
20+// is enough to drive sessionAgent.Run through PrepareStep and a clean
21+// completion without a recorded provider cassette.
22+type finishStreamModel struct {
23+ text string
24+}
25+
26+func (m *finishStreamModel) Provider() string { return "fake" }
27+func (m *finishStreamModel) Model() string { return "fake-model" }
28+
29+func (m *finishStreamModel) Generate(ctx context.Context, call fantasy.Call) (*fantasy.Response, error) {
30+ return &fantasy.Response{
31+ Content: fantasy.ResponseContent{fantasy.TextContent{Text: m.text}},
32+ FinishReason: fantasy.FinishReasonStop,
33+ }, nil
34+}
35+
36+func (m *finishStreamModel) Stream(ctx context.Context, call fantasy.Call) (fantasy.StreamResponse, error) {
37+ text := m.text
38+ return func(yield func(fantasy.StreamPart) bool) {
39+ if !yield(fantasy.StreamPart{Type: fantasy.StreamPartTypeTextStart, ID: "1"}) {
40+ return
41+ }
42+ if !yield(fantasy.StreamPart{Type: fantasy.StreamPartTypeTextDelta, ID: "1", Delta: text}) {
43+ return
44+ }
45+ if !yield(fantasy.StreamPart{Type: fantasy.StreamPartTypeTextEnd, ID: "1"}) {
46+ return
47+ }
48+ yield(fantasy.StreamPart{Type: fantasy.StreamPartTypeFinish, FinishReason: fantasy.FinishReasonStop})
49+ }, nil
50+}
51+
52+func (m *finishStreamModel) GenerateObject(ctx context.Context, call fantasy.ObjectCall) (*fantasy.ObjectResponse, error) {
53+ return nil, errors.New("not implemented")
54+}
55+
56+func (m *finishStreamModel) StreamObject(ctx context.Context, call fantasy.ObjectCall) (fantasy.ObjectStreamResponse, error) {
57+ return nil, errors.New("not implemented")
58+}
59+
60+func newStreamTestAgent(t *testing.T) (*sessionAgent, fakeEnv) {
61+ t.Helper()
62+ env := testEnv(t)
63+ model := &finishStreamModel{text: "done"}
64+ sa := testSessionAgent(env, model, model, "system").(*sessionAgent)
65+ return sa, env
66+}
67+
68+// TestCancel_ActiveAndAcceptedFiresBothBranches covers the case where a
69+// session is actively running (activeRequests set) AND a follow-up has
70+// been accepted (acceptedRuns > 0). A single Cancel must fire both: it
71+// invokes the active cancel func and records a pending cancel for the
72+// accepted follow-up.
73+func TestCancel_ActiveAndAcceptedFiresBothBranches(t *testing.T) {
74+ t.Parallel()
75+ sa, _ := newCancelTestAgent(t)
76+
77+ const sid = "sid"
78+ var activeCanceled atomic.Bool
79+ sa.activeRequests.Set(sid, func() { activeCanceled.Store(true) })
80+
81+ accept := sa.BeginAccepted(sid)
82+ defer accept.Close()
83+
84+ sa.Cancel(sid)
85+
86+ require.True(t, activeCanceled.Load(), "active cancel func must fire")
87+ require.True(t, sa.hasPendingCancel(sid), "accepted follow-up must record a pending cancel")
88+}
89+
90+// TestRun_BusyWithPendingCancelTakesCancelOnEntry covers the busy-queue
91+// branch consulting pendingCancels: when the session is busy AND a
92+// cancel has been recorded for an accepted follow-up, Run must take the
93+// cancel-on-entry path (persist a canceled turn) instead of enqueueing
94+// the call behind the active run.
95+func TestRun_BusyWithPendingCancelTakesCancelOnEntry(t *testing.T) {
96+ t.Parallel()
97+ sa, env := newCancelTestAgent(t)
98+
99+ sess, err := env.sessions.Create(t.Context(), "session")
100+ require.NoError(t, err)
101+
102+ // Make the session look busy: an earlier prompt is active.
103+ sa.activeRequests.Set(sess.ID, func() {})
104+
105+ accept := sa.BeginAccepted(sess.ID)
106+ // A cancel arrives while this follow-up is accepted-but-not-active.
107+ sa.Cancel(sess.ID)
108+ require.True(t, sa.hasPendingCancel(sess.ID))
109+
110+ result, err := sa.Run(t.Context(), SessionAgentCall{
111+ SessionID: sess.ID,
112+ Prompt: "follow-up",
113+ Accepted: accept,
114+ })
115+ require.NoError(t, err)
116+ require.Nil(t, result)
117+
118+ // The follow-up was canceled on entry, not enqueued.
119+ require.Equal(t, 0, sa.QueuedPrompts(sess.ID),
120+ "cancel-on-entry must not enqueue the follow-up behind the active run")
121+ require.False(t, sa.hasPendingCancel(sess.ID), "pending cancel must be consumed")
122+ require.Equal(t, 0, sa.acceptedCount(sess.ID), "accept reservation must be released")
123+
124+ msgs, err := env.messages.List(t.Context(), sess.ID)
125+ require.NoError(t, err)
126+ require.Len(t, msgs, 2)
127+ assert.Equal(t, message.User, msgs[0].Role)
128+ assert.Equal(t, message.Assistant, msgs[1].Role)
129+ assert.Equal(t, message.FinishReasonCanceled, msgs[1].FinishReason())
130+}
131+
132+// TestRun_PrepareStepDrainSkipsQueuedOnPendingCancel verifies that the
133+// queue drain inside PrepareStep skips queued follow-up prompts when a
134+// cancel has been recorded for the session: the queued prompt must not
135+// be folded into the active turn as an extra user message.
136+func TestRun_PrepareStepDrainSkipsQueuedOnPendingCancel(t *testing.T) {
137+ t.Parallel()
138+ sa, env := newStreamTestAgent(t)
139+
140+ sess, err := env.sessions.Create(t.Context(), "session")
141+ require.NoError(t, err)
142+
143+ // A follow-up prompt sits queued for the session.
144+ sa.enqueueCall(SessionAgentCall{SessionID: sess.ID, Prompt: "queued-followup"})
145+ // A cancel was recorded for the session while it sat in the queue.
146+ sa.cancelMark.Set(sess.ID, 1)
147+
148+ result, err := sa.Run(t.Context(), SessionAgentCall{
149+ SessionID: sess.ID,
150+ Prompt: "main",
151+ })
152+ require.NoError(t, err)
153+ require.NotNil(t, result)
154+
155+ // Only the main prompt produced a user message; the queued
156+ // follow-up was skipped, not folded into the turn.
157+ msgs, err := env.messages.List(t.Context(), sess.ID)
158+ require.NoError(t, err)
159+ var userMsgs []message.Message
160+ for _, m := range msgs {
161+ if m.Role == message.User {
162+ userMsgs = append(userMsgs, m)
163+ }
164+ }
165+ require.Len(t, userMsgs, 1, "queued follow-up must not create a user message")
166+ assert.Equal(t, "main", userMsgs[0].Content().String())
167+
168+ // The queue was drained and the pending cancel consumed.
169+ require.Equal(t, 0, sa.QueuedPrompts(sess.ID))
170+ require.False(t, sa.hasPendingCancel(sess.ID))
171+}
172+
173+// TestRun_NormalCompletionClearsStalePendingCancel verifies that a Run
174+// which completes normally clears any stale pending-cancel entry for the
175+// session, so it cannot catch a future run.
176+func TestRun_NormalCompletionClearsStalePendingCancel(t *testing.T) {
177+ t.Parallel()
178+ sa, env := newStreamTestAgent(t)
179+
180+ sess, err := env.sessions.Create(t.Context(), "session")
181+ require.NoError(t, err)
182+
183+ // A stale cancel mark lingers (no queued work, no accepted run).
184+ sa.cancelMark.Set(sess.ID, 1)
185+
186+ result, err := sa.Run(t.Context(), SessionAgentCall{
187+ SessionID: sess.ID,
188+ Prompt: "main",
189+ })
190+ require.NoError(t, err)
191+ require.NotNil(t, result)
192+
193+ require.False(t, sa.hasPendingCancel(sess.ID),
194+ "normal completion must clear the stale pending cancel")
195+
196+ msgs, err := env.messages.List(t.Context(), sess.ID)
197+ require.NoError(t, err)
198+ require.Len(t, msgs, 2)
199+ assert.Equal(t, message.Assistant, msgs[1].Role)
200+ assert.Equal(t, message.FinishReasonEndTurn, msgs[1].FinishReason())
201+}
202+
203+// newCancelTestAgentWithRunComplete builds a DB-backed sessionAgent wired
204+// to a RunComplete broker so tests can observe the terminal event a
205+// RunID-bearing caller (e.g. `crush run`) blocks on.
206+func newCancelTestAgentWithRunComplete(t *testing.T) (*sessionAgent, fakeEnv, *pubsub.Broker[notify.RunComplete]) {
207+ t.Helper()
208+ env := testEnv(t)
209+ broker := pubsub.NewBroker[notify.RunComplete]()
210+ t.Cleanup(broker.Shutdown)
211+ sa := NewSessionAgent(SessionAgentOptions{
212+ Sessions: env.sessions,
213+ Messages: env.messages,
214+ RunComplete: broker,
215+ }).(*sessionAgent)
216+ return sa, env, broker
217+}
218+
219+// TestRun_CancelOnEntryPublishesRunComplete covers the first review
220+// finding: the cancel-on-entry path returned before the streaming defer
221+// that publishes RunComplete was installed. A caller that dispatches a
222+// run with a RunID and blocks on RunComplete (ignoring message events,
223+// like `crush run`) would hang on an immediately-canceled accepted run.
224+// The cancel-on-entry path must publish a terminal RunComplete carrying
225+// the originating RunID.
226+func TestRun_CancelOnEntryPublishesRunComplete(t *testing.T) {
227+ t.Parallel()
228+ sa, env, broker := newCancelTestAgentWithRunComplete(t)
229+
230+ sess, err := env.sessions.Create(t.Context(), "session")
231+ require.NoError(t, err)
232+
233+ ctx, cancel := context.WithCancel(t.Context())
234+ defer cancel()
235+ ch := broker.Subscribe(ctx)
236+
237+ accept := sa.BeginAccepted(sess.ID)
238+ // A cancel arrives in the accepted-but-not-yet-active window.
239+ sa.Cancel(sess.ID)
240+ require.True(t, sa.hasPendingCancel(sess.ID))
241+
242+ result, err := sa.Run(t.Context(), SessionAgentCall{
243+ SessionID: sess.ID,
244+ RunID: "run-cancel-on-entry",
245+ Prompt: "hello",
246+ Accepted: accept,
247+ })
248+ require.NoError(t, err)
249+ require.Nil(t, result)
250+
251+ select {
252+ case got := <-ch:
253+ assert.Equal(t, "run-cancel-on-entry", got.Payload.RunID,
254+ "RunComplete must echo the originating RunID")
255+ assert.Equal(t, sess.ID, got.Payload.SessionID)
256+ assert.True(t, got.Payload.Cancelled,
257+ "cancel-on-entry RunComplete must be marked cancelled")
258+ case <-time.After(2 * time.Second):
259+ t.Fatal("cancel-on-entry must publish RunComplete; a RunID caller would hang otherwise")
260+ }
261+}
262+
263+// TestCancel_TwoAcceptedBothObserveCancellation covers the second review
264+// finding: a single cancel with two accepted-not-yet-active prompts must
265+// cancel both. The cancel raises the session's high-water mark to the
266+// latest accept sequence, so every prompt accepted-but-not-yet-active at
267+// cancel time is covered and both take the cancel-on-entry path.
268+func TestCancel_TwoAcceptedBothObserveCancellation(t *testing.T) {
269+ t.Parallel()
270+ sa, env := newCancelTestAgent(t)
271+
272+ sess, err := env.sessions.Create(t.Context(), "session")
273+ require.NoError(t, err)
274+
275+ // Two prompts are accepted-but-not-yet-active for the same session.
276+ accept1 := sa.BeginAccepted(sess.ID)
277+ accept2 := sa.BeginAccepted(sess.ID)
278+ require.Equal(t, 2, sa.acceptedCount(sess.ID))
279+
280+ // A single cancel arrives before either becomes active.
281+ sa.Cancel(sess.ID)
282+ require.Equal(t, accept2.seq, sa.pendingCancelMark(sess.ID),
283+ "one cancel must mark every currently-accepted prompt as canceled")
284+ require.GreaterOrEqual(t, sa.pendingCancelMark(sess.ID), accept1.seq,
285+ "the mark must cover the earlier accepted prompt too")
286+
287+ // Both prompts enter Run; each must take cancel-on-entry, not run.
288+ r1, err := sa.Run(t.Context(), SessionAgentCall{
289+ SessionID: sess.ID,
290+ Prompt: "first",
291+ Accepted: accept1,
292+ })
293+ require.NoError(t, err)
294+ require.Nil(t, r1)
295+
296+ r2, err := sa.Run(t.Context(), SessionAgentCall{
297+ SessionID: sess.ID,
298+ Prompt: "second",
299+ Accepted: accept2,
300+ })
301+ require.NoError(t, err)
302+ require.Nil(t, r2)
303+
304+ require.False(t, sa.hasPendingCancel(sess.ID),
305+ "both reserved units must be consumed")
306+ require.Equal(t, 0, sa.acceptedCount(sess.ID),
307+ "both accept reservations must be released")
308+
309+ // Each canceled-on-entry turn writes a user + canceled assistant
310+ // message, and neither prompt was enqueued to run normally.
311+ require.Equal(t, 0, sa.QueuedPrompts(sess.ID),
312+ "neither accepted prompt may be enqueued to run normally")
313+ msgs, err := env.messages.List(t.Context(), sess.ID)
314+ require.NoError(t, err)
315+ require.Len(t, msgs, 4, "two canceled turns produce two user + two assistant messages")
316+ var canceled int
317+ for _, m := range msgs {
318+ if m.Role == message.Assistant {
319+ assert.Equal(t, message.FinishReasonCanceled, m.FinishReason())
320+ canceled++
321+ }
322+ }
323+ require.Equal(t, 2, canceled, "both turns must finish canceled")
324+}
325+
326+// TestRun_IdleCancelDoesNotPoisonNextPrompt covers the idle-cancel
327+// no-op guarantee end-to-end: an Escape on an idle session must not
328+// record a pending cancel that leaks into the next accepted prompt, which
329+// must run normally to completion.
330+func TestRun_IdleCancelDoesNotPoisonNextPrompt(t *testing.T) {
331+ t.Parallel()
332+ sa, env := newStreamTestAgent(t)
333+
334+ sess, err := env.sessions.Create(t.Context(), "session")
335+ require.NoError(t, err)
336+
337+ // Idle Escape: no accepted run, no active request.
338+ sa.Cancel(sess.ID)
339+ require.False(t, sa.hasPendingCancel(sess.ID),
340+ "idle cancel must not record a pending cancel")
341+
342+ // The next accepted prompt must run normally, not cancel on entry.
343+ accept := sa.BeginAccepted(sess.ID)
344+ result, err := sa.Run(t.Context(), SessionAgentCall{
345+ SessionID: sess.ID,
346+ Prompt: "next",
347+ Accepted: accept,
348+ })
349+ require.NoError(t, err)
350+ require.NotNil(t, result, "next prompt must run normally after an idle cancel")
351+
352+ msgs, err := env.messages.List(t.Context(), sess.ID)
353+ require.NoError(t, err)
354+ require.Len(t, msgs, 2)
355+ assert.Equal(t, message.User, msgs[0].Role)
356+ assert.Equal(t, message.Assistant, msgs[1].Role)
357+ assert.Equal(t, message.FinishReasonEndTurn, msgs[1].FinishReason(),
358+ "the prompt must finish normally, not canceled")
359+}
360+
361+// TestCancel_AcceptedAfterCancelIsNotPoisoned is the regression test for
362+// the reviewer's finding: a counted session-level pending cancel let a
363+// prompt accepted after the cancel enter Run first and consume a unit
364+// reserved for the earlier prompts. With a sequence high-water mark, a
365+// single cancel covers exactly the prompts accepted-but-not-yet-active at
366+// cancel time (A and B); a prompt accepted afterwards (C) gets a higher
367+// sequence and must run normally without consuming A or B's cancellation.
368+// C is run first to prove it neither cancels nor drains the mark, then A
369+// and B are run and must both cancel on entry.
370+func TestCancel_AcceptedAfterCancelIsNotPoisoned(t *testing.T) {
371+ t.Parallel()
372+ sa, env := newStreamTestAgent(t)
373+
374+ sess, err := env.sessions.Create(t.Context(), "session")
375+ require.NoError(t, err)
376+
377+ // A and B are accepted-but-not-yet-active.
378+ acceptA := sa.BeginAccepted(sess.ID)
379+ acceptB := sa.BeginAccepted(sess.ID)
380+
381+ // One cancel arrives covering both A and B.
382+ sa.Cancel(sess.ID)
383+ require.True(t, sa.hasPendingCancel(sess.ID))
384+ require.Equal(t, acceptB.seq, sa.pendingCancelMark(sess.ID),
385+ "the mark must cover every prompt accepted before the cancel")
386+
387+ // C is accepted AFTER the cancel; its sequence is above the mark.
388+ acceptC := sa.BeginAccepted(sess.ID)
389+ require.Greater(t, acceptC.seq, sa.pendingCancelMark(sess.ID),
390+ "a prompt accepted after the cancel must not be covered by the mark")
391+
392+ // Run C first. It must run normally to completion and must not
393+ // consume or clear the cancellation reserved for A and B.
394+ rc, err := sa.Run(t.Context(), SessionAgentCall{
395+ SessionID: sess.ID,
396+ Prompt: "C",
397+ Accepted: acceptC,
398+ })
399+ require.NoError(t, err)
400+ require.NotNil(t, rc, "C was accepted after the cancel and must run normally")
401+ require.True(t, sa.hasPendingCancel(sess.ID),
402+ "running C must not drain the cancellation reserved for A and B")
403+
404+ // Now A and B run. Both were accepted before the cancel and must
405+ // take the cancel-on-entry path.
406+ ra, err := sa.Run(t.Context(), SessionAgentCall{
407+ SessionID: sess.ID,
408+ Prompt: "A",
409+ Accepted: acceptA,
410+ })
411+ require.NoError(t, err)
412+ require.Nil(t, ra, "A must cancel on entry, not run")
413+
414+ rb, err := sa.Run(t.Context(), SessionAgentCall{
415+ SessionID: sess.ID,
416+ Prompt: "B",
417+ Accepted: acceptB,
418+ })
419+ require.NoError(t, err)
420+ require.Nil(t, rb, "B must cancel on entry, not run")
421+
422+ require.False(t, sa.hasPendingCancel(sess.ID),
423+ "the mark clears once all covered handles are resolved")
424+ require.Equal(t, 0, sa.acceptedCount(sess.ID))
425+ require.Equal(t, 0, sa.QueuedPrompts(sess.ID),
426+ "neither A nor B may be enqueued to run normally")
427+
428+ // C produced a normal turn; A and B each produced a canceled turn.
429+ msgs, err := env.messages.List(t.Context(), sess.ID)
430+ require.NoError(t, err)
431+ require.Len(t, msgs, 6, "C normal + A canceled + B canceled = 3 user + 3 assistant")
432+
433+ var normal, canceled int
434+ for _, m := range msgs {
435+ if m.Role != message.Assistant {
436+ continue
437+ }
438+ switch m.FinishReason() {
439+ case message.FinishReasonEndTurn:
440+ normal++
441+ case message.FinishReasonCanceled:
442+ canceled++
443+ }
444+ }
445+ require.Equal(t, 1, normal, "only C finished normally")
446+ require.Equal(t, 2, canceled, "both A and B finished canceled")
447+}
internal/agent/errors.go+1−8
@@ -1,9 +1,6 @@
11package agent
22
3−import (
4− "context"
5− "errors"
6−)
3+import "errors"
74
85var (
96 ErrRequestCancelled = errors.New("request canceled by user")
@@ -11,7 +8,3 @@ var (
118 ErrEmptyPrompt = errors.New("prompt is empty")
129 ErrSessionMissing = errors.New("session id is missing")
1310)
14−
15−func isCancelledErr(err error) bool {
16− return errors.Is(err, context.Canceled) || errors.Is(err, ErrRequestCancelled)
17−}
internal/agent/event.gonew file+51
@@ -0,0 +1,51 @@
1+package agent
2+
3+import (
4+ "time"
5+
6+ "charm.land/fantasy"
7+ "github.com/charmbracelet/crush/internal/event"
8+)
9+
10+func (a *sessionAgent) eventPromptSent(sessionID string) {
11+ event.PromptSent(
12+ a.eventCommon(sessionID, a.largeModel.Get())...,
13+ )
14+}
15+
16+func (a *sessionAgent) eventPromptResponded(sessionID string, duration time.Duration) {
17+ event.PromptResponded(
18+ append(
19+ a.eventCommon(sessionID, a.largeModel.Get()),
20+ "prompt duration pretty", duration.String(),
21+ "prompt duration in seconds", int64(duration.Seconds()),
22+ )...,
23+ )
24+}
25+
26+func (a *sessionAgent) eventTokensUsed(sessionID string, model Model, usage fantasy.Usage, cost float64) {
27+ event.TokensUsed(
28+ append(
29+ a.eventCommon(sessionID, model),
30+ "input tokens", usage.InputTokens,
31+ "output tokens", usage.OutputTokens,
32+ "cache read tokens", usage.CacheReadTokens,
33+ "cache creation tokens", usage.CacheCreationTokens,
34+ "total tokens", usage.InputTokens+usage.OutputTokens+usage.CacheReadTokens+usage.CacheCreationTokens,
35+ "cost", cost,
36+ )...,
37+ )
38+}
39+
40+func (a *sessionAgent) eventCommon(sessionID string, model Model) []any {
41+ m := model.ModelCfg
42+
43+ return []any{
44+ "session id", sessionID,
45+ "provider", m.Provider,
46+ "model", m.Model,
47+ "reasoning effort", m.ReasoningEffort,
48+ "thinking mode", m.Think,
49+ "yolo mode", a.isYolo,
50+ }
51+}
internal/agent/hooked_tool.gonew file+142
@@ -0,0 +1,142 @@
1+package agent
2+
3+import (
4+ "context"
5+ "encoding/json"
6+ "fmt"
7+ "log/slog"
8+
9+ "charm.land/fantasy"
10+ "github.com/charmbracelet/crush/internal/agent/tools"
11+ "github.com/charmbracelet/crush/internal/hooks"
12+ "github.com/charmbracelet/crush/internal/permission"
13+ "github.com/tidwall/sjson"
14+)
15+
16+// hookedTool wraps a fantasy.AgentTool to run PreToolUse hooks before
17+// delegating to the inner tool.
18+type hookedTool struct {
19+ inner fantasy.AgentTool
20+ runner *hooks.Runner
21+}
22+
23+func newHookedTool(inner fantasy.AgentTool, runner *hooks.Runner) *hookedTool {
24+ return &hookedTool{inner: inner, runner: runner}
25+}
26+
27+// wrapToolsWithHooks returns a tool slice with each entry wrapped in a
28+// hookedTool. Returns the original slice unchanged when runner is nil or
29+// when isSubAgent is true — sub-agents never fire hooks, the top-level
30+// invocation of the sub-agent tool itself is wrapped on the caller's side.
31+func wrapToolsWithHooks(tools []fantasy.AgentTool, runner *hooks.Runner, isSubAgent bool) []fantasy.AgentTool {
32+ if runner == nil || isSubAgent {
33+ return tools
34+ }
35+ out := make([]fantasy.AgentTool, len(tools))
36+ for i, tool := range tools {
37+ out[i] = newHookedTool(tool, runner)
38+ }
39+ return out
40+}
41+
42+func (h *hookedTool) Info() fantasy.ToolInfo {
43+ return h.inner.Info()
44+}
45+
46+func (h *hookedTool) ProviderOptions() fantasy.ProviderOptions {
47+ return h.inner.ProviderOptions()
48+}
49+
50+func (h *hookedTool) SetProviderOptions(opts fantasy.ProviderOptions) {
51+ h.inner.SetProviderOptions(opts)
52+}
53+
54+func (h *hookedTool) Run(ctx context.Context, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
55+ sessionID := tools.GetSessionFromContext(ctx)
56+ result, err := h.runner.Run(ctx, hooks.EventPreToolUse, sessionID, call.Name, call.Input)
57+ if err != nil {
58+ slog.Warn("Hook execution error, proceeding with tool call",
59+ "tool", call.Name, "error", err)
60+ }
61+
62+ if result.Decision == hooks.DecisionDeny || result.Halt {
63+ reason := fmt.Sprintf("Tool call blocked by hook. Reason: %s", result.Reason)
64+ if result.Halt {
65+ reason = fmt.Sprintf("Turn halted by hook. Reason: %s", result.Reason)
66+ }
67+ resp := fantasy.NewTextErrorResponse(reason)
68+ // Halt ends the whole turn; a plain deny only blocks this tool
69+ // call so the model can see the error and try something else.
70+ resp.StopTurn = result.Halt
71+ resp.Metadata = hookMetadataJSON(result)
72+ return resp, nil
73+ }
74+
75+ if result.UpdatedInput != "" {
76+ call.Input = result.UpdatedInput
77+ }
78+
79+ // An explicit allow from a hook pre-approves the permission prompt for
80+ // this tool call. Deny is already handled above; silence falls through
81+ // to the normal permission flow.
82+ if result.Decision == hooks.DecisionAllow {
83+ ctx = permission.WithHookApproval(ctx, call.ID)
84+ }
85+
86+ resp, err := h.inner.Run(ctx, call)
87+ if err != nil {
88+ return resp, err
89+ }
90+
91+ if result.Context != "" {
92+ if resp.Content != "" {
93+ resp.Content += "\n"
94+ }
95+ resp.Content += result.Context
96+ }
97+
98+ resp.Metadata = mergeHookMetadata(resp.Metadata, result)
99+ return resp, nil
100+}
101+
102+// buildHookMetadata creates a HookMetadata from an AggregateResult.
103+func buildHookMetadata(result hooks.AggregateResult) hooks.HookMetadata {
104+ return hooks.HookMetadata{
105+ HookCount: result.HookCount,
106+ Decision: result.Decision.String(),
107+ Halt: result.Halt,
108+ Reason: result.Reason,
109+ InputRewrite: result.UpdatedInput != "",
110+ Hooks: result.Hooks,
111+ }
112+}
113+
114+// hookMetadataJSON builds a JSON string containing only the hook metadata.
115+func hookMetadataJSON(result hooks.AggregateResult) string {
116+ meta := buildHookMetadata(result)
117+ data, err := json.Marshal(meta)
118+ if err != nil {
119+ return ""
120+ }
121+ return `{"hook":` + string(data) + `}`
122+}
123+
124+// mergeHookMetadata injects hook metadata into existing tool metadata.
125+func mergeHookMetadata(existing string, result hooks.AggregateResult) string {
126+ if result.HookCount == 0 {
127+ return existing
128+ }
129+ meta := buildHookMetadata(result)
130+ data, err := json.Marshal(meta)
131+ if err != nil {
132+ return existing
133+ }
134+ if existing == "" {
135+ existing = "{}"
136+ }
137+ merged, err := sjson.SetRaw(existing, "hook", string(data))
138+ if err != nil {
139+ return existing
140+ }
141+ return merged
142+}
internal/agent/hooked_tool_test.gonew file+147
@@ -0,0 +1,147 @@
1+package agent
2+
3+import (
4+ "context"
5+ "testing"
6+
7+ "charm.land/fantasy"
8+ "github.com/charmbracelet/crush/internal/config"
9+ "github.com/charmbracelet/crush/internal/hooks"
10+ "github.com/charmbracelet/crush/internal/permission"
11+ "github.com/stretchr/testify/require"
12+)
13+
14+// fakeTool records the context it was invoked with so tests can assert on
15+// values stamped onto it by the hookedTool decorator.
16+type fakeTool struct {
17+ name string
18+ called bool
19+ gotCtx context.Context
20+ resp fantasy.ToolResponse
21+}
22+
23+func (f *fakeTool) Info() fantasy.ToolInfo {
24+ return fantasy.ToolInfo{Name: f.name}
25+}
26+
27+func (f *fakeTool) Run(ctx context.Context, _ fantasy.ToolCall) (fantasy.ToolResponse, error) {
28+ f.called = true
29+ f.gotCtx = ctx
30+ return f.resp, nil
31+}
32+
33+func (f *fakeTool) ProviderOptions() fantasy.ProviderOptions { return nil }
34+func (f *fakeTool) SetProviderOptions(_ fantasy.ProviderOptions) {}
35+
36+// newRunner builds a hooks.Runner from a single HookConfig, running the
37+// config-loader path that compiles the matcher regex.
38+func newRunner(t *testing.T, cmd string) *hooks.Runner {
39+ t.Helper()
40+ cfg := &config.Config{
41+ Hooks: map[string][]config.HookConfig{
42+ hooks.EventPreToolUse: {{Command: cmd}},
43+ },
44+ }
45+ require.NoError(t, cfg.ValidateHooks())
46+ return hooks.NewRunner(cfg.Hooks[hooks.EventPreToolUse], t.TempDir(), t.TempDir())
47+}
48+
49+func TestHookedTool_AllowStampsHookApproval(t *testing.T) {
50+ t.Parallel()
51+
52+ inner := &fakeTool{name: "view", resp: fantasy.NewTextResponse("ok")}
53+ runner := newRunner(t, `echo '{"decision":"allow"}'`)
54+ tool := newHookedTool(inner, runner)
55+
56+ _, err := tool.Run(t.Context(), fantasy.ToolCall{ID: "call-1", Name: "view"})
57+ require.NoError(t, err)
58+ require.True(t, inner.called, "inner tool should have run")
59+
60+ // The inner tool's permission service can now treat call-1 as pre-approved.
61+ svc := permission.NewPermissionService(t.TempDir(), false, nil)
62+ granted, err := svc.Request(inner.gotCtx, permission.CreatePermissionRequest{
63+ SessionID: "s1",
64+ ToolCallID: "call-1",
65+ ToolName: "view",
66+ Action: "read",
67+ Path: t.TempDir(),
68+ })
69+ require.NoError(t, err)
70+ require.True(t, granted, "hook allow should bypass the permission prompt")
71+}
72+
73+func TestHookedTool_SilentDoesNotStampApproval(t *testing.T) {
74+ t.Parallel()
75+
76+ inner := &fakeTool{name: "view", resp: fantasy.NewTextResponse("ok")}
77+ runner := newRunner(t, `exit 0`) // no stdout, no decision
78+ tool := newHookedTool(inner, runner)
79+
80+ _, err := tool.Run(t.Context(), fantasy.ToolCall{ID: "call-2", Name: "view"})
81+ require.NoError(t, err)
82+ require.True(t, inner.called)
83+
84+ // With no hook opinion, a fresh permission request has nothing stamped
85+ // and must fall through to the normal flow. We verify by checking that
86+ // the context does not look pre-approved for this call ID: sending a
87+ // request that no subscriber resolves will block until cancelled.
88+ svc := permission.NewPermissionService(t.TempDir(), false, nil)
89+ ctx, cancel := context.WithCancel(inner.gotCtx)
90+ cancel()
91+ granted, err := svc.Request(ctx, permission.CreatePermissionRequest{
92+ SessionID: "s1",
93+ ToolCallID: "call-2",
94+ ToolName: "view",
95+ Action: "read",
96+ Path: t.TempDir(),
97+ })
98+ require.Error(t, err, "no approval stamped => request should reach the prompt path")
99+ require.False(t, granted)
100+}
101+
102+func TestHookedTool_DenySkipsInnerTool(t *testing.T) {
103+ t.Parallel()
104+
105+ inner := &fakeTool{name: "bash"}
106+ runner := newRunner(t, `echo "blocked" >&2; exit 2`)
107+ tool := newHookedTool(inner, runner)
108+
109+ resp, err := tool.Run(t.Context(), fantasy.ToolCall{ID: "call-3", Name: "bash"})
110+ require.NoError(t, err)
111+ require.False(t, inner.called, "denied call must not reach the inner tool")
112+ require.True(t, resp.IsError)
113+ require.Contains(t, resp.Content, "blocked")
114+}
115+
116+func TestWrapToolsWithHooks(t *testing.T) {
117+ t.Parallel()
118+
119+ runner := newRunner(t, `exit 0`)
120+ inputs := []fantasy.AgentTool{&fakeTool{name: "a"}, &fakeTool{name: "b"}}
121+
122+ t.Run("top-level agent wraps every tool", func(t *testing.T) {
123+ t.Parallel()
124+ out := wrapToolsWithHooks(inputs, runner, false)
125+ require.Len(t, out, len(inputs))
126+ for i, tool := range out {
127+ _, ok := tool.(*hookedTool)
128+ require.Truef(t, ok, "tool %d should be a *hookedTool", i)
129+ }
130+ })
131+
132+ t.Run("sub-agent skips the wrap", func(t *testing.T) {
133+ t.Parallel()
134+ out := wrapToolsWithHooks(inputs, runner, true)
135+ require.Equal(t, inputs, out, "sub-agent tools should be returned unwrapped")
136+ for _, tool := range out {
137+ _, isHooked := tool.(*hookedTool)
138+ require.False(t, isHooked, "sub-agent tool should not be wrapped")
139+ }
140+ })
141+
142+ t.Run("nil runner skips the wrap for both agent kinds", func(t *testing.T) {
143+ t.Parallel()
144+ require.Equal(t, inputs, wrapToolsWithHooks(inputs, nil, false))
145+ require.Equal(t, inputs, wrapToolsWithHooks(inputs, nil, true))
146+ })
147+}
internal/agent/hyper/provider.gonew file+105
@@ -0,0 +1,105 @@
1+// Package hyper provides a fantasy.Provider that proxies requests to Hyper.
2+package hyper
3+
4+import (
5+ "cmp"
6+ "context"
7+ _ "embed"
8+ "encoding/json"
9+ "fmt"
10+ "log/slog"
11+ "net/http"
12+ "os"
13+ "sync"
14+ "sync/atomic"
15+ "time"
16+
17+ "charm.land/catwalk/pkg/catwalk"
18+)
19+
20+//go:generate wget -O provider.json https://hyper.charm.land/v1/provider
21+
22+//go:embed provider.json
23+var embedded []byte
24+
25+// Embedded returns the embedded Hyper provider.
26+var Embedded = sync.OnceValue(func() catwalk.Provider {
27+ var provider catwalk.Provider
28+ if err := json.Unmarshal(embedded, &provider); err != nil {
29+ slog.Error("Could not use embedded provider data", "err", err)
30+ }
31+ if e := os.Getenv("HYPER_URL"); e != "" {
32+ provider.APIEndpoint = e + "/api/v1/fantasy"
33+ }
34+ return provider
35+})
36+
37+const (
38+ // Name is the default name of this meta provider.
39+ Name = "hyper"
40+ // DisplayName is the display name of Hyper.
41+ DisplayName = "Charm Hyper"
42+ // defaultBaseURL is the default proxy URL.
43+ defaultBaseURL = "https://hyper.charm.land"
44+)
45+
46+// BaseURL returns the base URL, which is either $HYPER_URL or the default.
47+var BaseURL = sync.OnceValue(func() string {
48+ return cmp.Or(os.Getenv("HYPER_URL"), defaultBaseURL)
49+})
50+
51+// lastKnownBalance stores the most recently extracted hypercredit balance
52+// from API response metadata. FetchCredits checks this before making a
53+// separate HTTP call.
54+var lastKnownBalance atomic.Int64
55+
56+// hasBalance tracks whether lastKnownBalance has been set.
57+var hasBalance atomic.Bool
58+
59+// SetBalance stores a credit balance extracted from API response metadata.
60+func SetBalance(balance int) {
61+ lastKnownBalance.Store(int64(balance))
62+ hasBalance.Store(true)
63+}
64+
65+// FetchCredits returns the remaining hypercredit balance. It first checks
66+// for a balance extracted from the most recent API response's usage
67+// metadata. If none is available, it falls back to calling the /v1/credits
68+// endpoint directly.
69+func FetchCredits(ctx context.Context, apiKey string) (int, error) {
70+ if hasBalance.Load() {
71+ hasBalance.Store(false)
72+ return int(lastKnownBalance.Load()), nil
73+ }
74+
75+ req, err := http.NewRequestWithContext(
76+ ctx,
77+ http.MethodGet,
78+ BaseURL()+"/v1/credits",
79+ nil,
80+ )
81+ if err != nil {
82+ return 0, fmt.Errorf("could not create request: %w", err)
83+ }
84+ req.Header.Set("Authorization", "Bearer "+apiKey)
85+
86+ client := &http.Client{Timeout: 10 * time.Second}
87+ resp, err := client.Do(req)
88+ if err != nil {
89+ return 0, fmt.Errorf("failed to make request: %w", err)
90+ }
91+ defer resp.Body.Close()
92+
93+ if resp.StatusCode != http.StatusOK {
94+ return 0, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
95+ }
96+
97+ var result struct {
98+ Balance int `json:"balance"`
99+ }
100+ if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
101+ return 0, fmt.Errorf("failed to decode response: %w", err)
102+ }
103+
104+ return result.Balance, nil
105+}
internal/agent/hyper/provider.jsonnew file+295
@@ -0,0 +1,295 @@
1+{
2+ "name": "Charm Hyper",
3+ "id": "hyper",
4+ "api_endpoint": "https://hyper.charm.land/api/v1/fantasy",
5+ "type": "hyper",
6+ "default_large_model_id": "qwen3.7-plus",
7+ "default_small_model_id": "deepseek-v4-flash",
8+ "models": [
9+ {
10+ "id": "deepseek-v4-flash",
11+ "name": "DeepSeek V4 Flash",
12+ "cost_per_1m_in": 0.14,
13+ "cost_per_1m_out": 0.28,
14+ "cost_per_1m_in_cached": 0.0028,
15+ "cost_per_1m_out_cached": 0,
16+ "context_window": 1000000,
17+ "default_max_tokens": 384000,
18+ "can_reason": true,
19+ "reasoning_levels": [
20+ "high",
21+ "xhigh"
22+ ],
23+ "default_reasoning_effort": "high",
24+ "supports_attachments": false
25+ },
26+ {
27+ "id": "deepseek-v4-pro",
28+ "name": "DeepSeek V4 Pro",
29+ "cost_per_1m_in": 0.435,
30+ "cost_per_1m_out": 0.87,
31+ "cost_per_1m_in_cached": 0.0036,
32+ "cost_per_1m_out_cached": 0,
33+ "context_window": 1000000,
34+ "default_max_tokens": 384000,
35+ "can_reason": true,
36+ "reasoning_levels": [
37+ "high",
38+ "xhigh"
39+ ],
40+ "default_reasoning_effort": "high",
41+ "supports_attachments": false
42+ },
43+ {
44+ "id": "gemma-4-26b-a4b-it",
45+ "name": "Gemma 4 26B A4B",
46+ "cost_per_1m_in": 0.126,
47+ "cost_per_1m_out": 0.42,
48+ "cost_per_1m_in_cached": 0.063,
49+ "cost_per_1m_out_cached": 0,
50+ "context_window": 256000,
51+ "default_max_tokens": 25600,
52+ "can_reason": true,
53+ "supports_attachments": false
54+ },
55+ {
56+ "id": "glm-5",
57+ "name": "GLM-5",
58+ "cost_per_1m_in": 0.86,
59+ "cost_per_1m_out": 2.784,
60+ "cost_per_1m_in_cached": 0.43,
61+ "cost_per_1m_out_cached": 0,
62+ "context_window": 202752,
63+ "default_max_tokens": 20275,
64+ "can_reason": true,
65+ "supports_attachments": false
66+ },
67+ {
68+ "id": "glm-5.1",
69+ "name": "GLM-5.1",
70+ "cost_per_1m_in": 1.3,
71+ "cost_per_1m_out": 4.3,
72+ "cost_per_1m_in_cached": 0.26,
73+ "cost_per_1m_out_cached": 0,
74+ "context_window": 202000,
75+ "default_max_tokens": 202000,
76+ "can_reason": true,
77+ "reasoning_levels": [
78+ "low",
79+ "medium",
80+ "high"
81+ ],
82+ "default_reasoning_effort": "medium",
83+ "supports_attachments": false
84+ },
85+ {
86+ "id": "glm-5.2",
87+ "name": "GLM-5.2",
88+ "cost_per_1m_in": 1.5,
89+ "cost_per_1m_out": 4.5,
90+ "cost_per_1m_in_cached": 0.3,
91+ "cost_per_1m_out_cached": 0,
92+ "context_window": 1000000,
93+ "default_max_tokens": 128000,
94+ "can_reason": true,
95+ "reasoning_levels": [
96+ "high",
97+ "xhigh"
98+ ],
99+ "default_reasoning_effort": "high",
100+ "supports_attachments": false
101+ },
102+ {
103+ "id": "gpt-oss-120b",
104+ "name": "gpt-oss-120b",
105+ "cost_per_1m_in": 0.168,
106+ "cost_per_1m_out": 0.562,
107+ "cost_per_1m_in_cached": 0.084,
108+ "cost_per_1m_out_cached": 0,
109+ "context_window": 131072,
110+ "default_max_tokens": 13107,
111+ "can_reason": true,
112+ "reasoning_levels": [
113+ "low",
114+ "medium",
115+ "high"
116+ ],
117+ "default_reasoning_effort": "medium",
118+ "supports_attachments": false
119+ },
120+ {
121+ "id": "kimi-k2.5",
122+ "name": "Kimi K2.5",
123+ "cost_per_1m_in": 0.51,
124+ "cost_per_1m_out": 2.67,
125+ "cost_per_1m_in_cached": 0.255,
126+ "cost_per_1m_out_cached": 0,
127+ "context_window": 262144,
128+ "default_max_tokens": 26214,
129+ "can_reason": true,
130+ "supports_attachments": false
131+ },
132+ {
133+ "id": "kimi-k2.6",
134+ "name": "Kimi K2.6",
135+ "cost_per_1m_in": 0.95,
136+ "cost_per_1m_out": 4,
137+ "cost_per_1m_in_cached": 0.16,
138+ "cost_per_1m_out_cached": 0,
139+ "context_window": 262000,
140+ "default_max_tokens": 262000,
141+ "can_reason": true,
142+ "reasoning_levels": [
143+ "low",
144+ "medium",
145+ "high"
146+ ],
147+ "default_reasoning_effort": "medium",
148+ "supports_attachments": true
149+ },
150+ {
151+ "id": "kimi-k2.7-code",
152+ "name": "Kimi K2.7 Code",
153+ "cost_per_1m_in": 0.95,
154+ "cost_per_1m_out": 4,
155+ "cost_per_1m_in_cached": 0.19,
156+ "cost_per_1m_out_cached": 0,
157+ "context_window": 256000,
158+ "default_max_tokens": 32768,
159+ "can_reason": true,
160+ "reasoning_levels": [
161+ "low",
162+ "medium",
163+ "high"
164+ ],
165+ "default_reasoning_effort": "medium",
166+ "supports_attachments": true
167+ },
168+ {
169+ "id": "llama-3.3-70b-instruct",
170+ "name": "Llama 3.3 70B Instruct",
171+ "cost_per_1m_in": 0.6066,
172+ "cost_per_1m_out": 1.0386,
173+ "cost_per_1m_in_cached": 0.3033,
174+ "cost_per_1m_out_cached": 0,
175+ "context_window": 128000,
176+ "default_max_tokens": 12800,
177+ "can_reason": true,
178+ "supports_attachments": false
179+ },
180+ {
181+ "id": "llama-4-maverick-17b-128e-instruct-fp8",
182+ "name": "Llama 4 Maverick 17B 128E Instruct FP8",
183+ "cost_per_1m_in": 0.274,
184+ "cost_per_1m_out": 0.894,
185+ "cost_per_1m_in_cached": 0.137,
186+ "cost_per_1m_out_cached": 0,
187+ "context_window": 430000,
188+ "default_max_tokens": 43000,
189+ "can_reason": true,
190+ "supports_attachments": false
191+ },
192+ {
193+ "id": "minimax-m2.7",
194+ "name": "MiniMax M2.7",
195+ "cost_per_1m_in": 0.3,
196+ "cost_per_1m_out": 1.2,
197+ "cost_per_1m_in_cached": 0.06,
198+ "cost_per_1m_out_cached": 0.375,
199+ "context_window": 204800,
200+ "default_max_tokens": 131000,
201+ "can_reason": true,
202+ "reasoning_levels": [
203+ "low",
204+ "medium",
205+ "high"
206+ ],
207+ "default_reasoning_effort": "medium",
208+ "supports_attachments": false
209+ },
210+ {
211+ "id": "qwen3.6-flash",
212+ "name": "Qwen3.6-Flash",
213+ "cost_per_1m_in": 1,
214+ "cost_per_1m_out": 4,
215+ "cost_per_1m_in_cached": 1.25,
216+ "cost_per_1m_out_cached": 0.1,
217+ "context_window": 1000000,
218+ "default_max_tokens": 64000,
219+ "can_reason": true,
220+ "supports_attachments": true
221+ },
222+ {
223+ "id": "qwen3.6-max",
224+ "name": "Qwen3.6-Max",
225+ "cost_per_1m_in": 2,
226+ "cost_per_1m_out": 12,
227+ "cost_per_1m_in_cached": 2.5,
228+ "cost_per_1m_out_cached": 0.2,
229+ "context_window": 256000,
230+ "default_max_tokens": 64000,
231+ "can_reason": true,
232+ "supports_attachments": false
233+ },
234+ {
235+ "id": "qwen3.6-plus",
236+ "name": "Qwen3.6-Plus",
237+ "cost_per_1m_in": 2,
238+ "cost_per_1m_out": 6,
239+ "cost_per_1m_in_cached": 2.5,
240+ "cost_per_1m_out_cached": 0.2,
241+ "context_window": 1000000,
242+ "default_max_tokens": 64000,
243+ "can_reason": true,
244+ "supports_attachments": true
245+ },
246+ {
247+ "id": "qwen3.7-max",
248+ "name": "Qwen3.7-Max",
249+ "cost_per_1m_in": 2.5,
250+ "cost_per_1m_out": 7.5,
251+ "cost_per_1m_in_cached": 3.125,
252+ "cost_per_1m_out_cached": 0.25,
253+ "context_window": 1000000,
254+ "default_max_tokens": 64000,
255+ "can_reason": true,
256+ "supports_attachments": false
257+ },
258+ {
259+ "id": "qwen3.7-plus",
260+ "name": "Qwen3.7-Plus",
261+ "cost_per_1m_in": 1.2,
262+ "cost_per_1m_out": 4.8,
263+ "cost_per_1m_in_cached": 1.5,
264+ "cost_per_1m_out_cached": 0.12,
265+ "context_window": 1000000,
266+ "default_max_tokens": 64000,
267+ "can_reason": true,
268+ "supports_attachments": true
269+ },
270+ {
271+ "id": "qwen3-coder-480b-a35b-instruct-int4-mixed-ar",
272+ "name": "Qwen3 Coder 480B A35B Instruct INT4 Mixed AR",
273+ "cost_per_1m_in": 0.557,
274+ "cost_per_1m_out": 2.545,
275+ "cost_per_1m_in_cached": 0.2785,
276+ "cost_per_1m_out_cached": 0,
277+ "context_window": 106000,
278+ "default_max_tokens": 10600,
279+ "can_reason": false,
280+ "supports_attachments": false
281+ },
282+ {
283+ "id": "qwen3-next-80b-a3b-instruct",
284+ "name": "Qwen3 Next 80B A3B Instruct",
285+ "cost_per_1m_in": 0.128,
286+ "cost_per_1m_out": 1.28,
287+ "cost_per_1m_in_cached": 0.064,
288+ "cost_per_1m_out_cached": 0,
289+ "context_window": 262144,
290+ "default_max_tokens": 26214,
291+ "can_reason": false,
292+ "supports_attachments": false
293+ }
294+ ]
295+}
internal/agent/loop_detection.gonew file+92
@@ -0,0 +1,92 @@
1+package agent
2+
3+import (
4+ "hash/fnv"
5+ "io"
6+
7+ "charm.land/fantasy"
8+)
9+
10+const (
11+ loopDetectionWindowSize = 10
12+ loopDetectionMaxRepeats = 5
13+)
14+
15+// hasRepeatedToolCalls checks whether the agent is stuck in a loop by looking
16+// at recent steps. It examines the last windowSize steps and returns true if
17+// any tool-call signature appears more than maxRepeats times.
18+func hasRepeatedToolCalls(steps []fantasy.StepResult, windowSize, maxRepeats int) bool {
19+ if len(steps) < windowSize {
20+ return false
21+ }
22+
23+ window := steps[len(steps)-windowSize:]
24+ counts := make(map[uint64]int, windowSize)
25+
26+ for _, step := range window {
27+ sig := getToolInteractionSignature(step.Content)
28+ if sig == 0 {
29+ continue
30+ }
31+ counts[sig]++
32+ if counts[sig] > maxRepeats {
33+ return true
34+ }
35+ }
36+
37+ return false
38+}
39+
40+// getToolInteractionSignature computes a hash signature for the tool
41+// interactions in a single step's content. It pairs tool calls with their
42+// results (matched by ToolCallID) and returns an FNV-1a hash. FNV is ~10x
43+// faster than SHA-256 and collision risk is negligible for loop detection
44+// over a 10-step window. If the step contains no tool calls, it returns 0.
45+func getToolInteractionSignature(content fantasy.ResponseContent) uint64 {
46+ toolCalls := content.ToolCalls()
47+ if len(toolCalls) == 0 {
48+ return 0
49+ }
50+
51+ // Index tool results by their ToolCallID for fast lookup.
52+ resultsByID := make(map[string]fantasy.ToolResultContent, len(toolCalls))
53+ for _, tr := range content.ToolResults() {
54+ resultsByID[tr.ToolCallID] = tr
55+ }
56+
57+ h := fnv.New64a()
58+ for _, tc := range toolCalls {
59+ output := ""
60+ if tr, ok := resultsByID[tc.ToolCallID]; ok {
61+ output = toolResultOutputString(tr.Result)
62+ }
63+ _, _ = io.WriteString(h, tc.ToolName)
64+ h.Write([]byte{0})
65+ _, _ = io.WriteString(h, tc.Input)
66+ h.Write([]byte{0})
67+ _, _ = io.WriteString(h, output)
68+ h.Write([]byte{0})
69+ }
70+ return h.Sum64()
71+}
72+
73+// toolResultOutputString converts a ToolResultOutputContent to a stable string
74+// representation for signature comparison.
75+func toolResultOutputString(result fantasy.ToolResultOutputContent) string {
76+ if result == nil {
77+ return ""
78+ }
79+ if text, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentText](result); ok {
80+ return text.Text
81+ }
82+ if errResult, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentError](result); ok {
83+ if errResult.Error != nil {
84+ return errResult.Error.Error()
85+ }
86+ return ""
87+ }
88+ if media, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentMedia](result); ok {
89+ return media.Data
90+ }
91+ return ""
92+}
internal/agent/loop_detection_test.gonew file+205
@@ -0,0 +1,205 @@
1+package agent
2+
3+import (
4+ "fmt"
5+ "testing"
6+
7+ "charm.land/fantasy"
8+)
9+
10+// makeStep creates a StepResult with the given tool calls and results in its Content.
11+func makeStep(calls []fantasy.ToolCallContent, results []fantasy.ToolResultContent) fantasy.StepResult {
12+ var content fantasy.ResponseContent
13+ for _, c := range calls {
14+ content = append(content, c)
15+ }
16+ for _, r := range results {
17+ content = append(content, r)
18+ }
19+ return fantasy.StepResult{
20+ Response: fantasy.Response{
21+ Content: content,
22+ },
23+ }
24+}
25+
26+// makeToolStep creates a step with a single tool call and matching text result.
27+func makeToolStep(name, input, output string) fantasy.StepResult {
28+ callID := fmt.Sprintf("call_%s_%s", name, input)
29+ return makeStep(
30+ []fantasy.ToolCallContent{
31+ {ToolCallID: callID, ToolName: name, Input: input},
32+ },
33+ []fantasy.ToolResultContent{
34+ {ToolCallID: callID, ToolName: name, Result: fantasy.ToolResultOutputContentText{Text: output}},
35+ },
36+ )
37+}
38+
39+// makeEmptyStep creates a step with no tool calls (e.g. a text-only response).
40+func makeEmptyStep() fantasy.StepResult {
41+ return fantasy.StepResult{
42+ Response: fantasy.Response{
43+ Content: fantasy.ResponseContent{
44+ fantasy.TextContent{Text: "thinking..."},
45+ },
46+ },
47+ }
48+}
49+
50+func TestHasRepeatedToolCalls(t *testing.T) {
51+ t.Run("no steps", func(t *testing.T) {
52+ result := hasRepeatedToolCalls(nil, 10, 5)
53+ if result {
54+ t.Error("expected false for empty steps")
55+ }
56+ })
57+
58+ t.Run("fewer steps than window", func(t *testing.T) {
59+ steps := make([]fantasy.StepResult, 5)
60+ for i := range steps {
61+ steps[i] = makeToolStep("read", `{"file":"a.go"}`, "content")
62+ }
63+ result := hasRepeatedToolCalls(steps, 10, 5)
64+ if result {
65+ t.Error("expected false when fewer steps than window size")
66+ }
67+ })
68+
69+ t.Run("all different signatures", func(t *testing.T) {
70+ steps := make([]fantasy.StepResult, 10)
71+ for i := range steps {
72+ steps[i] = makeToolStep("tool", fmt.Sprintf(`{"i":%d}`, i), fmt.Sprintf("result-%d", i))
73+ }
74+ result := hasRepeatedToolCalls(steps, 10, 5)
75+ if result {
76+ t.Error("expected false when all signatures are different")
77+ }
78+ })
79+
80+ t.Run("exact repeat at threshold not detected", func(t *testing.T) {
81+ // maxRepeats=5 means > 5 is needed, so exactly 5 should return false
82+ steps := make([]fantasy.StepResult, 10)
83+ for i := range 5 {
84+ steps[i] = makeToolStep("read", `{"file":"a.go"}`, "content")
85+ }
86+ for i := 5; i < 10; i++ {
87+ steps[i] = makeToolStep("tool", fmt.Sprintf(`{"i":%d}`, i), fmt.Sprintf("result-%d", i))
88+ }
89+ result := hasRepeatedToolCalls(steps, 10, 5)
90+ if result {
91+ t.Error("expected false when count equals maxRepeats (threshold is >)")
92+ }
93+ })
94+
95+ t.Run("loop detected", func(t *testing.T) {
96+ // 6 identical steps in a window of 10 with maxRepeats=5 → detected
97+ steps := make([]fantasy.StepResult, 10)
98+ for i := range 6 {
99+ steps[i] = makeToolStep("read", `{"file":"a.go"}`, "content")
100+ }
101+ for i := 6; i < 10; i++ {
102+ steps[i] = makeToolStep("tool", fmt.Sprintf(`{"i":%d}`, i), fmt.Sprintf("result-%d", i))
103+ }
104+ result := hasRepeatedToolCalls(steps, 10, 5)
105+ if !result {
106+ t.Error("expected true when same signature appears more than maxRepeats times")
107+ }
108+ })
109+
110+ t.Run("steps without tool calls are skipped", func(t *testing.T) {
111+ // Mix of tool steps and empty steps — empty ones should not affect counts
112+ steps := make([]fantasy.StepResult, 10)
113+ for i := range 4 {
114+ steps[i] = makeToolStep("read", `{"file":"a.go"}`, "content")
115+ }
116+ for i := 4; i < 8; i++ {
117+ steps[i] = makeEmptyStep()
118+ }
119+ for i := 8; i < 10; i++ {
120+ steps[i] = makeToolStep("write", `{"file":"b.go"}`, "ok")
121+ }
122+ result := hasRepeatedToolCalls(steps, 10, 5)
123+ if result {
124+ t.Error("expected false: only 4 repeated tool calls, empty steps should be skipped")
125+ }
126+ })
127+
128+ t.Run("multiple different patterns alternating", func(t *testing.T) {
129+ // Two patterns alternating: each appears 5 times — not above threshold
130+ steps := make([]fantasy.StepResult, 10)
131+ for i := range steps {
132+ if i%2 == 0 {
133+ steps[i] = makeToolStep("read", `{"file":"a.go"}`, "content-a")
134+ } else {
135+ steps[i] = makeToolStep("write", `{"file":"b.go"}`, "content-b")
136+ }
137+ }
138+ result := hasRepeatedToolCalls(steps, 10, 5)
139+ if result {
140+ t.Error("expected false: two patterns each appearing 5 times (not > 5)")
141+ }
142+ })
143+}
144+
145+func TestGetToolInteractionSignature(t *testing.T) {
146+ t.Run("empty content returns empty string", func(t *testing.T) {
147+ sig := getToolInteractionSignature(fantasy.ResponseContent{})
148+ if sig != 0 {
149+ t.Errorf("expected zero signature, got %d", sig)
150+ }
151+ })
152+
153+ t.Run("text only content returns zero signature", func(t *testing.T) {
154+ content := fantasy.ResponseContent{
155+ fantasy.TextContent{Text: "hello"},
156+ }
157+ sig := getToolInteractionSignature(content)
158+ if sig != 0 {
159+ t.Errorf("expected zero signature, got %d", sig)
160+ }
161+ })
162+
163+ t.Run("tool call with result produces signature", func(t *testing.T) {
164+ content := fantasy.ResponseContent{
165+ fantasy.ToolCallContent{ToolCallID: "1", ToolName: "read", Input: `{"file":"a.go"}`},
166+ fantasy.ToolResultContent{ToolCallID: "1", ToolName: "read", Result: fantasy.ToolResultOutputContentText{Text: "content"}},
167+ }
168+ sig := getToolInteractionSignature(content)
169+ if sig == 0 {
170+ t.Error("expected non-zero signature")
171+ }
172+ })
173+
174+ t.Run("same interactions produce same signature", func(t *testing.T) {
175+ content1 := fantasy.ResponseContent{
176+ fantasy.ToolCallContent{ToolCallID: "1", ToolName: "read", Input: `{"file":"a.go"}`},
177+ fantasy.ToolResultContent{ToolCallID: "1", ToolName: "read", Result: fantasy.ToolResultOutputContentText{Text: "content"}},
178+ }
179+ content2 := fantasy.ResponseContent{
180+ fantasy.ToolCallContent{ToolCallID: "2", ToolName: "read", Input: `{"file":"a.go"}`},
181+ fantasy.ToolResultContent{ToolCallID: "2", ToolName: "read", Result: fantasy.ToolResultOutputContentText{Text: "content"}},
182+ }
183+ sig1 := getToolInteractionSignature(content1)
184+ sig2 := getToolInteractionSignature(content2)
185+ if sig1 != sig2 {
186+ t.Errorf("expected same signature for same interactions, got %d and %d", sig1, sig2)
187+ }
188+ })
189+
190+ t.Run("different inputs produce different signatures", func(t *testing.T) {
191+ content1 := fantasy.ResponseContent{
192+ fantasy.ToolCallContent{ToolCallID: "1", ToolName: "read", Input: `{"file":"a.go"}`},
193+ fantasy.ToolResultContent{ToolCallID: "1", ToolName: "read", Result: fantasy.ToolResultOutputContentText{Text: "content"}},
194+ }
195+ content2 := fantasy.ResponseContent{
196+ fantasy.ToolCallContent{ToolCallID: "1", ToolName: "read", Input: `{"file":"b.go"}`},
197+ fantasy.ToolResultContent{ToolCallID: "1", ToolName: "read", Result: fantasy.ToolResultOutputContentText{Text: "content"}},
198+ }
199+ sig1 := getToolInteractionSignature(content1)
200+ sig2 := getToolInteractionSignature(content2)
201+ if sig1 == sig2 {
202+ t.Error("expected different signatures for different inputs")
203+ }
204+ })
205+}
internal/agent/notify/notify.gonew file+63
@@ -0,0 +1,63 @@
1+// Package notify defines domain notification types for agent events.
2+// These types are decoupled from UI concerns so the agent can publish
3+// events without importing UI packages.
4+package notify
5+
6+// Type identifies the kind of agent notification.
7+type Type string
8+
9+const (
10+ // TypeAgentFinished indicates the agent has completed its turn.
11+ TypeAgentFinished Type = "agent_finished"
12+ // TypeReAuthenticate indicates the agent encountered an
13+ // authentication error and the user needs to re-authenticate.
14+ TypeReAuthenticate Type = "re_authenticate"
15+ // TypeAgentError indicates the agent's turn terminated with an
16+ // error. The error text is carried in Notification.Message.
17+ TypeAgentError Type = "error"
18+)
19+
20+// Notification represents a domain event published by the agent.
21+type Notification struct {
22+ SessionID string
23+ SessionTitle string
24+ Type Type
25+ ProviderID string
26+ // RunID, when non-empty, is the caller-supplied correlator
27+ // (proto.AgentMessage.RunID) for the run that produced this
28+ // notification. It lets observers attribute a TypeAgentError to a
29+ // specific request rather than to any in-flight run on the
30+ // session. Empty when no caller set one.
31+ RunID string
32+ // Message carries the error text for TypeAgentError. Other
33+ // notification types ignore it.
34+ Message string
35+}
36+
37+// RunComplete is the authoritative end-of-run signal for a session.
38+// It is published exactly once per top-level agent run (per
39+// [sessionAgent.Run] invocation that actually executed) after all
40+// message updates for the turn have been flushed via
41+// message.Service.FlushAll. Carries the final assistant text and
42+// message ID so non-interactive clients can reconcile stdout even if
43+// SSE events arrive out of order or are dropped by the broker. Error
44+// is non-empty when the run terminated with an error; Cancelled is
45+// true when the run terminated due to context cancellation. The two
46+// are mutually exclusive in the success case but may overlap when a
47+// cancel triggers a downstream error.
48+//
49+// RunID identifies the specific request that produced this event.
50+// It is the value the caller set on `proto.AgentMessage.RunID` (or
51+// equivalently propagated via agent.WithRunID on the context that
52+// reaches the coordinator); empty when no caller set one. Filtering
53+// by RunID lets a client correlate a SendMessage call with its
54+// terminal event even when the session is busy and other turns are
55+// finishing on the same session.
56+type RunComplete struct {
57+ SessionID string
58+ RunID string
59+ MessageID string
60+ Text string
61+ Error string
62+ Cancelled bool
63+}
internal/agent/prompt/prompt.go+151−43
@@ -1,7 +1,10 @@
11package prompt
22
33import (
4+ "cmp"
5+ "context"
46 "fmt"
7+ "log/slog"
58 "os"
69 "path/filepath"
710 "runtime"
@@ -10,7 +13,10 @@ import (
1013 "time"
1114
1215 "github.com/charmbracelet/crush/internal/config"
16+ "github.com/charmbracelet/crush/internal/filepathext"
1317 "github.com/charmbracelet/crush/internal/home"
18+ "github.com/charmbracelet/crush/internal/shell"
19+ "github.com/charmbracelet/crush/internal/skills"
1420)
1521
1622// Prompt represents a template-based prompt generator.
@@ -23,14 +29,17 @@ type Prompt struct {
2329}
2430
2531type PromptDat struct {
26− Provider string
27− Model string
28− Config config.Config
29− WorkingDir string
30− IsGitRepo bool
31− Platform string
32− Date string
33− ContextFiles []ContextFile
32+ Provider string
33+ Model string
34+ Config config.Config
35+ WorkingDir string
36+ IsGitRepo bool
37+ Platform string
38+ Date string
39+ GitStatus string
40+ ContextFiles []ContextFile
41+ GlobalContextFiles []ContextFile
42+ AvailSkillXML string
3443}
3544
3645type ContextFile struct {
@@ -70,13 +79,17 @@ func NewPrompt(name, promptTemplate string, opts ...Option) (*Prompt, error) {
7079 return p, nil
7180}
7281
73−func (p *Prompt) Build(provider, model string, cfg config.Config) (string, error) {
82+func (p *Prompt) Build(ctx context.Context, provider, model string, store *config.ConfigStore) (string, error) {
7483 t, err := template.New(p.name).Parse(p.template)
7584 if err != nil {
7685 return "", fmt.Errorf("parsing template: %w", err)
7786 }
7887 var sb strings.Builder
79− if err := t.Execute(&sb, p.promptData(provider, model, cfg)); err != nil {
88+ d, err := p.promptData(ctx, provider, model, store)
89+ if err != nil {
90+ return "", err
91+ }
92+ if err := t.Execute(&sb, d); err != nil {
8093 return "", fmt.Errorf("executing template: %w", err)
8194 }
8295
@@ -94,18 +107,15 @@ func processFile(filePath string) *ContextFile {
94107 }
95108}
96109
97−func processContextPath(p string, cfg config.Config) []ContextFile {
110+func processContextPath(p string, store *config.ConfigStore) []ContextFile {
98111 var contexts []ContextFile
99− fullPath := p
100− if !filepath.IsAbs(p) {
101− fullPath = filepath.Join(cfg.WorkingDir(), p)
102− }
112+ fullPath := filepathext.SmartJoin(store.WorkingDir(), p)
103113 info, err := os.Stat(fullPath)
104114 if err != nil {
105115 return contexts
106116 }
107117 if info.IsDir() {
108− filepath.WalkDir(fullPath, func(path string, d os.DirEntry, err error) error {
118+ _ = filepath.WalkDir(fullPath, func(path string, d os.DirEntry, err error) error {
109119 if err != nil {
110120 return err
111121 }
@@ -126,11 +136,11 @@ func processContextPath(p string, cfg config.Config) []ContextFile {
126136}
127137
128138// expandPath expands ~ and environment variables in file paths
129−func expandPath(path string, cfg config.Config) string {
139+func expandPath(path string, store *config.ConfigStore) string {
130140 path = home.Long(path)
131141 // Handle environment variable expansion using the same pattern as config
132142 if strings.HasPrefix(path, "$") {
133− if expanded, err := cfg.Resolver().ResolveValue(path); err == nil {
143+ if expanded, err := store.Resolver().ResolveValue(path); err == nil {
134144 path = expanded
135145 }
136146 }
@@ -138,42 +148,88 @@ func expandPath(path string, cfg config.Config) string {
138148 return path
139149}
140150
141−func (p *Prompt) promptData(provider, model string, cfg config.Config) PromptDat {
142− workingDir := cfg.WorkingDir()
143− if p.workingDir != "" {
144− workingDir = p.workingDir
145− }
146− platform := runtime.GOOS
147− if p.platform != "" {
148− platform = p.platform
149− }
150−
151+// loadContextFiles loads and deduplicates context files from a list of paths.
152+func loadContextFiles(paths []string, store *config.ConfigStore) map[string][]ContextFile {
151153 files := map[string][]ContextFile{}
152−
153− for _, pth := range cfg.Options.ContextPaths {
154− expanded := expandPath(pth, cfg)
154+ for _, pth := range paths {
155+ expanded := expandPath(pth, store)
155156 pathKey := strings.ToLower(expanded)
156157 if _, ok := files[pathKey]; ok {
157158 continue
158159 }
159− content := processContextPath(expanded, cfg)
160− files[pathKey] = content
160+ files[pathKey] = processContextPath(expanded, store)
161161 }
162+ return files
163+}
164+
165+func (p *Prompt) promptData(ctx context.Context, provider, model string, store *config.ConfigStore) (PromptDat, error) {
166+ workingDir := cmp.Or(p.workingDir, store.WorkingDir())
167+ platform := cmp.Or(p.platform, runtime.GOOS)
162168
169+ cfg := store.Config()
170+ contextFiles := loadContextFiles(cfg.Options.ContextPaths, store)
171+ globalContextFiles := loadContextFiles(cfg.Options.GlobalContextPaths, store)
172+
173+ // Discover and load skills metadata.
174+ var availSkillXML string
175+
176+ // Start with builtin skills.
177+ allSkills := skills.DiscoverBuiltin()
178+ builtinNames := make(map[string]bool, len(allSkills))
179+ for _, s := range allSkills {
180+ builtinNames[s.Name] = true
181+ }
182+
183+ // Discover user skills from configured paths.
184+ if len(cfg.Options.SkillsPaths) > 0 {
185+ expandedPaths := make([]string, 0, len(cfg.Options.SkillsPaths))
186+ for _, pth := range cfg.Options.SkillsPaths {
187+ expandedPaths = append(expandedPaths, expandPath(pth, store))
188+ }
189+ for _, userSkill := range skills.Discover(expandedPaths) {
190+ if builtinNames[userSkill.Name] {
191+ slog.Warn("User skill overrides builtin skill", "name", userSkill.Name)
192+ }
193+ allSkills = append(allSkills, userSkill)
194+ }
195+ }
196+
197+ // Deduplicate: user skills override builtins with the same name.
198+ allSkills = skills.Deduplicate(allSkills)
199+
200+ // Filter out disabled skills.
201+ allSkills = skills.Filter(allSkills, cfg.Options.DisabledSkills)
202+
203+ if len(allSkills) > 0 {
204+ availSkillXML = skills.ToPromptXML(allSkills)
205+ }
206+
207+ isGit := isGitRepo(store.WorkingDir())
163208 data := PromptDat{
164− Provider: provider,
165− Model: model,
166− Config: cfg,
167− WorkingDir: workingDir,
168− IsGitRepo: isGitRepo(cfg.WorkingDir()),
169− Platform: platform,
170− Date: p.now().Format("1/2/2006"),
209+ Provider: provider,
210+ Model: model,
211+ Config: *cfg,
212+ WorkingDir: filepath.ToSlash(workingDir),
213+ IsGitRepo: isGit,
214+ Platform: platform,
215+ Date: p.now().Format("1/2/2006"),
216+ AvailSkillXML: availSkillXML,
217+ }
218+ if isGit {
219+ var err error
220+ data.GitStatus, err = getGitStatus(ctx, store.WorkingDir())
221+ if err != nil {
222+ return PromptDat{}, err
223+ }
171224 }
172225
173− for _, contextFiles := range files {
174− data.ContextFiles = append(data.ContextFiles, contextFiles...)
226+ for _, files := range contextFiles {
227+ data.ContextFiles = append(data.ContextFiles, files...)
228+ }
229+ for _, files := range globalContextFiles {
230+ data.GlobalContextFiles = append(data.GlobalContextFiles, files...)
175231 }
176− return data
232+ return data, nil
177233}
178234
179235func isGitRepo(dir string) bool {
@@ -181,6 +237,58 @@ func isGitRepo(dir string) bool {
181237 return err == nil
182238}
183239
240+func getGitStatus(ctx context.Context, dir string) (string, error) {
241+ sh := shell.NewShell(&shell.Options{
242+ WorkingDir: dir,
243+ })
244+ branch, err := getGitBranch(ctx, sh)
245+ if err != nil {
246+ return "", err
247+ }
248+ status, err := getGitStatusSummary(ctx, sh)
249+ if err != nil {
250+ return "", err
251+ }
252+ commits, err := getGitRecentCommits(ctx, sh)
253+ if err != nil {
254+ return "", err
255+ }
256+ return branch + status + commits, nil
257+}
258+
259+func getGitBranch(ctx context.Context, sh *shell.Shell) (string, error) {
260+ out, _, err := sh.Exec(ctx, "git branch --show-current 2>/dev/null")
261+ if err != nil {
262+ return "", nil
263+ }
264+ out = strings.TrimSpace(out)
265+ if out == "" {
266+ return "", nil
267+ }
268+ return fmt.Sprintf("Current branch: %s\n", out), nil
269+}
270+
271+func getGitStatusSummary(ctx context.Context, sh *shell.Shell) (string, error) {
272+ out, _, err := sh.Exec(ctx, "git status --short 2>/dev/null | head -20")
273+ if err != nil {
274+ return "", nil
275+ }
276+ out = strings.TrimSpace(out)
277+ if out == "" {
278+ return "Status: clean\n", nil
279+ }
280+ return fmt.Sprintf("Status:\n%s\n", out), nil
281+}
282+
283+func getGitRecentCommits(ctx context.Context, sh *shell.Shell) (string, error) {
284+ out, _, err := sh.Exec(ctx, "git log --oneline -n 3 2>/dev/null")
285+ if err != nil || out == "" {
286+ return "", nil
287+ }
288+ out = strings.TrimSpace(out)
289+ return fmt.Sprintf("Recent commits:\n%s\n", out), nil
290+}
291+
184292func (p *Prompt) Name() string {
185293 return p.name
186294}
internal/agent/prompts.go+10−4
@@ -1,9 +1,11 @@
11package agent
22
33import (
4+ "context"
45 _ "embed"
56
67 "github.com/charmbracelet/crush/internal/agent/prompt"
8+ "github.com/charmbracelet/crush/internal/config"
79)
810
911//go:embed templates/coder.md.tpl
@@ -12,8 +14,8 @@ var coderPromptTmpl []byte
1214//go:embed templates/task.md.tpl
1315var taskPromptTmpl []byte
1416
15−//go:embed templates/initialize.md
16−var initializePrompt []byte
17+//go:embed templates/initialize.md.tpl
18+var initializePromptTmpl []byte
1719
1820func coderPrompt(opts ...prompt.Option) (*prompt.Prompt, error) {
1921 systemPrompt, err := prompt.NewPrompt("coder", string(coderPromptTmpl), opts...)
@@ -31,6 +33,10 @@ func taskPrompt(opts ...prompt.Option) (*prompt.Prompt, error) {
3133 return systemPrompt, nil
3234}
3335
34−func InitializePrompt() string {
35− return string(initializePrompt)
36+func InitializePrompt(cfg *config.ConfigStore) (string, error) {
37+ systemPrompt, err := prompt.NewPrompt("initialize", string(initializePromptTmpl))
38+ if err != nil {
39+ return "", err
40+ }
41+ return systemPrompt.Build(context.Background(), "", "", cfg)
3642}
internal/agent/queued_runid_test.gonew file+181
@@ -0,0 +1,181 @@
1+package agent
2+
3+import (
4+ "context"
5+ "errors"
6+ "sync/atomic"
7+ "testing"
8+ "time"
9+
10+ "charm.land/catwalk/pkg/catwalk"
11+ "charm.land/fantasy"
12+ "github.com/charmbracelet/crush/internal/agent/notify"
13+ "github.com/charmbracelet/crush/internal/message"
14+ "github.com/charmbracelet/crush/internal/pubsub"
15+ "github.com/stretchr/testify/require"
16+)
17+
18+// gatedStreamModel streams a single text part followed by a clean finish,
19+// but blocks the very first Stream call until its gate is released. That
20+// lets a test hold a run "active" (past PrepareStep, inside Stream) just
21+// long enough to enqueue a follow-up prompt behind the busy session.
22+// Subsequent Stream calls (e.g. the recursive run draining the queue)
23+// proceed immediately.
24+type gatedStreamModel struct {
25+ text string
26+ gate chan struct{}
27+ entered chan struct{}
28+ calls atomic.Int64
29+}
30+
31+func (m *gatedStreamModel) Provider() string { return "fake" }
32+func (m *gatedStreamModel) Model() string { return "fake-model" }
33+
34+func (m *gatedStreamModel) Generate(ctx context.Context, call fantasy.Call) (*fantasy.Response, error) {
35+ return &fantasy.Response{
36+ Content: fantasy.ResponseContent{fantasy.TextContent{Text: m.text}},
37+ FinishReason: fantasy.FinishReasonStop,
38+ }, nil
39+}
40+
41+func (m *gatedStreamModel) Stream(ctx context.Context, call fantasy.Call) (fantasy.StreamResponse, error) {
42+ if m.calls.Add(1) == 1 {
43+ close(m.entered)
44+ select {
45+ case <-m.gate:
46+ case <-ctx.Done():
47+ }
48+ }
49+ text := m.text
50+ return func(yield func(fantasy.StreamPart) bool) {
51+ if !yield(fantasy.StreamPart{Type: fantasy.StreamPartTypeTextStart, ID: "1"}) {
52+ return
53+ }
54+ if !yield(fantasy.StreamPart{Type: fantasy.StreamPartTypeTextDelta, ID: "1", Delta: text}) {
55+ return
56+ }
57+ if !yield(fantasy.StreamPart{Type: fantasy.StreamPartTypeTextEnd, ID: "1"}) {
58+ return
59+ }
60+ yield(fantasy.StreamPart{Type: fantasy.StreamPartTypeFinish, FinishReason: fantasy.FinishReasonStop})
61+ }, nil
62+}
63+
64+func (m *gatedStreamModel) GenerateObject(ctx context.Context, call fantasy.ObjectCall) (*fantasy.ObjectResponse, error) {
65+ return nil, errors.New("not implemented")
66+}
67+
68+func (m *gatedStreamModel) StreamObject(ctx context.Context, call fantasy.ObjectCall) (fantasy.ObjectStreamResponse, error) {
69+ return nil, errors.New("not implemented")
70+}
71+
72+// TestRun_QueuedRunIDPromptRunsRecursivelyAndPublishesRunComplete is the
73+// end-to-end proof of fix 2: a prompt carrying a RunID that is queued
74+// behind a busy session must NOT be silently folded into the active turn.
75+// It runs as its own turn via the recursive run path and publishes its
76+// own terminal RunComplete, so a `crush run` caller blocking on that
77+// RunID does not hang. The active turn keeps its own RunComplete too.
78+func TestRun_QueuedRunIDPromptRunsRecursivelyAndPublishesRunComplete(t *testing.T) {
79+ t.Parallel()
80+
81+ env := testEnv(t)
82+ broker := pubsub.NewBroker[notify.RunComplete]()
83+ t.Cleanup(broker.Shutdown)
84+
85+ large := &gatedStreamModel{
86+ text: "done",
87+ gate: make(chan struct{}),
88+ entered: make(chan struct{}),
89+ }
90+ small := &finishStreamModel{text: "title"}
91+
92+ sa := NewSessionAgent(SessionAgentOptions{
93+ LargeModel: Model{Model: large, CatwalkCfg: catwalk.Model{ContextWindow: 200000, DefaultMaxTokens: 10000}},
94+ SmallModel: Model{Model: small, CatwalkCfg: catwalk.Model{ContextWindow: 200000, DefaultMaxTokens: 10000}},
95+ IsYolo: true,
96+ Sessions: env.sessions,
97+ Messages: env.messages,
98+ RunComplete: broker,
99+ }).(*sessionAgent)
100+
101+ sess, err := env.sessions.Create(t.Context(), "session")
102+ require.NoError(t, err)
103+
104+ subCtx, subCancel := context.WithCancel(t.Context())
105+ defer subCancel()
106+ ch := broker.Subscribe(subCtx)
107+
108+ // Start the main turn; it blocks inside Stream once active.
109+ mainDone := make(chan error, 1)
110+ go func() {
111+ _, runErr := sa.Run(t.Context(), SessionAgentCall{
112+ SessionID: sess.ID,
113+ RunID: "run-main",
114+ Prompt: "main",
115+ })
116+ mainDone <- runErr
117+ }()
118+
119+ // Wait until the main turn is active (inside Stream).
120+ select {
121+ case <-large.entered:
122+ case <-time.After(5 * time.Second):
123+ t.Fatal("main run never entered Stream")
124+ }
125+ require.True(t, sa.IsSessionBusy(sess.ID), "main run must be active before enqueueing the follow-up")
126+
127+ // Enqueue a RunID-bearing follow-up behind the busy session.
128+ res, err := sa.Run(t.Context(), SessionAgentCall{
129+ SessionID: sess.ID,
130+ RunID: "run-follow",
131+ Prompt: "follow",
132+ })
133+ require.NoError(t, err)
134+ require.Nil(t, res, "a busy-session follow-up must enqueue and return (nil, nil)")
135+ require.Equal(t, 1, sa.QueuedPrompts(sess.ID), "the follow-up must be queued, not folded")
136+
137+ // Release the main turn so it completes and hands off to the queue.
138+ close(large.gate)
139+ require.NoError(t, <-mainDone)
140+
141+ // Both turns must publish their own terminal RunComplete.
142+ got := map[string]notify.RunComplete{}
143+ deadline := time.After(5 * time.Second)
144+ for len(got) < 2 {
145+ select {
146+ case ev := <-ch:
147+ got[ev.Payload.RunID] = ev.Payload
148+ case <-deadline:
149+ t.Fatalf("timed out waiting for both RunCompletes; got %v", got)
150+ }
151+ }
152+
153+ main, ok := got["run-main"]
154+ require.True(t, ok, "the active turn must publish its own RunComplete")
155+ require.Empty(t, main.Error)
156+ require.False(t, main.Cancelled)
157+
158+ follow, ok := got["run-follow"]
159+ require.True(t, ok,
160+ "the queued RunID prompt must publish its own RunComplete instead of being folded silently")
161+ require.Empty(t, follow.Error)
162+ require.False(t, follow.Cancelled)
163+ require.Equal(t, "done", follow.Text, "the queued prompt ran as its own turn")
164+
165+ // Two distinct assistant turns prove the follow-up was not folded.
166+ msgs, err := env.messages.List(t.Context(), sess.ID)
167+ require.NoError(t, err)
168+ var assistants, follows int
169+ for _, m := range msgs {
170+ switch m.Role {
171+ case message.Assistant:
172+ assistants++
173+ case message.User:
174+ if m.Content().String() == "follow" {
175+ follows++
176+ }
177+ }
178+ }
179+ require.Equal(t, 2, assistants, "the active turn and the recursive turn each produce one assistant message")
180+ require.Equal(t, 1, follows, "the follow-up prompt is its own user turn")
181+}
internal/agent/recorder_test.godeleted−104
@@ -1,104 +0,0 @@
1−package agent
2−
3−import (
4− "bytes"
5− "encoding/json"
6− "io"
7− "net/http"
8− "path/filepath"
9− "reflect"
10− "strings"
11− "testing"
12−
13− "go.yaml.in/yaml/v4"
14− "gopkg.in/dnaeon/go-vcr.v4/pkg/cassette"
15− "gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
16−)
17−
18−func newRecorder(t *testing.T) *recorder.Recorder {
19− cassetteName := filepath.Join("testdata", t.Name())
20−
21− r, err := recorder.New(
22− cassetteName,
23− recorder.WithMode(recorder.ModeRecordOnce),
24− recorder.WithMatcher(customMatcher(t)),
25− recorder.WithMarshalFunc(marshalFunc),
26− recorder.WithSkipRequestLatency(true), // disable sleep to simulate response time, makes tests faster
27− recorder.WithHook(hookRemoveHeaders, recorder.AfterCaptureHook),
28− )
29− if err != nil {
30− t.Fatalf("recorder: failed to create recorder: %v", err)
31− }
32−
33− t.Cleanup(func() {
34− if err := r.Stop(); err != nil {
35− t.Errorf("recorder: failed to stop recorder: %v", err)
36− }
37− })
38−
39− return r
40−}
41−
42−func customMatcher(t *testing.T) recorder.MatcherFunc {
43− return func(r *http.Request, i cassette.Request) bool {
44− if r.Body == nil || r.Body == http.NoBody {
45− return cassette.DefaultMatcher(r, i)
46− }
47− if r.Method != i.Method || r.URL.String() != i.URL {
48− return false
49− }
50−
51− reqBody, err := io.ReadAll(r.Body)
52− if err != nil {
53− t.Fatalf("recorder: failed to read request body")
54− }
55− r.Body.Close()
56− r.Body = io.NopCloser(bytes.NewBuffer(reqBody))
57−
58− // Some providers can sometimes generate JSON requests with keys in
59− // a different order, which means a direct string comparison will fail.
60− // Falling back to deserializing the content if we don't have a match.
61− if string(reqBody) == i.Body { // hot path
62− return true
63− }
64− var content1, content2 any
65− if err := json.Unmarshal(reqBody, &content1); err != nil {
66− return false
67− }
68− if err := json.Unmarshal([]byte(i.Body), &content2); err != nil {
69− return false
70− }
71− return reflect.DeepEqual(content1, content2)
72− }
73−}
74−
75−func marshalFunc(in any) ([]byte, error) {
76− var buff bytes.Buffer
77− enc := yaml.NewEncoder(&buff)
78− enc.SetIndent(2)
79− enc.CompactSeqIndent()
80− if err := enc.Encode(in); err != nil {
81− return nil, err
82− }
83− return buff.Bytes(), nil
84−}
85−
86−var headersToKeep = map[string]struct{}{
87− "accept": {},
88− "content-type": {},
89− "user-agent": {},
90−}
91−
92−func hookRemoveHeaders(i *cassette.Interaction) error {
93− for k := range i.Request.Headers {
94− if _, ok := headersToKeep[strings.ToLower(k)]; !ok {
95− delete(i.Request.Headers, k)
96− }
97− }
98− for k := range i.Response.Headers {
99− if _, ok := headersToKeep[strings.ToLower(k)]; !ok {
100− delete(i.Response.Headers, k)
101− }
102− }
103− return nil
104−}
internal/agent/run_complete_test.gonew file+322
@@ -0,0 +1,322 @@
1+package agent
2+
3+import (
4+ "context"
5+ "testing"
6+ "time"
7+
8+ "github.com/charmbracelet/crush/internal/agent/notify"
9+ "github.com/charmbracelet/crush/internal/pubsub"
10+ "github.com/stretchr/testify/require"
11+)
12+
13+// TestSessionAgentRun_QueueStripsOnComplete verifies that when a Run
14+// call is enqueued (because the session is already busy), the
15+// OnComplete hook is NOT propagated onto the queued copy. The hook
16+// belongs to the caller's retry/coalesce scope (typically
17+// coordinator.Run) which has already returned by the time the queue
18+// drains; carrying it forward would silently funnel the terminal
19+// event into a closure nobody reads, and subscribers (`crush run`)
20+// would hang waiting for a RunComplete that never publishes.
21+func TestSessionAgentRun_QueueStripsOnComplete(t *testing.T) {
22+ t.Parallel()
23+
24+ env := testEnv(t)
25+ a := NewSessionAgent(SessionAgentOptions{
26+ Sessions: env.sessions,
27+ Messages: env.messages,
28+ }).(*sessionAgent)
29+
30+ const sessionID = "queued-session"
31+ // Mark the session as busy so Run takes the queue branch
32+ // without needing a real model.
33+ a.activeRequests.Set(sessionID, func() {})
34+
35+ var called bool
36+ hook := func(notify.RunComplete) { called = true }
37+
38+ res, err := a.Run(t.Context(), SessionAgentCall{
39+ SessionID: sessionID,
40+ RunID: "run-xyz",
41+ Prompt: "queued prompt",
42+ OnComplete: hook,
43+ })
44+ require.NoError(t, err)
45+ require.Nil(t, res, "queued Run must return (nil, nil)")
46+ require.False(t, called,
47+ "OnComplete must not fire on the enqueue path; the caller's scope is still live")
48+
49+ queued, ok := a.messageQueue.Get(sessionID)
50+ require.True(t, ok)
51+ require.Len(t, queued, 1)
52+ require.Nil(t, queued[0].OnComplete,
53+ "queued SessionAgentCall must have OnComplete stripped so the drain falls back to the default broker publish")
54+ require.Equal(t, "queued prompt", queued[0].Prompt,
55+ "all other fields must be preserved on the queued copy")
56+ require.Equal(t, "run-xyz", queued[0].RunID,
57+ "RunID must be preserved on the queued copy so the drained turn's "+
58+ "RunComplete still correlates with the originating SendMessage")
59+}
60+
61+// TestDrainQueueForStep_FiltersUnderDispatchLock verifies that the queue
62+// drain evaluates the per-session cancel mark while holding the dispatch
63+// mutex (canceledBySeq's documented precondition). Queued calls at or
64+// below the cancel high-water mark are dropped, calls queued after the
65+// cancel (higher seq) are folded, untracked enqueues (seq == 0) are
66+// dropped whenever any mark is present, and the queue is cleared. These
67+// calls carry no RunID, so all foldable survivors are returned for
68+// folding (the existing follow-up behavior).
69+func TestDrainQueueForStep_FiltersUnderDispatchLock(t *testing.T) {
70+ t.Parallel()
71+
72+ env := testEnv(t)
73+ a := NewSessionAgent(SessionAgentOptions{
74+ Sessions: env.sessions,
75+ Messages: env.messages,
76+ }).(*sessionAgent)
77+
78+ const sessionID = "drain-session"
79+ a.messageQueue.Set(sessionID, []SessionAgentCall{
80+ {SessionID: sessionID, Prompt: "below", acceptSeq: 1},
81+ {SessionID: sessionID, Prompt: "at-mark", acceptSeq: 2},
82+ {SessionID: sessionID, Prompt: "after", acceptSeq: 3},
83+ {SessionID: sessionID, Prompt: "untracked", acceptSeq: 0},
84+ })
85+ // Cancel high-water mark at seq 2: seq <= 2 and seq == 0 are covered.
86+ a.cancelMark.Set(sessionID, 2)
87+
88+ fold, canceledWithRunID := a.drainQueueForStep(sessionID)
89+
90+ require.Len(t, fold, 1,
91+ "only the follow-up queued after the cancel (seq > mark) must be folded")
92+ require.Equal(t, "after", fold[0].Prompt)
93+ require.Empty(t, canceledWithRunID,
94+ "no dropped call carried a RunID, so none need a terminal RunComplete")
95+
96+ _, ok := a.messageQueue.Get(sessionID)
97+ require.False(t, ok, "drain must clear the session message queue when nothing is kept")
98+}
99+
100+// TestDrainQueueForStep_NoMarkFoldsAllNonRunID verifies that with no
101+// cancel mark recorded, every queued call without a RunID is folded.
102+func TestDrainQueueForStep_NoMarkFoldsAllNonRunID(t *testing.T) {
103+ t.Parallel()
104+
105+ env := testEnv(t)
106+ a := NewSessionAgent(SessionAgentOptions{
107+ Sessions: env.sessions,
108+ Messages: env.messages,
109+ }).(*sessionAgent)
110+
111+ const sessionID = "drain-nomark"
112+ a.messageQueue.Set(sessionID, []SessionAgentCall{
113+ {SessionID: sessionID, Prompt: "a", acceptSeq: 0},
114+ {SessionID: sessionID, Prompt: "b", acceptSeq: 5},
115+ })
116+
117+ fold, canceledWithRunID := a.drainQueueForStep(sessionID)
118+ require.Len(t, fold, 2, "no cancel mark means all non-RunID queued calls are folded")
119+ require.Empty(t, canceledWithRunID)
120+}
121+
122+// TestDrainQueueForStep_KeepsRunIDPromptsQueued is the core of fix 2: a
123+// queued prompt that carries a RunID must NOT be folded into the active
124+// turn. Folding it would silently absorb it into another turn and never
125+// publish a RunComplete for its RunID, hanging a `crush run` caller that
126+// blocks on that event. Such prompts are left in the queue so the
127+// recursive run path gives each its own turn and its own RunComplete.
128+// Non-RunID prompts are still folded.
129+func TestDrainQueueForStep_KeepsRunIDPromptsQueued(t *testing.T) {
130+ t.Parallel()
131+
132+ env := testEnv(t)
133+ a := NewSessionAgent(SessionAgentOptions{
134+ Sessions: env.sessions,
135+ Messages: env.messages,
136+ }).(*sessionAgent)
137+
138+ const sessionID = "drain-runid"
139+ a.messageQueue.Set(sessionID, []SessionAgentCall{
140+ {SessionID: sessionID, Prompt: "fold-me", acceptSeq: 1},
141+ {SessionID: sessionID, RunID: "run-a", Prompt: "keep-me", acceptSeq: 2},
142+ {SessionID: sessionID, RunID: "run-b", Prompt: "keep-me-too", acceptSeq: 3},
143+ })
144+
145+ fold, canceledWithRunID := a.drainQueueForStep(sessionID)
146+
147+ require.Len(t, fold, 1, "only the non-RunID prompt is folded into the active turn")
148+ require.Equal(t, "fold-me", fold[0].Prompt)
149+ require.Empty(t, canceledWithRunID)
150+
151+ kept, ok := a.messageQueue.Get(sessionID)
152+ require.True(t, ok, "RunID-bearing prompts must remain queued for the recursive run path")
153+ require.Len(t, kept, 2)
154+ require.Equal(t, "run-a", kept[0].RunID)
155+ require.Equal(t, "run-b", kept[1].RunID)
156+}
157+
158+// TestDrainQueueForStep_ReportsCanceledRunIDDrops verifies that a queued
159+// prompt carrying a RunID that is dropped because a cancel covers it is
160+// reported in canceledWithRunID so the caller can publish its terminal
161+// cancelled RunComplete. A canceled prompt without a RunID is dropped
162+// silently as before.
163+func TestDrainQueueForStep_ReportsCanceledRunIDDrops(t *testing.T) {
164+ t.Parallel()
165+
166+ env := testEnv(t)
167+ a := NewSessionAgent(SessionAgentOptions{
168+ Sessions: env.sessions,
169+ Messages: env.messages,
170+ }).(*sessionAgent)
171+
172+ const sessionID = "drain-cancel-runid"
173+ a.messageQueue.Set(sessionID, []SessionAgentCall{
174+ {SessionID: sessionID, RunID: "run-canceled", Prompt: "canceled", acceptSeq: 1},
175+ {SessionID: sessionID, Prompt: "canceled-no-runid", acceptSeq: 1},
176+ {SessionID: sessionID, RunID: "run-survives", Prompt: "survives", acceptSeq: 5},
177+ })
178+ a.cancelMark.Set(sessionID, 2)
179+
180+ fold, canceledWithRunID := a.drainQueueForStep(sessionID)
181+
182+ require.Empty(t, fold, "no uncanceled non-RunID prompts to fold")
183+ require.Len(t, canceledWithRunID, 1,
184+ "only the dropped RunID-bearing prompt needs a terminal RunComplete")
185+ require.Equal(t, "run-canceled", canceledWithRunID[0].RunID)
186+
187+ kept, ok := a.messageQueue.Get(sessionID)
188+ require.True(t, ok)
189+ require.Len(t, kept, 1, "the uncanceled RunID prompt stays queued")
190+ require.Equal(t, "run-survives", kept[0].RunID)
191+}
192+
193+// TestRunCompletePublisher_MustDeliverOverTakesPublish exercises the
194+// pubsub.Publisher interface change end-to-end: a Broker is the only
195+// concrete Publisher implementation and must satisfy both Publish and
196+// PublishMustDeliver. The coordinator's final RunComplete emit relies
197+// on PublishMustDeliver to apply bounded-blocking semantics so a
198+// momentarily-full subscriber buffer can't silently drop the
199+// authoritative end-of-run event.
200+func TestRunCompletePublisher_MustDeliverOverTakesPublish(t *testing.T) {
201+ t.Parallel()
202+
203+ broker := pubsub.NewBroker[notify.RunComplete]()
204+ t.Cleanup(broker.Shutdown)
205+
206+ // Subscribe before publishing so the event is delivered.
207+ ctx, cancel := context.WithCancel(t.Context())
208+ defer cancel()
209+ ch := broker.Subscribe(ctx)
210+
211+ rc := notify.RunComplete{SessionID: "S", MessageID: "m", Text: "ok"}
212+ var pub pubsub.Publisher[notify.RunComplete] = broker
213+ pub.PublishMustDeliver(t.Context(), pubsub.UpdatedEvent, rc)
214+
215+ select {
216+ case got := <-ch:
217+ require.Equal(t, rc, got.Payload)
218+ case <-time.After(time.Second):
219+ t.Fatal("PublishMustDeliver did not deliver event")
220+ }
221+}
222+
223+// requireSingleCancelledRunComplete reads exactly one RunComplete from ch,
224+// asserts it is the cancelled terminal event for runID, and verifies no
225+// second event arrives. This observes the published pubsub event rather
226+// than internal bookkeeping, which is the contract a `crush run` caller
227+// blocking on the broker actually relies on.
228+func requireSingleCancelledRunComplete(t *testing.T, ch <-chan pubsub.Event[notify.RunComplete], sessionID, runID string) {
229+ t.Helper()
230+ select {
231+ case ev := <-ch:
232+ require.Equal(t, runID, ev.Payload.RunID,
233+ "the published RunComplete must carry the dropped queued prompt's RunID")
234+ require.Equal(t, sessionID, ev.Payload.SessionID)
235+ require.True(t, ev.Payload.Cancelled,
236+ "a dropped queued prompt must publish a cancelled RunComplete")
237+ case <-time.After(5 * time.Second):
238+ t.Fatal("timed out waiting for the cancelled RunComplete")
239+ }
240+ select {
241+ case extra := <-ch:
242+ t.Fatalf("expected exactly one RunComplete, got a second: %+v", extra.Payload)
243+ case <-time.After(100 * time.Millisecond):
244+ }
245+}
246+
247+// TestCancel_QueuedRunIDPromptPublishesCancelledRunComplete proves the
248+// terminal-event behavior end-to-end: a RunID-bearing prompt sitting in
249+// the queue that is canceled while queued (via the public Cancel path,
250+// which routes through clearQueueAndNotify -> publishCanceledQueueDrops)
251+// must emit exactly one cancelled RunComplete on the broker for its
252+// RunID. A queued prompt without a RunID is dropped silently. This is the
253+// coverage the earlier drain test lacked: it asserted the returned
254+// bookkeeping slice, not the published event a `crush run` caller awaits.
255+func TestCancel_QueuedRunIDPromptPublishesCancelledRunComplete(t *testing.T) {
256+ t.Parallel()
257+
258+ env := testEnv(t)
259+ broker := pubsub.NewBroker[notify.RunComplete]()
260+ t.Cleanup(broker.Shutdown)
261+
262+ a := NewSessionAgent(SessionAgentOptions{
263+ Sessions: env.sessions,
264+ Messages: env.messages,
265+ RunComplete: broker,
266+ }).(*sessionAgent)
267+
268+ subCtx, subCancel := context.WithCancel(t.Context())
269+ defer subCancel()
270+ ch := broker.Subscribe(subCtx)
271+
272+ const sessionID = "cancel-queued-runid"
273+ a.messageQueue.Set(sessionID, []SessionAgentCall{
274+ {SessionID: sessionID, Prompt: "no-runid", acceptSeq: 1},
275+ {SessionID: sessionID, RunID: "run-queued", Prompt: "queued", acceptSeq: 2},
276+ })
277+
278+ a.Cancel(sessionID)
279+
280+ requireSingleCancelledRunComplete(t, ch, sessionID, "run-queued")
281+
282+ _, ok := a.messageQueue.Get(sessionID)
283+ require.False(t, ok, "Cancel must clear the queue")
284+}
285+
286+// TestDrainQueueForStep_DroppedRunIDPublishesCancelledRunComplete drives
287+// the production drain sequence (drainQueueForStep then
288+// publishCanceledQueueDrops, mirroring the PrepareStep handoff) and
289+// asserts the dropped RunID-bearing prompt actually publishes exactly one
290+// cancelled RunComplete on the broker. The companion bookkeeping test
291+// covers the returned slice; this one covers the observable terminal
292+// event.
293+func TestDrainQueueForStep_DroppedRunIDPublishesCancelledRunComplete(t *testing.T) {
294+ t.Parallel()
295+
296+ env := testEnv(t)
297+ broker := pubsub.NewBroker[notify.RunComplete]()
298+ t.Cleanup(broker.Shutdown)
299+
300+ a := NewSessionAgent(SessionAgentOptions{
301+ Sessions: env.sessions,
302+ Messages: env.messages,
303+ RunComplete: broker,
304+ }).(*sessionAgent)
305+
306+ subCtx, subCancel := context.WithCancel(t.Context())
307+ defer subCancel()
308+ ch := broker.Subscribe(subCtx)
309+
310+ const sessionID = "drain-drop-runid"
311+ a.messageQueue.Set(sessionID, []SessionAgentCall{
312+ {SessionID: sessionID, RunID: "run-dropped", Prompt: "dropped", acceptSeq: 1},
313+ {SessionID: sessionID, Prompt: "dropped-no-runid", acceptSeq: 1},
314+ })
315+ a.cancelMark.Set(sessionID, 2)
316+
317+ _, canceledWithRunID := a.drainQueueForStep(sessionID)
318+ require.Len(t, canceledWithRunID, 1)
319+ a.publishCanceledQueueDrops(canceledWithRunID)
320+
321+ requireSingleCancelledRunComplete(t, ch, sessionID, "run-dropped")
322+}
internal/agent/run_marker.gonew file+52
@@ -0,0 +1,52 @@
1+package agent
2+
3+import (
4+ "context"
5+ "sync/atomic"
6+)
7+
8+// runCompleteMarkerKey is the unexported context key carrying a
9+// [runCompleteMarker] from the dispatch boundary (backend.runAgent)
10+// down into the coordinator. It lets the dispatcher learn whether the
11+// coordinator already published the authoritative terminal
12+// notify.RunComplete for the run, so a fallback terminal event is only
13+// emitted when one is actually missing (e.g. an error returned before
14+// sessionAgent.Run ever executed). It avoids a breaking change to the
15+// Coordinator interface.
16+type runCompleteMarkerKey struct{}
17+
18+// runCompleteMarker records whether a terminal RunComplete has been
19+// published for a run. It is shared by pointer through the context so
20+// a publish deep in the call stack is observable by the dispatcher
21+// after the call returns.
22+type runCompleteMarker struct {
23+ published atomic.Bool
24+}
25+
26+// WithRunCompleteMarker returns ctx carrying a fresh marker the
27+// coordinator can flag via [MarkRunCompletePublished] once it emits the
28+// run's terminal RunComplete. Callers read the result with
29+// [RunCompletePublished]. Attaching the marker is optional: code paths
30+// without one simply skip the dedup signal.
31+func WithRunCompleteMarker(ctx context.Context) context.Context {
32+ return context.WithValue(ctx, runCompleteMarkerKey{}, &runCompleteMarker{})
33+}
34+
35+// MarkRunCompletePublished records that the authoritative terminal
36+// RunComplete has been published for the run carried by ctx. It is a
37+// no-op when no marker is present (e.g. the in-process/local Run path,
38+// which is not dispatched through backend.runAgent).
39+func MarkRunCompletePublished(ctx context.Context) {
40+ if m, ok := ctx.Value(runCompleteMarkerKey{}).(*runCompleteMarker); ok {
41+ m.published.Store(true)
42+ }
43+}
44+
45+// RunCompletePublished reports whether [MarkRunCompletePublished] was
46+// called on ctx's marker. It returns false when no marker is present.
47+func RunCompletePublished(ctx context.Context) bool {
48+ if m, ok := ctx.Value(runCompleteMarkerKey{}).(*runCompleteMarker); ok {
49+ return m.published.Load()
50+ }
51+ return false
52+}
internal/agent/runid.gonew file+33
@@ -0,0 +1,33 @@
1+package agent
2+
3+import "context"
4+
5+// runIDContextKey is the unexported context key used to carry a
6+// caller-supplied RunID from the workspace HTTP boundary
7+// (backend.SendMessage) down into coordinator.Run without forcing a
8+// breaking change to the Coordinator.Run signature. The value is
9+// then copied onto SessionAgentCall.RunID by the coordinator so the
10+// agent's terminal RunComplete event can echo it back to the
11+// originating caller.
12+type runIDContextKey struct{}
13+
14+// WithRunID returns ctx tagged with a per-request RunID. It is the
15+// boundary helper for callers that need their SendMessage→Run
16+// terminal event to be uniquely correlatable (e.g. `crush run`
17+// against a session that may be busy). Empty runIDs are stored
18+// as-is; downstream code treats an empty RunID as "caller did not
19+// supply one" and falls back to SessionID-only correlation.
20+func WithRunID(ctx context.Context, runID string) context.Context {
21+ return context.WithValue(ctx, runIDContextKey{}, runID)
22+}
23+
24+// RunIDFromContext returns the RunID set by [WithRunID], or "" if
25+// none was set or the value is not a string. Exported because the
26+// coordinator and tests in other packages need to read it; safe to
27+// call on any context.
28+func RunIDFromContext(ctx context.Context) string {
29+ if v, ok := ctx.Value(runIDContextKey{}).(string); ok {
30+ return v
31+ }
32+ return ""
33+}
internal/agent/templates/agent_tool.md+1−15
@@ -1,15 +1 @@
1−Launch a new agent that has access to the following tools: GlobTool, GrepTool, LS, View. When you are searching for a keyword or file and are not confident that you will find the right match on the first try, use the Agent tool to perform the search for you.
2−
3−<usage>
4−- If you are searching for a keyword like "config" or "logger", or for questions like "which file does X?", the Agent tool is strongly recommended
5−- If you want to read a specific file path, use the View or GlobTool tool instead of the Agent tool, to find the match more quickly
6−- If you are searching for a specific class definition like "class Foo", use the GlobTool tool instead, to find the match more quickly
7−</usage>
8−
9−<usage_notes>
10−1. Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses
11−2. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.
12−3. Each agent invocation is stateless. You will not be able to send additional messages to the agent, nor will the agent be able to communicate with you outside of its final report. Therefore, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.
13−4. The agent's outputs should generally be trusted
14−5. IMPORTANT: The agent can not use Bash, Replace, Edit, so can not modify files. If you want to use these tools, use them directly instead of going through the agent.
15−</usage_notes>
1+Launch a new agent that has access to the following tools: glob, grep, ls, view. When you are searching for a keyword or file and are not confident that you will find the right match on the first try, use the agent tool to perform the search for you.
internal/agent/templates/agentic_fetch.mdnew file+1
@@ -0,0 +1 @@
1+Fetch a URL or search the web using an AI sub-agent that can extract, summarize, and answer questions. Slower and costlier than fetch; use fetch for raw content or API responses.
internal/agent/templates/agentic_fetch_prompt.md.tplnew file+76
@@ -0,0 +1,76 @@
1+You are a web content analysis agent for Crush. Your task is to analyze web content, search results, or web pages to extract the information requested by the user.
2+
3+<rules>
4+1. Be concise and direct in your responses
5+2. Focus only on the information requested in the user's prompt
6+3. If the content is provided in a file path, use the grep and view tools to efficiently search through it
7+4. When relevant, quote specific sections from the content to support your answer
8+5. If the requested information is not found, clearly state that
9+6. Any file paths you use MUST be absolute
10+7. **IMPORTANT**: If you need information from a linked page or search result, use the web_fetch tool to get that content
11+8. **IMPORTANT**: If you need to search for more information, use the web_search tool
12+9. After fetching a link, analyze the content yourself to extract what's needed
13+10. Don't hesitate to follow multiple links or perform multiple searches if necessary to get complete information
14+11. **CRITICAL**: At the end of your response, include a "Sources" section listing ALL URLs that were useful in answering the question
15+</rules>
16+
17+<search_strategy>
18+When searching for information:
19+
20+1. **Break down complex questions** - If the user's question has multiple parts, search for each part separately
21+2. **Use specific, targeted queries** - Prefer multiple small searches over one broad search
22+ - Bad: "Python 3.12 new features performance improvements async changes"
23+ - Good: First "Python 3.12 new features", then "Python 3.12 performance improvements", then "Python 3.12 async changes"
24+3. **Iterate and refine** - If initial results aren't helpful, try different search terms or more specific queries
25+4. **Search for different aspects** - For comprehensive answers, search for different angles of the topic
26+5. **Follow up on promising results** - When you find a good source, fetch it and look for links to related information
27+
28+Example workflow for "What are the pros and cons of using Rust vs Go for web services?":
29+- Search 1: "Rust web services advantages"
30+- Search 2: "Go web services advantages"
31+- Search 3: "Rust vs Go performance comparison"
32+- Search 4: "Rust vs Go developer experience"
33+- Then fetch the most relevant results from each search
34+</search_strategy>
35+
36+<response_format>
37+Your response should be structured as follows:
38+
39+[Your answer to the user's question]
40+
41+## Sources
42+- [URL 1 that was useful]
43+- [URL 2 that was useful]
44+- [URL 3 that was useful]
45+...
46+
47+Only include URLs that actually contributed information to your answer. Include the main URL or search results that were helpful. Add any additional URLs you fetched that provided relevant information.
48+</response_format>
49+
50+<env>
51+Working directory: {{.WorkingDir}}
52+Platform: {{.Platform}}
53+Today's date: {{.Date}}
54+</env>
55+
56+<web_search_tool>
57+You have access to a web_search tool that allows you to search the web:
58+- Provide a search query and optionally max_results (default: 10)
59+- The tool returns search results with titles, URLs, and snippets
60+- After getting search results, use web_fetch to get full content from relevant URLs
61+- **Prefer multiple focused searches over single broad searches**
62+- Keep queries short and specific (3-6 words is often ideal)
63+- If results aren't relevant, try rephrasing with different keywords
64+- Don't be afraid to do 3-5+ searches to thoroughly answer a complex question
65+</web_search_tool>
66+
67+<web_fetch_tool>
68+You have access to a web_fetch tool that allows you to fetch web pages:
69+- Use it when you need to follow links from search results or the current page
70+- Provide just the URL (no prompt parameter)
71+- The tool will fetch and return the content (or save to a file if large)
72+- YOU must then analyze that content to answer the user's question
73+- **Use this liberally** - if a link seems relevant to answering the question, fetch it!
74+- You can fetch multiple pages in sequence to gather all needed information
75+- Remember to include any fetched URLs in your Sources section if they were helpful
76+</web_fetch_tool>
internal/agent/templates/coder.md.tpl+250−22
@@ -3,24 +3,35 @@ You are Crush, a powerful AI Assistant that runs in the CLI.
33<critical_rules>
44These rules override everything else. Follow them strictly:
55
6−1. **ALWAYS READ BEFORE EDITING**: Never edit a file you haven't read in this conversation (only read files if you did not read them before or they changed)
7−2. **BE AUTONOMOUS**: Don't ask questions - search, read, decide, act
8−3. **TEST AFTER CHANGES**: Run tests immediately after each modification
9−4. **BE CONCISE**: Under 4 lines unless user asks for detail
10−5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace
11−6. **NEVER COMMIT**: Unless user explicitly says "commit"
6+1. **READ THE RELEVANT CONTEXT BEFORE EDITING**: Never edit a file you haven't already read the relevant context for in this conversation. Once read, you don't need to re-read unless it changed. Pay close attention to exact formatting, indentation, and whitespace - these must match exactly in your edits.
7+2. **BE AUTONOMOUS**: Don't ask questions - search, read, think, decide, act. Break complex tasks into steps and complete them all. Systematically try alternative strategies (different commands, search terms, tools, refactors, or scopes) until either the task is complete or you hit a hard external limit (missing credentials, permissions, files, or network access you cannot change). Only stop for actual blocking errors, not perceived difficulty.
8+3. **TEST AFTER CHANGES**: Run tests immediately after each modification.
9+4. **BE CONCISE**: Keep output concise (default <4 lines), unless explaining complex changes or asked for detail. Conciseness applies to output only, not to thoroughness of work.
10+5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks.
11+6. **NEVER COMMIT**: Unless user explicitly says "commit". When committing, follow the `<git_commits>` format from the bash tool description exactly, including any configured attribution lines.
12127. **FOLLOW MEMORY FILE INSTRUCTIONS**: If memory files contain specific instructions, preferences, or commands, you MUST follow them.
13−8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so
13+8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so. Focus on *why* not *what*. NEVER communicate with the user through code comments.
14+9. **SECURITY FIRST**: Only assist with defensive security tasks. Refuse to create, modify, or improve code that may be used maliciously.
15+10. **NO URL GUESSING**: Only use URLs provided by the user or found in local files.
16+11. **NEVER PUSH TO REMOTE**: Don't push changes to remote repositories unless explicitly asked.
17+12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.
18+13. **TOOL CONSTRAINTS**: Only use documented tools. Never attempt 'apply_patch' or 'apply_diff' - they don't exist. Use 'edit' or 'multiedit' instead.
19+14. **LOAD MATCHING SKILLS**: If any entry in `<available_skills>` matches the current task, you MUST call `view` on its `<location>` before taking any other action for that task. The `<description>` is only a trigger — the actual procedure, scripts, and references live in SKILL.md. Do NOT infer a skill's behavior from its description or skip loading it because you think you already know how to do the task.
20+15. **LIMIT FILE READS**: Avoid reading entire files, as they can be very large. Read only the sections you need using 'offset' and 'limit' parameters.
1421</critical_rules>
1522
1623<communication_style>
1724Keep responses minimal:
25+- ALWAYS think and respond in the same spoken language the prompt was written in.
1826- Under 4 lines of text (tool use doesn't count)
27+- Conciseness is about **text only**: always fully implement the requested feature, tests, and wiring even if that requires many tool calls.
1928- No preamble ("Here's...", "I'll...")
2029- No postamble ("Let me know...", "Hope this helps...")
2130- One-word answers when possible
2231- No emojis ever
2332- No explanations unless user asks
33+- Never send acknowledgement-only responses; after receiving new context or instructions, immediately continue the task or state the concrete next action you will take.
34+- Use rich Markdown formatting (headings, bullet lists, tables, code fences) for any multi-sentence or explanatory answer; only use plain unformatted text if the user explicitly asks.
2435
2536Examples:
2637user: what is 2+2?
@@ -36,8 +47,17 @@ assistant: src/foo.c
3647user: add error handling to the login function
3748assistant: [searches for login, reads file, edits with exact match, runs tests]
3849Done
50+
51+user: Where are errors from the client handled?
52+assistant: Clients are marked as failed in the `connectToServer` function in src/services/process.go:712.
3953</communication_style>
4054
55+<code_references>
56+When referencing specific functions or code locations, use the pattern `file_path:line_number` to help users navigate:
57+- Example: "The error is handled in src/main.go:45"
58+- Example: "See the implementation in pkg/utils/helper.go:123-145"
59+</code_references>
60+
4161<workflow>
4262For every task, follow this sequence internally (don't narrate it):
4363
@@ -46,15 +66,23 @@ For every task, follow this sequence internally (don't narrate it):
4666- Read files to understand current state
4767- Check memory for stored commands
4868- Identify what needs to change
69+- Use `git log` and `git blame` for additional context when needed
4970
5071**While acting**:
5172- Read entire file before editing it
73+- Before editing: verify exact whitespace and indentation from View output
5274- Use exact text for find/replace (include whitespace)
5375- Make one logical change at a time
5476- After each change: run tests
5577- If tests fail: fix immediately
78+- If edit fails: read more context, don't guess - the text must match exactly
79+- Keep going until query is completely resolved before yielding to user
80+- For longer tasks, send brief progress updates (under 10 words) BUT IMMEDIATELY CONTINUE WORKING - progress updates are not stopping points
5681
5782**Before finishing**:
83+- Verify ENTIRE query is resolved (not just first step)
84+- All described next steps must be completed
85+- Cross-check the original prompt and your own mental checklist; if any feasible part remains undone, continue working instead of responding.
5886- Run lint/typecheck if in memory
5987- Verify all changes work
6088- Keep response under 4 lines
@@ -64,6 +92,8 @@ For every task, follow this sequence internally (don't narrate it):
6492- Follow existing patterns (check similar files)
6593- If stuck, try different approach (don't repeat failures)
6694- Make decisions yourself (search first, don't ask)
95+- Fix problems at root cause, not surface-level patches
96+- Don't fix unrelated bugs or broken tests (mention them in final message if relevant)
6797</workflow>
6898
6999<decision_making>
@@ -73,12 +103,27 @@ For every task, follow this sequence internally (don't narrate it):
73103- Check similar code
74104- Infer from context
75105- Try most likely approach
106+- When requirements are underspecified but not obviously dangerous, make the most reasonable assumptions based on project patterns and memory files, briefly state them if needed, and proceed instead of waiting for clarification.
76107
77−**Only ask user if**:
108+**Only stop/ask user if**:
78109- Truly ambiguous business requirement
79110- Multiple valid approaches with big tradeoffs
80111- Could cause data loss
81−- Exhausted all attempts
112+- Exhausted all attempts and hit actual blocking errors
113+
114+**When requesting information/access**:
115+- Exhaust all available tools, searches, and reasonable assumptions first.
116+- Never say "Need more info" without detail.
117+- In the same message, list each missing item, why it is required, acceptable substitutes, and what you already attempted.
118+- State exactly what you will do once the information arrives so the user knows the next step.
119+
120+When you must stop, first finish all unblocked parts of the request, then clearly report: (a) what you tried, (b) exactly why you are blocked, and (c) the minimal external action required. Don't stop just because one path failed—exhaust multiple plausible approaches first.
121+
122+**Never stop for**:
123+- Task seems too large (break it down)
124+- Multiple files to change (change them)
125+- Concerns about "session limits" (no such limits exist)
126+- Work will take many steps (do all the steps)
82127
83128Examples of autonomous decisions:
84129- File location → search for similar files
@@ -89,43 +134,125 @@ Examples of autonomous decisions:
89134</decision_making>
90135
91136<editing_files>
92−Critical: ALWAYS read files before editing them in this conversation.
137+**Available edit tools:**
138+- `edit` - Single find/replace in a file
139+- `multiedit` - Multiple find/replace operations in one file
140+- `write` - Create/overwrite entire file
141+
142+Never use `apply_patch` or similar - those tools don't exist.
143+
144+Critical: ALWAYS read the relevant context of files before editing them in this conversation.
93145
94146When using edit tools:
95−1. Read the file first
96−2. Find exact text to replace (include indentation/spaces)
97−3. Make replacement unambiguous (enough context)
98−4. Verify edit succeeded
99−5. Run tests
147+1. Read the relevant context first - note the EXACT indentation (spaces vs tabs, count)
148+2. Copy the exact text including ALL whitespace, newlines, and indentation
149+3. Include 3-5 lines of context before and after the target
150+4. Verify your old_string would appear exactly once in the file
151+5. If uncertain about whitespace, include more surrounding context
152+6. Verify edit succeeded
153+7. Run tests
154+
155+**Whitespace matters**:
156+- Count spaces/tabs carefully (use View tool line numbers as reference)
157+- Include blank lines if they exist
158+- Match line endings exactly
159+- When in doubt, include MORE context rather than less
160+
161+Efficiency tips:
162+- Don't re-read files after successful edits (tool will fail if it didn't work)
163+- Same applies for making folders, deleting files, etc.
100164
101165Common mistakes to avoid:
102166- Editing without reading first
103167- Approximate text matches
104−- Wrong indentation
168+- Wrong indentation (spaces vs tabs, wrong count)
169+- Missing or extra blank lines
105170- Not enough context (text appears multiple times)
171+- Trimming whitespace that exists in the original
106172- Not testing after changes
107173</editing_files>
108174
175+<whitespace_and_exact_matching>
176+The Edit tool is extremely literal. "Close enough" will fail.
177+
178+**Before every edit**:
179+1. View the file and locate the exact lines to change
180+2. Copy the text EXACTLY including:
181+ - Every space and tab
182+ - Every blank line
183+ - Opening/closing braces position
184+ - Comment formatting
185+3. Include enough surrounding lines (3-5) to make it unique
186+4. Double-check indentation level matches
187+
188+**Common failures**:
189+- `func foo() {` vs `func foo(){` (space before brace)
190+- Tab vs 4 spaces vs 2 spaces
191+- Missing blank line before/after
192+- `// comment` vs `//comment` (space after //)
193+- Different number of spaces in indentation
194+
195+**If edit fails**:
196+- View the file again at the specific location
197+- Copy even more context
198+- Check for tabs vs spaces
199+- Verify line endings
200+- Try including the entire function/block if needed
201+- Never retry with guessed changes - get the exact text first
202+</whitespace_and_exact_matching>
203+
204+<task_completion>
205+Ensure every task is implemented completely, not partially or sketched.
206+
207+1. **Think before acting** (for non-trivial tasks)
208+ - Identify all components that need changes (models, logic, routes, config, tests, docs)
209+ - Consider edge cases and error paths upfront
210+ - Form a mental checklist of requirements before making the first edit
211+ - This planning happens internally - don't narrate it to the user
212+
213+2. **Implement end-to-end**
214+ - Treat every request as complete work: if adding a feature, wire it fully
215+ - Update all affected files (callers, configs, tests, docs)
216+ - Don't leave TODOs or "you'll also need to..." - do it yourself
217+ - No task is too large - break it down and complete all parts
218+ - For multi-part prompts, treat each bullet/question as a checklist item and ensure every item is implemented or answered. Partial completion is not an acceptable final state.
219+
220+3. **Verify before finishing**
221+ - Re-read the original request and verify each requirement is met
222+ - Check for missing error handling, edge cases, or unwired code
223+ - Run tests to confirm the implementation works
224+ - Only say "Done" when truly done - never stop mid-task
225+</task_completion>
226+
109227<error_handling>
110228When errors occur:
1112291. Read complete error message
112−2. Understand root cause
230+2. Understand root cause (isolate with debug logs or minimal reproduction if needed)
1132313. Try different approach (don't repeat same action)
1142324. Search for similar code that works
1152335. Make targeted fix
1162346. Test to verify
235+7. For each error, attempt at least two or three distinct remediation strategies (search similar code, adjust commands, narrow or widen scope, change approach) before concluding the problem is externally blocked.
117236
118237Common errors:
119238- Import/Module → check paths, spelling, what exists
120239- Syntax → check brackets, indentation, typos
121240- Tests fail → read test, see what it expects
122241- File not found → use ls, check exact path
242+
243+**Edit tool "old_string not found"**:
244+- View the file again at the target location
245+- Copy the EXACT text including all whitespace
246+- Include more surrounding context (full function if needed)
247+- Check for tabs vs spaces, extra/missing blank lines
248+- Count indentation spaces carefully
249+- Don't retry with approximate matches - get the exact text
123250</error_handling>
124251
125252<memory_instructions>
126253Memory files store commands, preferences, and codebase info. Update them when you discover:
127254- Build/test/lint commands
128−- Code style preferences
255+- Code style preferences
129256- Important codebase patterns
130257- Useful project information
131258</memory_instructions>
@@ -137,40 +264,106 @@ Before writing code:
1372643. Match existing style
1382654. Use same libraries/frameworks
1392665. Follow security best practices (never log secrets)
267+6. Don't use one-letter variable names unless requested
140268
141269Never assume libraries are available - verify first.
270+
271+**Ambition vs. precision**:
272+- New projects → be creative and ambitious with implementation
273+- Existing codebases → be surgical and precise, respect surrounding code
274+- Don't change filenames or variables unnecessarily
275+- Don't add formatters/linters/tests to codebases that don't have them
142276</code_conventions>
143277
144278<testing>
145279After significant changes:
280+- Start testing as specific as possible to code changed, then broaden to build confidence
281+- Use self-verification: write unit tests, add output logs, or use debug statements to verify your solutions
146282- Run relevant test suite
147283- If tests fail, fix before continuing
148284- Check memory for test commands
149−- Run lint/typecheck if available
285+- Run lint/typecheck if available (on precise targets when possible)
286+- For formatters: iterate max 3 times to get it right; if still failing, present correct solution and note formatting issue
150287- Suggest adding commands to memory if not found
288+- Don't fix unrelated bugs or test failures (not your responsibility)
151289</testing>
152290
153291<tool_usage>
292+- Default to using tools (ls, grep, view, agent, tests, web_fetch, etc.) rather than speculation whenever they can reduce uncertainty or unlock progress, even if it takes multiple tool calls.
154293- Search before assuming
155294- Read files before editing
295+- Always use absolute paths for file operations (editing, reading, writing)
156296- Use Agent tool for complex searches
157297- Run tools in parallel when safe (no dependencies)
298+- When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution
158299- Summarize tool output for user (they don't see it)
300+- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.
301+- Only use the tools you know exist.
302+
303+<bash_commands>
304+**CRITICAL**: The `description` parameter is REQUIRED for all bash tool calls. Always provide it.
305+
306+When running non-trivial bash commands (especially those that modify the system):
307+- Briefly explain what the command does and why you're running it
308+- This ensures the user understands potentially dangerous operations
309+- Simple read-only commands (ls, cat, etc.) don't need explanation
310+- Use `&` for background processes that won't stop on their own (e.g., `node server.js &`)
311+- Avoid interactive commands - use non-interactive versions (e.g., `npm init -y` not `npm init`)
312+- Combine related commands to save time (e.g., `git status && git diff HEAD && git log -n 3`)
313+</bash_commands>
159314</tool_usage>
160315
161316<proactiveness>
162317Balance autonomy with user intent:
163−- When asked to do something → do it fully (including follow-ups)
318+- When asked to do something → do it fully (including ALL follow-ups and "next steps")
319+- Never describe what you'll do next - just do it
320+- When the user provides new information or clarification, incorporate it immediately and keep executing instead of stopping with an acknowledgement.
321+- Responding with only a plan, outline, or TODO list (or any other purely verbal response) is failure; you must execute the plan via tools whenever execution is possible.
164322- When asked how to approach → explain first, don't auto-implement
165323- After completing work → stop, don't explain (unless asked)
166324- Don't surprise user with unexpected actions
167325</proactiveness>
168326
327+<final_answers>
328+Adapt verbosity to match the work completed:
329+
330+**Default (under 4 lines)**:
331+- Simple questions or single-file changes
332+- Casual conversation, greetings, acknowledgements
333+- One-word answers when possible
334+
335+**More detail allowed (up to 10-15 lines)**:
336+- Large multi-file changes that need walkthrough
337+- Complex refactoring where rationale adds value
338+- Tasks where understanding the approach is important
339+- When mentioning unrelated bugs/issues found
340+- Suggesting logical next steps user might want
341+- Structure longer answers with Markdown sections and lists, and put all code, commands, and config in fenced code blocks.
342+
343+**What to include in verbose answers**:
344+- Brief summary of what was done and why
345+- Key files/functions changed (with `file:line` references)
346+- Any important decisions or tradeoffs made
347+- Next steps or things user should verify
348+- Issues found but not fixed
349+
350+**What to avoid**:
351+- Don't show full file contents unless explicitly asked
352+- Don't explain how to save files or copy code (user has access to your work)
353+- Don't use "Here's what I did" or "Let me know if..." style preambles/postambles
354+- Keep tone direct and factual, like handing off work to a teammate
355+</final_answers>
356+
169357<env>
170358Working directory: {{.WorkingDir}}
171359Is directory a git repo: {{if .IsGitRepo}}yes{{else}}no{{end}}
172360Platform: {{.Platform}}
173361Today's date: {{.Date}}
362+{{if .GitStatus}}
363+
364+Git status (snapshot at conversation start - may be outdated):
365+{{.GitStatus}}
366+{{end}}
174367</env>
175368
176369{{if gt (len .Config.LSP) 0}}
@@ -180,13 +373,48 @@ Diagnostics (lint/typecheck) included in tool output.
180373- Ignore issues in files you didn't touch (unless user asks)
181374</lsp>
182375{{end}}
376+{{- if .AvailSkillXML}}
377+
378+{{.AvailSkillXML}}
379+
380+<skills_usage>
381+The `<description>` of each skill is a TRIGGER — it tells you *when* a skill applies. It is NOT a specification of what the skill does or how to do it. The procedure, scripts, commands, references, and required flags live only in the SKILL.md body. You do not know what a skill actually does until you have read its SKILL.md.
382+
383+MANDATORY activation flow:
384+1. Scan `<available_skills>` against the current user task.
385+2. If any skill's `<description>` matches, call the View tool with its `<location>` EXACTLY as shown — before any other tool call that performs the task.
386+3. Read the entire SKILL.md and follow its instructions.
387+4. Only then execute the task, using the skill's prescribed commands/tools.
388+
389+Do NOT skip step 2 because you think you already know how to do the task. Do NOT infer a skill's behavior from its name or description. If you find yourself about to run `bash`, `edit`, or any task-doing tool for a skill-eligible request without having just viewed the SKILL.md, stop and load the skill first.
390+
391+Builtin skills (type=builtin) use virtual `crush://skills/...` location identifiers. The "crush://" prefix is NOT a URL, network address, or MCP resource — it is a special internal identifier the View tool understands natively. Pass the `<location>` verbatim to View.
392+
393+Do not use MCP tools (including read_mcp_resource) to load skills.
394+If a skill mentions scripts, references, or assets, they live in the same folder as the skill itself (e.g., scripts/, references/, assets/ subdirectories within the skill's folder).
395+</skills_usage>
396+{{end}}
183397
184398{{if .ContextFiles}}
185−<memory>
399+# Project-Specific Context
400+Make sure to follow the instructions in the context below.
401+<project_context>
186402{{range .ContextFiles}}
187403<file path="{{.Path}}">
188404{{.Content}}
189405</file>
190406{{end}}
191−</memory>
407+</project_context>
408+{{end}}
409+{{if .GlobalContextFiles}}
410+
411+# User context
412+The following is personal content added by the user that they'd like you to follow no matter what project you're working in.
413+<user_preferences>
414+{{range .GlobalContextFiles}}
415+<file path="{{.Path}}">
416+{{.Content}}
417+</file>
418+{{end}}
419+</user_preferences>
192420{{end}}
internal/agent/templates/initialize.mddeleted−9
@@ -1,9 +0,0 @@
1−Please analyze this codebase and create a **CRUSH.md** file containing:
2−
3−- Build/lint/test commands - especially for running a single test
4−- Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
5−
6−The file you create will be given to agentic coding agents (such as yourself) that operate in this repository. Make it about 20-30 lines long.
7−If there's already a **CRUSH.md**, improve it.
8−
9−If there are Cursor rules (in `.cursor/rules/` or `.cursorrules`) or Copilot rules (in `.github/copilot-instructions.md`), make sure to include them.
internal/agent/templates/initialize.md.tplnew file+29
@@ -0,0 +1,29 @@
1+Analyze this codebase and create/update **{{.Config.Options.InitializeAs}}** to help future agents work effectively in this repository.
2+
3+**First**: Check if directory is empty or contains only config files. If so, stop and say "Directory appears empty or only contains config. Add source code first, then run this command to generate {{.Config.Options.InitializeAs}}."
4+
5+**Goal**: Document what an agent needs to know to work in this codebase - commands, patterns, conventions, gotchas, overall architecture, how components fit together
6+
7+**Discovery process**:
8+
9+1. Check directory contents with `ls`
10+2. Look for existing rule files (`.cursor/rules/*.md`, `.cursorrules`, `.github/copilot-instructions.md`, `claude.md`, `agents.md`) - only read if they exist
11+3. Identify project type from config files and directory structure
12+4. Find build/test/lint commands from config files, scripts, Makefiles, or CI configs
13+5. Read representative source files to understand code patterns, architecture, control/data flow
14+6. If {{.Config.Options.InitializeAs}} exists, read and improve it
15+
16+**Content to include**:
17+
18+- Essential commands (build, test, run, deploy, etc.) - whatever is relevant for this project
19+- Code organization and structure, application architecture and control/data flow
20+- Naming conventions and style patterns
21+- Testing approach and patterns
22+- Important gotchas or non-obvious patterns
23+- Any project-specific context from existing rule files
24+
25+**Note:** LLM agents learn and adapt to their context as they obtain it, so mentioning obvious details they would immediately pick up from reading a file or two is actively detrimental. Keep the principles of progressive disclosure in mind and focus primarily on non-obvious knowledge that saves the agent from trial-and-error discovery: gotchas, implicit conventions, commands with surprising flags, and context that isn't self-evident from the code in a single file.
26+
27+**Format**: Clear markdown sections. Use your judgment on structure based on what you find. Aim for completeness over brevity - include everything an agent would need to know.
28+
29+**Critical**: Only document what you actually observe. Never invent commands, patterns, or conventions. If you can't find something, don't include it.
internal/agent/templates/summary.md+43−12
@@ -1,17 +1,48 @@
1−You are a helpful AI assistant tasked with summarizing conversations.
1+You are summarizing a conversation to preserve context for continuing work later.
22
3−When asked to summarize, provide a detailed but concise summary of the conversation.
4−Focus on information that would be helpful for continuing the conversation, including:
3+**Critical**: This summary will be the ONLY context available when the conversation resumes. Assume all previous messages will be lost. Be thorough.
54
6−- What was done
7−- What is currently being worked on
8−- Which files are being modified
9−- Helpful commands that helped you implement this task so far
10−- Any context that would be needed to continue working on the task
11−- What needs to be done next
5+**Required sections**:
126
13−Your summary should be comprehensive enough to provide context to be quickly understood.
7+## Current State
148
15−It is very important to keep context of files that are important and strategy you are following.
9+- What task is being worked on (exact user request)
10+- Current progress and what's been completed
11+- What's being worked on right now (incomplete work)
12+- What remains to be done (specific next steps, not vague)
1613
17−It is very important to have the next steps clearly defined.
14+## Files & Changes
15+
16+- Files that were modified (with brief description of changes)
17+- Files that were read/analyzed (why they're relevant)
18+- Key files not yet touched but will need changes
19+- File paths and line numbers for important code locations
20+
21+## Technical Context
22+
23+- Architecture decisions made and why
24+- Patterns being followed (with examples)
25+- Libraries/frameworks being used
26+- Commands that worked (exact commands with context)
27+- Commands that failed (what was tried and why it didn't work)
28+- Environment details (language versions, dependencies, etc.)
29+
30+## Strategy & Approach
31+
32+- Overall approach being taken
33+- Why this approach was chosen over alternatives
34+- Key insights or gotchas discovered
35+- Assumptions made
36+- Any blockers or risks identified
37+
38+## Exact Next Steps
39+
40+Be specific. Don't write "implement authentication" - write:
41+
42+1. Add JWT middleware to src/middleware/auth.js:15
43+2. Update login handler in src/routes/user.js:45 to return token
44+3. Test with: npm test -- auth.test.js
45+
46+**Tone**: Write as if briefing a teammate taking over mid-task. Include everything they'd need to continue without asking questions. No emojis ever.
47+
48+**Length**: No limit. Err on the side of too much detail rather than too little. Critical context is worth the tokens.
internal/agent/templates/title.md+8−7
@@ -1,10 +1,11 @@
1−you will generate a short title based on the first message a user begins a conversation with
1+You will generate a short title based on the first message a user begins a conversation with.
22
33<rules>
4−- ensure it is not more than 50 characters long
5−- the title should be a summary of the user's message
6−- it should be one line long
7−- do not use quotes or colons
8−- the entire text you return will be used as the title
9−- never return anything that is more than one sentence (one line) long
4+- Keep the title in the same language that the user wrote their message in.
5+- Ensure it is not more than 50 characters long.
6+- The title should be a summary of the user's message.
7+- It should be one line long.
8+- Do not use quotes or colons.
9+- The entire text you return will be used as the title.
10+- Never return anything that is more than one sentence (one line) long.
1011</rules>
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/bash_tool.yamldeleted−204
@@ -1,204 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 774
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nuse bash to create a file named test.txt with content ''hello bash''\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_0134NcQsuCWiH9G2f1pFdbjd","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":147,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Bash File"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Creation"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" with"} }
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Hello Message"} }
47−
48− event: content_block_stop
49− data: {"type":"content_block_stop","index":0 }
50−
51− event: message_delta
52− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":147,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":10} }
53−
54− event: message_stop
55− data: {"type":"message_stop" }
56−
57− headers:
58− Content-Type:
59− - text/event-stream; charset=utf-8
60− status: 200 OK
61− code: 200
62− duration: 580.862ms
63−- id: 1
64− request:
65− proto: HTTP/1.1
66− proto_major: 1
67− proto_minor: 1
68− content_length: 32080
69− host: ""
70− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use bash to create a file named test.txt with content 'hello bash'\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/bash_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
71− headers:
72− Accept:
73− - application/json
74− Content-Type:
75− - application/json
76− User-Agent:
77− - Anthropic/Go 1.12.0
78− url: https://api.anthropic.com/v1/messages
79− method: POST
80− response:
81− proto: HTTP/2.0
82− proto_major: 2
83− proto_minor: 0
84− content_length: -1
85− body: |+
86− event: message_start
87− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_014HBZ4z2bf13yA4JhmVnxwF","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1807,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1807,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
88−
89− event: content_block_start
90− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01YBoqWcXiuoc1fZf4muKFXn","name":"bash","input":{}} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""}}
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"com"} }
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"mand"} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\": \"echo 'h"} }
103−
104− event: content_block_delta
105− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ello bas"} }
106−
107− event: content_block_delta
108− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"h'"} }
109−
110− event: content_block_delta
111− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":" > te"} }
112−
113− event: content_block_delta
114− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"st.txt\""} }
115−
116− event: content_block_delta
117− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":", \"descript"} }
118−
119− event: content_block_delta
120− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ion\": \"C"} }
121−
122− event: content_block_delta
123− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"reat"} }
124−
125− event: content_block_delta
126− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"e tes"} }
127−
128− event: content_block_delta
129− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"t.txt with"} }
130−
131− event: content_block_delta
132− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":" content 'h"} }
133−
134− event: content_block_delta
135− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"el"} }
136−
137− event: content_block_delta
138− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"lo bash'\"}"} }
139−
140− event: content_block_stop
141− data: {"type":"content_block_stop","index":0 }
142−
143− event: message_delta
144− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1807,"cache_read_input_tokens":6853,"output_tokens":87} }
145−
146− event: message_stop
147− data: {"type":"message_stop" }
148−
149− headers:
150− Content-Type:
151− - text/event-stream; charset=utf-8
152− status: 200 OK
153− code: 200
154− duration: 2.250892459s
155−- id: 2
156− request:
157− proto: HTTP/1.1
158− proto_major: 1
159− proto_minor: 1
160− content_length: 32481
161− host: ""
162− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use bash to create a file named test.txt with content 'hello bash'\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_01YBoqWcXiuoc1fZf4muKFXn\",\"input\":{\"command\":\"echo 'hello bash' \\u003e test.txt\",\"description\":\"Create test.txt with content 'hello bash'\"},\"name\":\"bash\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01YBoqWcXiuoc1fZf4muKFXn\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"no output\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/bash_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
163− headers:
164− Accept:
165− - application/json
166− Content-Type:
167− - application/json
168− User-Agent:
169− - Anthropic/Go 1.12.0
170− url: https://api.anthropic.com/v1/messages
171− method: POST
172− response:
173− proto: HTTP/2.0
174− proto_major: 2
175− proto_minor: 0
176− content_length: -1
177− body: |+
178− event: message_start
179− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01VhFdZK9M9rh9iPzGkdoG1R","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":99,"cache_read_input_tokens":8660,"cache_creation":{"ephemeral_5m_input_tokens":99,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
180−
181− event: content_block_start
182− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
183−
184− event: content_block_delta
185− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"File"} }
186−
187− event: content_block_delta
188− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" created successfully."} }
189−
190− event: content_block_stop
191− data: {"type":"content_block_stop","index":0 }
192−
193− event: message_delta
194− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":99,"cache_read_input_tokens":8660,"output_tokens":7} }
195−
196− event: message_stop
197− data: {"type":"message_stop" }
198−
199− headers:
200− Content-Type:
201− - text/event-stream; charset=utf-8
202− status: 200 OK
203− code: 200
204− duration: 2.466855833s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/download_tool.yamldeleted−227
@@ -1,227 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 787
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\ndownload the file from https://httpbin.org/robots.txt and save it as robots.txt\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01HgEdLNNxYjaZP4qdjC1kgA","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":151,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Downloa"}}
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d robots"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":".txt from http"} }
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"bin.org"} }
47−
48− event: content_block_stop
49− data: {"type":"content_block_stop","index":0 }
50−
51− event: message_delta
52− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":151,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":12} }
53−
54− event: message_stop
55− data: {"type":"message_stop" }
56−
57− headers:
58− Content-Type:
59− - text/event-stream; charset=utf-8
60− status: 200 OK
61− code: 200
62− duration: 538.064375ms
63−- id: 1
64− request:
65− proto: HTTP/1.1
66− proto_major: 1
67− proto_minor: 1
68− content_length: 32097
69− host: ""
70− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"download the file from https://httpbin.org/robots.txt and save it as robots.txt\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/download_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
71− headers:
72− Accept:
73− - application/json
74− Content-Type:
75− - application/json
76− User-Agent:
77− - Anthropic/Go 1.12.0
78− url: https://api.anthropic.com/v1/messages
79− method: POST
80− response:
81− proto: HTTP/2.0
82− proto_major: 2
83− proto_minor: 0
84− content_length: -1
85− body: |+
86− event: message_start
87− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_019KcWmqSk79v6LJf1bza4q3","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1811,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1811,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
88−
89− event: content_block_start
90− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01TQRnNYg7te6aMms1MBRHL8","name":"download","input":{}} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"u"} }
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"rl\": \"https:"} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"//httpbin."}}
103−
104− event: content_block_delta
105− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"org/robots."} }
106−
107− event: content_block_delta
108− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"txt\""} }
109−
110− event: content_block_delta
111− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":", \"file_pat"} }
112−
113− event: content_block_delta
114− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"h\": \"rob"} }
115−
116− event: content_block_delta
117− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ots.tx"} }
118−
119− event: content_block_delta
120− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"t\"}"} }
121−
122− event: content_block_stop
123− data: {"type":"content_block_stop","index":0 }
124−
125− event: message_delta
126− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1811,"cache_read_input_tokens":6853,"output_tokens":81} }
127−
128− event: message_stop
129− data: {"type":"message_stop" }
130−
131− headers:
132− Content-Type:
133− - text/event-stream; charset=utf-8
134− status: 200 OK
135− code: 200
136− duration: 2.481377833s
137−- id: 2
138− request:
139− proto: HTTP/1.1
140− proto_major: 1
141− proto_minor: 1
142− content_length: 0
143− host: httpbin.org
144− headers:
145− User-Agent:
146− - crush/1.0
147− url: https://httpbin.org/robots.txt
148− method: GET
149− response:
150− proto: HTTP/2.0
151− proto_major: 2
152− proto_minor: 0
153− content_length: 30
154− body: |
155− User-agent: *
156− Disallow: /deny
157− headers:
158− Content-Type:
159− - text/plain
160− status: 200 OK
161− code: 200
162− duration: 1.07370375s
163−- id: 3
164− request:
165− proto: HTTP/1.1
166− proto_major: 1
167− proto_minor: 1
168− content_length: 32588
169− host: ""
170− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"download the file from https://httpbin.org/robots.txt and save it as robots.txt\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_01TQRnNYg7te6aMms1MBRHL8\",\"input\":{\"file_path\":\"robots.txt\",\"url\":\"https://httpbin.org/robots.txt\"},\"name\":\"download\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01TQRnNYg7te6aMms1MBRHL8\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"Successfully downloaded 30 bytes to /tmp/crush-test/TestCoderAgent/anthropic-sonnet/download_tool/robots.txt (Content-Type: text/plain)\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/download_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
171− headers:
172− Accept:
173− - application/json
174− Content-Type:
175− - application/json
176− User-Agent:
177− - Anthropic/Go 1.12.0
178− url: https://api.anthropic.com/v1/messages
179− method: POST
180− response:
181− proto: HTTP/2.0
182− proto_major: 2
183− proto_minor: 0
184− content_length: -1
185− body: |+
186− event: message_start
187− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01HaRYTipxH4buqTj1ojHLri","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":5,"cache_creation_input_tokens":132,"cache_read_input_tokens":8664,"cache_creation":{"ephemeral_5m_input_tokens":132,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
188−
189− event: content_block_start
190− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
191−
192− event: content_block_delta
193− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Done"} }
194−
195− event: content_block_delta
196− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":". Downloaded 30 bytes to `"} }
197−
198− event: ping
199− data: {"type": "ping"}
200−
201− event: content_block_delta
202− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"robots.txt`."} }
203−
204− event: ping
205− data: {"type": "ping"}
206−
207− event: content_block_stop
208− data: {"type":"content_block_stop","index":0 }
209−
210− event: ping
211− data: {"type": "ping"}
212−
213− event: ping
214− data: {"type": "ping"}
215−
216− event: message_delta
217− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":5,"cache_creation_input_tokens":132,"cache_read_input_tokens":8664,"output_tokens":16} }
218−
219− event: message_stop
220− data: {"type":"message_stop" }
221−
222− headers:
223− Content-Type:
224− - text/event-stream; charset=utf-8
225− status: 200 OK
226− code: 200
227− duration: 2.018951292s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/fetch_tool.yamldeleted−245
@@ -1,245 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 800
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nfetch the content from https://httpbin.org/html and tell me if it contains the word ''Herman''\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01FxSVzNELCauTsk6fSTg87j","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":154,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Web"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Scraping Content"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for"} }
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Specific"} }
47−
48− event: content_block_delta
49− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Wor"} }
50−
51− event: content_block_delta
52− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d"}}
53−
54− event: content_block_stop
55− data: {"type":"content_block_stop","index":0 }
56−
57− event: message_delta
58− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":154,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":12} }
59−
60− event: message_stop
61− data: {"type":"message_stop" }
62−
63− headers:
64− Content-Type:
65− - text/event-stream; charset=utf-8
66− status: 200 OK
67− code: 200
68− duration: 555.344458ms
69−- id: 1
70− request:
71− proto: HTTP/1.1
72− proto_major: 1
73− proto_minor: 1
74− content_length: 32107
75− host: ""
76− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"fetch the content from https://httpbin.org/html and tell me if it contains the word 'Herman'\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/fetch_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
77− headers:
78− Accept:
79− - application/json
80− Content-Type:
81− - application/json
82− User-Agent:
83− - Anthropic/Go 1.12.0
84− url: https://api.anthropic.com/v1/messages
85− method: POST
86− response:
87− proto: HTTP/2.0
88− proto_major: 2
89− proto_minor: 0
90− content_length: -1
91− body: |+
92− event: message_start
93− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01SiShydSKVnKzai3nv14vyP","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1814,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1814,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}}
94−
95− event: content_block_start
96− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01GWL89Gxjkj9y4Eg5VDVbty","name":"fetch","input":{}} }
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"url"} }
103−
104− event: content_block_delta
105− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\":"} }
106−
107− event: content_block_delta
108− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":" \"https"} }
109−
110− event: content_block_delta
111− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"://ht"} }
112−
113− event: content_block_delta
114− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"tpbi"} }
115−
116− event: content_block_delta
117− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"n.or"} }
118−
119− event: content_block_delta
120− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"g/h"} }
121−
122− event: content_block_delta
123− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"tml\""} }
124−
125− event: content_block_delta
126− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":", "} }
127−
128− event: content_block_delta
129− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\"format\":"} }
130−
131− event: content_block_delta
132− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":" \"tex"} }
133−
134− event: content_block_delta
135− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"t\"}"} }
136−
137− event: content_block_stop
138− data: {"type":"content_block_stop","index":0 }
139−
140− event: message_delta
141− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1814,"cache_read_input_tokens":6853,"output_tokens":75} }
142−
143− event: message_stop
144− data: {"type":"message_stop" }
145−
146− headers:
147− Content-Type:
148− - text/event-stream; charset=utf-8
149− status: 200 OK
150− code: 200
151− duration: 2.398155292s
152−- id: 2
153− request:
154− proto: HTTP/1.1
155− proto_major: 1
156− proto_minor: 1
157− content_length: 0
158− host: httpbin.org
159− headers:
160− User-Agent:
161− - crush/1.0
162− url: https://httpbin.org/html
163− method: GET
164− response:
165− proto: HTTP/2.0
166− proto_major: 2
167− proto_minor: 0
168− content_length: 3741
169− body: |-
170− <!DOCTYPE html>
171− <html>
172− <head>
173− </head>
174− <body>
175− <h1>Herman Melville - Moby-Dick</h1>
176−
177− <div>
178− <p>
179− Availing himself of the mild, summer-cool weather that now reigned in these latitudes, and in preparation for the peculiarly active pursuits shortly to be anticipated, Perth, the begrimed, blistered old blacksmith, had not removed his portable forge to the hold again, after concluding his contributory work for Ahab's leg, but still retained it on deck, fast lashed to ringbolts by the foremast; being now almost incessantly invoked by the headsmen, and harpooneers, and bowsmen to do some little job for them; altering, or repairing, or new shaping their various weapons and boat furniture. Often he would be surrounded by an eager circle, all waiting to be served; holding boat-spades, pike-heads, harpoons, and lances, and jealously watching his every sooty movement, as he toiled. Nevertheless, this old man's was a patient hammer wielded by a patient arm. No murmur, no impatience, no petulance did come from him. Silent, slow, and solemn; bowing over still further his chronically broken back, he toiled away, as if toil were life itself, and the heavy beating of his hammer the heavy beating of his heart. And so it was.—Most miserable! A peculiar walk in this old man, a certain slight but painful appearing yawing in his gait, had at an early period of the voyage excited the curiosity of the mariners. And to the importunity of their persisted questionings he had finally given in; and so it came to pass that every one now knew the shameful story of his wretched fate. Belated, and not innocently, one bitter winter's midnight, on the road running between two country towns, the blacksmith half-stupidly felt the deadly numbness stealing over him, and sought refuge in a leaning, dilapidated barn. The issue was, the loss of the extremities of both feet. Out of this revelation, part by part, at last came out the four acts of the gladness, and the one long, and as yet uncatastrophied fifth act of the grief of his life's drama. He was an old man, who, at the age of nearly sixty, had postponedly encountered that thing in sorrow's technicals called ruin. He had been an artisan of famed excellence, and with plenty to do; owned a house and garden; embraced a youthful, daughter-like, loving wife, and three blithe, ruddy children; every Sunday went to a cheerful-looking church, planted in a grove. But one night, under cover of darkness, and further concealed in a most cunning disguisement, a desperate burglar slid into his happy home, and robbed them all of everything. And darker yet to tell, the blacksmith himself did ignorantly conduct this burglar into his family's heart. It was the Bottle Conjuror! Upon the opening of that fatal cork, forth flew the fiend, and shrivelled up his home. Now, for prudent, most wise, and economic reasons, the blacksmith's shop was in the basement of his dwelling, but with a separate entrance to it; so that always had the young and loving healthy wife listened with no unhappy nervousness, but with vigorous pleasure, to the stout ringing of her young-armed old husband's hammer; whose reverberations, muffled by passing through the floors and walls, came up to her, not unsweetly, in her nursery; and so, to stout Labor's iron lullaby, the blacksmith's infants were rocked to slumber. Oh, woe on woe! Oh, Death, why canst thou not sometimes be timely? Hadst thou taken this old blacksmith to thyself ere his full ruin came upon him, then had the young widow had a delicious grief, and her orphans a truly venerable, legendary sire to dream of in their after years; and all of them a care-killing competency.
180− </p>
181− </div>
182− </body>
183− </html>
184− headers:
185− Content-Type:
186− - text/html; charset=utf-8
187− status: 200 OK
188− code: 200
189− duration: 461.971291ms
190−- id: 3
191− request:
192− proto: HTTP/1.1
193− proto_major: 1
194− proto_minor: 1
195− content_length: 36041
196− host: ""
197− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"fetch the content from https://httpbin.org/html and tell me if it contains the word 'Herman'\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_01GWL89Gxjkj9y4Eg5VDVbty\",\"input\":{\"format\":\"text\",\"url\":\"https://httpbin.org/html\"},\"name\":\"fetch\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01GWL89Gxjkj9y4Eg5VDVbty\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"Herman Melville - Moby-Dick Availing himself of the mild, summer-cool weather that now reigned in these latitudes, and in preparation for the peculiarly active pursuits shortly to be anticipated, Perth, the begrimed, blistered old blacksmith, had not removed his portable forge to the hold again, after concluding his contributory work for Ahab's leg, but still retained it on deck, fast lashed to ringbolts by the foremast; being now almost incessantly invoked by the headsmen, and harpooneers, and bowsmen to do some little job for them; altering, or repairing, or new shaping their various weapons and boat furniture. Often he would be surrounded by an eager circle, all waiting to be served; holding boat-spades, pike-heads, harpoons, and lances, and jealously watching his every sooty movement, as he toiled. Nevertheless, this old man's was a patient hammer wielded by a patient arm. No murmur, no impatience, no petulance did come from him. Silent, slow, and solemn; bowing over still further his chronically broken back, he toiled away, as if toil were life itself, and the heavy beating of his hammer the heavy beating of his heart. And so it was.—Most miserable! A peculiar walk in this old man, a certain slight but painful appearing yawing in his gait, had at an early period of the voyage excited the curiosity of the mariners. And to the importunity of their persisted questionings he had finally given in; and so it came to pass that every one now knew the shameful story of his wretched fate. Belated, and not innocently, one bitter winter's midnight, on the road running between two country towns, the blacksmith half-stupidly felt the deadly numbness stealing over him, and sought refuge in a leaning, dilapidated barn. The issue was, the loss of the extremities of both feet. Out of this revelation, part by part, at last came out the four acts of the gladness, and the one long, and as yet uncatastrophied fifth act of the grief of his life's drama. He was an old man, who, at the age of nearly sixty, had postponedly encountered that thing in sorrow's technicals called ruin. He had been an artisan of famed excellence, and with plenty to do; owned a house and garden; embraced a youthful, daughter-like, loving wife, and three blithe, ruddy children; every Sunday went to a cheerful-looking church, planted in a grove. But one night, under cover of darkness, and further concealed in a most cunning disguisement, a desperate burglar slid into his happy home, and robbed them all of everything. And darker yet to tell, the blacksmith himself did ignorantly conduct this burglar into his family's heart. It was the Bottle Conjuror! Upon the opening of that fatal cork, forth flew the fiend, and shrivelled up his home. Now, for prudent, most wise, and economic reasons, the blacksmith's shop was in the basement of his dwelling, but with a separate entrance to it; so that always had the young and loving healthy wife listened with no unhappy nervousness, but with vigorous pleasure, to the stout ringing of her young-armed old husband's hammer; whose reverberations, muffled by passing through the floors and walls, came up to her, not unsweetly, in her nursery; and so, to stout Labor's iron lullaby, the blacksmith's infants were rocked to slumber. Oh, woe on woe! Oh, Death, why canst thou not sometimes be timely? Hadst thou taken this old blacksmith to thyself ere his full ruin came upon him, then had the young widow had a delicious grief, and her orphans a truly venerable, legendary sire to dream of in their after years; and all of them a care-killing competency.\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/fetch_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
198− headers:
199− Accept:
200− - application/json
201− Content-Type:
202− - application/json
203− User-Agent:
204− - Anthropic/Go 1.12.0
205− url: https://api.anthropic.com/v1/messages
206− method: POST
207− response:
208− proto: HTTP/2.0
209− proto_major: 2
210− proto_minor: 0
211− content_length: -1
212− body: |+
213− event: message_start
214− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_013boRMcJ6WXTJLGeihTDTQn","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":5,"cache_creation_input_tokens":980,"cache_read_input_tokens":8667,"cache_creation":{"ephemeral_5m_input_tokens":980,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
215−
216− event: content_block_start
217− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
218−
219− event: content_block_delta
220− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Yes"} }
221−
222− event: content_block_delta
223− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":", it contains \"Herman\" (Herman"} }
224−
225− event: ping
226− data: {"type": "ping"}
227−
228− event: content_block_delta
229− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Melville) in the first line."} }
230−
231− event: content_block_stop
232− data: {"type":"content_block_stop","index":0 }
233−
234− event: message_delta
235− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":5,"cache_creation_input_tokens":980,"cache_read_input_tokens":8667,"output_tokens":21} }
236−
237− event: message_stop
238− data: {"type":"message_stop" }
239−
240− headers:
241− Content-Type:
242− - text/event-stream; charset=utf-8
243− status: 200 OK
244− code: 200
245− duration: 2.482454875s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/glob_tool.yamldeleted−168
@@ -1,168 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 763
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nuse glob to find all .go files in the current directory\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01FXonqh4CRaskWcSFpTBVeC","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":142,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Finding"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Go"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Files with"}}
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Glob"} }
47−
48− event: content_block_stop
49− data: {"type":"content_block_stop","index":0 }
50−
51− event: message_delta
52− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":142,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":9} }
53−
54− event: message_stop
55− data: {"type":"message_stop" }
56−
57− headers:
58− Content-Type:
59− - text/event-stream; charset=utf-8
60− status: 200 OK
61− code: 200
62− duration: 550.481417ms
63−- id: 1
64− request:
65− proto: HTTP/1.1
66− proto_major: 1
67− proto_minor: 1
68− content_length: 32069
69− host: ""
70− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use glob to find all .go files in the current directory\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/glob_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
71− headers:
72− Accept:
73− - application/json
74− Content-Type:
75− - application/json
76− User-Agent:
77− - Anthropic/Go 1.12.0
78− url: https://api.anthropic.com/v1/messages
79− method: POST
80− response:
81− proto: HTTP/2.0
82− proto_major: 2
83− proto_minor: 0
84− content_length: -1
85− body: |+
86− event: message_start
87− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_015aAoWx6ygTpFGHtvfoYkez","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1802,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1802,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
88−
89− event: content_block_start
90− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01CiThu8c8L9DgtKyE1RwQbU","name":"glob","input":{}} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"patt"} }
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ern\": \"*"} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":".go\"}"} }
103−
104− event: content_block_stop
105− data: {"type":"content_block_stop","index":0 }
106−
107− event: message_delta
108− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1802,"cache_read_input_tokens":6853,"output_tokens":52} }
109−
110− event: message_stop
111− data: {"type":"message_stop" }
112−
113− headers:
114− Content-Type:
115− - text/event-stream; charset=utf-8
116− status: 200 OK
117− code: 200
118− duration: 2.538935s
119−- id: 2
120− request:
121− proto: HTTP/1.1
122− proto_major: 1
123− proto_minor: 1
124− content_length: 32439
125− host: ""
126− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use glob to find all .go files in the current directory\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_01CiThu8c8L9DgtKyE1RwQbU\",\"input\":{\"pattern\":\"*.go\"},\"name\":\"glob\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01CiThu8c8L9DgtKyE1RwQbU\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"/tmp/crush-test/TestCoderAgent/anthropic-sonnet/glob_tool/main.go\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/glob_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
127− headers:
128− Accept:
129− - application/json
130− Content-Type:
131− - application/json
132− User-Agent:
133− - Anthropic/Go 1.12.0
134− url: https://api.anthropic.com/v1/messages
135− method: POST
136− response:
137− proto: HTTP/2.0
138− proto_major: 2
139− proto_minor: 0
140− content_length: -1
141− body: |+
142− event: message_start
143− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01VogCUV3zi9sLYPDKeEq64p","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":86,"cache_read_input_tokens":8655,"cache_creation":{"ephemeral_5m_input_tokens":86,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
144−
145− event: content_block_start
146− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
147−
148− event: content_block_delta
149− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"`"} }
150−
151− event: content_block_delta
152− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"main.go`"} }
153−
154− event: content_block_stop
155− data: {"type":"content_block_stop","index":0 }
156−
157− event: message_delta
158− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":86,"cache_read_input_tokens":8655,"output_tokens":8} }
159−
160− event: message_stop
161− data: {"type":"message_stop" }
162−
163− headers:
164− Content-Type:
165− - text/event-stream; charset=utf-8
166− status: 200 OK
167− code: 200
168− duration: 2.1703915s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/grep_tool.yamldeleted−183
@@ -1,183 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 761
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nuse grep to search for the word ''package'' in go files\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_012JHSdafaYGKa7doAmoqq17","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":144,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Searching"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for "} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"'package' in Go"} }
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" files with"} }
47−
48− event: content_block_delta
49− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" grep"} }
50−
51− event: content_block_stop
52− data: {"type":"content_block_stop","index":0 }
53−
54− event: message_delta
55− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":144,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":15} }
56−
57− event: message_stop
58− data: {"type":"message_stop" }
59−
60− headers:
61− Content-Type:
62− - text/event-stream; charset=utf-8
63− status: 200 OK
64− code: 200
65− duration: 592.433333ms
66−- id: 1
67− request:
68− proto: HTTP/1.1
69− proto_major: 1
70− proto_minor: 1
71− content_length: 32067
72− host: ""
73− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use grep to search for the word 'package' in go files\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/grep_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
74− headers:
75− Accept:
76− - application/json
77− Content-Type:
78− - application/json
79− User-Agent:
80− - Anthropic/Go 1.12.0
81− url: https://api.anthropic.com/v1/messages
82− method: POST
83− response:
84− proto: HTTP/2.0
85− proto_major: 2
86− proto_minor: 0
87− content_length: -1
88− body: |+
89− event: message_start
90− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01T85q5no8RwmV56PJA7PFXc","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1804,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1804,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
91−
92− event: content_block_start
93− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01BpVu9fuTSX8GtfcFtF4B5i","name":"grep","input":{}} }
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"patter"} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"n\": \"packag"} }
103−
104− event: content_block_delta
105− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"e\""} }
106−
107− event: content_block_delta
108− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":", \"include\":"} }
109−
110− event: content_block_delta
111− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":" \"*.go\"}"} }
112−
113− event: content_block_stop
114− data: {"type":"content_block_stop","index":0 }
115−
116− event: message_delta
117− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1804,"cache_read_input_tokens":6853,"output_tokens":69} }
118−
119− event: message_stop
120− data: {"type":"message_stop" }
121−
122− headers:
123− Content-Type:
124− - text/event-stream; charset=utf-8
125− status: 200 OK
126− code: 200
127− duration: 2.190177334s
128−- id: 2
129− request:
130− proto: HTTP/1.1
131− proto_major: 1
132− proto_minor: 1
133− content_length: 32501
134− host: ""
135− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use grep to search for the word 'package' in go files\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_01BpVu9fuTSX8GtfcFtF4B5i\",\"input\":{\"include\":\"*.go\",\"pattern\":\"package\"},\"name\":\"grep\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01BpVu9fuTSX8GtfcFtF4B5i\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"Found 1 matches\\n/tmp/crush-test/TestCoderAgent/anthropic-sonnet/grep_tool/main.go:\\n Line 1: package main\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/grep_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
136− headers:
137− Accept:
138− - application/json
139− Content-Type:
140− - application/json
141− User-Agent:
142− - Anthropic/Go 1.12.0
143− url: https://api.anthropic.com/v1/messages
144− method: POST
145− response:
146− proto: HTTP/2.0
147− proto_major: 2
148− proto_minor: 0
149− content_length: -1
150− body: |+
151− event: message_start
152− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01FAo1UdYq7G9CPG6q95Yrya","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":120,"cache_read_input_tokens":8657,"cache_creation":{"ephemeral_5m_input_tokens":120,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
153−
154− event: content_block_start
155− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
156−
157− event: content_block_delta
158− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Foun"} }
159−
160− event: content_block_delta
161− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d 1 match in `main"} }
162−
163− event: ping
164− data: {"type": "ping"}
165−
166− event: content_block_delta
167− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":".go` at line 1."} }
168−
169− event: content_block_stop
170− data: {"type":"content_block_stop","index":0 }
171−
172− event: message_delta
173− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":120,"cache_read_input_tokens":8657,"output_tokens":19} }
174−
175− event: message_stop
176− data: {"type":"message_stop" }
177−
178− headers:
179− Content-Type:
180− - text/event-stream; charset=utf-8
181− status: 200 OK
182− code: 200
183− duration: 1.973956917s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/ls_tool.yamldeleted−174
@@ -1,174 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 757
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nuse ls to list the files in the current directory\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01WsuD73Q7FNCwhY6r9yesAF","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":140,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"List"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Files"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" in"} }
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Current Directory"} }
47−
48− event: content_block_stop
49− data: {"type":"content_block_stop","index":0 }
50−
51− event: message_delta
52− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":140,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":8} }
53−
54− event: message_stop
55− data: {"type":"message_stop" }
56−
57− headers:
58− Content-Type:
59− - text/event-stream; charset=utf-8
60− status: 200 OK
61− code: 200
62− duration: 508.105833ms
63−- id: 1
64− request:
65− proto: HTTP/1.1
66− proto_major: 1
67− proto_minor: 1
68− content_length: 32061
69− host: ""
70− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use ls to list the files in the current directory\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/ls_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
71− headers:
72− Accept:
73− - application/json
74− Content-Type:
75− - application/json
76− User-Agent:
77− - Anthropic/Go 1.12.0
78− url: https://api.anthropic.com/v1/messages
79− method: POST
80− response:
81− proto: HTTP/2.0
82− proto_major: 2
83− proto_minor: 0
84− content_length: -1
85− body: |+
86− event: message_start
87− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01EQmDNVC4ukLghSgfd5NSuj","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1800,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1800,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
88−
89− event: content_block_start
90− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_014cpfm3Fz4JYkeqR2cjbpNm","name":"ls","input":{}} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"path\":"}}
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":" \".\"}"} }
100−
101− event: content_block_stop
102− data: {"type":"content_block_stop","index":0 }
103−
104− event: message_delta
105− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1800,"cache_read_input_tokens":6853,"output_tokens":50} }
106−
107− event: message_stop
108− data: {"type":"message_stop" }
109−
110− headers:
111− Content-Type:
112− - text/event-stream; charset=utf-8
113− status: 200 OK
114− code: 200
115− duration: 2.599475s
116−- id: 2
117− request:
118− proto: HTTP/1.1
119− proto_major: 1
120− proto_minor: 1
121− content_length: 32445
122− host: ""
123− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use ls to list the files in the current directory\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_014cpfm3Fz4JYkeqR2cjbpNm\",\"input\":{\"path\":\".\"},\"name\":\"ls\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_014cpfm3Fz4JYkeqR2cjbpNm\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"\\n- /tmp/crush-test/TestCoderAgent/anthropic-sonnet/ls_tool/\\n - go.mod\\n - main.go\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/ls_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
124− headers:
125− Accept:
126− - application/json
127− Content-Type:
128− - application/json
129− User-Agent:
130− - Anthropic/Go 1.12.0
131− url: https://api.anthropic.com/v1/messages
132− method: POST
133− response:
134− proto: HTTP/2.0
135− proto_major: 2
136− proto_minor: 0
137− content_length: -1
138− body: |+
139− event: message_start
140− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01HYUPtHYzevgHi9AXRzhzaM","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":97,"cache_read_input_tokens":8653,"cache_creation":{"ephemeral_5m_input_tokens":97,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
141−
142− event: content_block_start
143− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
144−
145− event: content_block_delta
146− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"```"}}
147−
148− event: content_block_delta
149− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"\ngo.mod\nmain.go\n```"} }
150−
151− event: ping
152− data: {"type": "ping"}
153−
154− event: content_block_stop
155− data: {"type":"content_block_stop","index":0 }
156−
157− event: ping
158− data: {"type": "ping"}
159−
160− event: ping
161− data: {"type": "ping"}
162−
163− event: message_delta
164− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":97,"cache_read_input_tokens":8653,"output_tokens":14} }
165−
166− event: message_stop
167− data: {"type":"message_stop" }
168−
169− headers:
170− Content-Type:
171− - text/event-stream; charset=utf-8
172− status: 200 OK
173− code: 200
174− duration: 2.239520333s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/multiedit_tool.yamldeleted−314
@@ -1,314 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 836
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nuse multiedit to change ''Hello, World!'' to ''Hello, Crush!'' and add a comment ''// Greeting'' above the fmt.Println line in main.go\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_012wZCQZFhzqRTZZ7xbNXT9P","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":170,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Modify"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Greeting in"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" main.go File"} }
44−
45− event: content_block_stop
46− data: {"type":"content_block_stop","index":0 }
47−
48− event: message_delta
49− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":170,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":12} }
50−
51− event: message_stop
52− data: {"type":"message_stop" }
53−
54− headers:
55− Content-Type:
56− - text/event-stream; charset=utf-8
57− status: 200 OK
58− code: 200
59− duration: 593.423917ms
60−- id: 1
61− request:
62− proto: HTTP/1.1
63− proto_major: 1
64− proto_minor: 1
65− content_length: 32147
66− host: ""
67− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use multiedit to change 'Hello, World!' to 'Hello, Crush!' and add a comment '// Greeting' above the fmt.Println line in main.go\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/multiedit_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
68− headers:
69− Accept:
70− - application/json
71− Content-Type:
72− - application/json
73− User-Agent:
74− - Anthropic/Go 1.12.0
75− url: https://api.anthropic.com/v1/messages
76− method: POST
77− response:
78− proto: HTTP/2.0
79− proto_major: 2
80− proto_minor: 0
81− content_length: -1
82− body: |+
83− event: message_start
84− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01TY1ypWiFAWPQkRLEmEo4Tt","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1832,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1832,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard"}} }
85−
86− event: content_block_start
87− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
88−
89− event: content_block_delta
90− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"I'll first"} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" check the content of main.go, then use mult"} }
94−
95− event: ping
96− data: {"type": "ping"}
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"iedit to make both changes."} }
100−
101− event: content_block_stop
102− data: {"type":"content_block_stop","index":0 }
103−
104− event: content_block_start
105− data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_01EkVHzmaPGJju2LRYbGM3gJ","name":"view","input":{}} }
106−
107− event: content_block_delta
108− data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""} }
109−
110− event: content_block_delta
111− data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"f"} }
112−
113− event: content_block_delta
114− data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"ile_path\""} }
115−
116− event: content_block_delta
117− data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":": \"main.g"} }
118−
119− event: content_block_delta
120− data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"o\"}"} }
121−
122− event: content_block_stop
123− data: {"type":"content_block_stop","index":1 }
124−
125− event: message_delta
126− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1832,"cache_read_input_tokens":6853,"output_tokens":77} }
127−
128− event: message_stop
129− data: {"type":"message_stop"}
130−
131− headers:
132− Content-Type:
133− - text/event-stream; charset=utf-8
134− status: 200 OK
135− code: 200
136− duration: 2.025194292s
137−- id: 2
138− request:
139− proto: HTTP/1.1
140− proto_major: 1
141− proto_minor: 1
142− content_length: 32736
143− host: ""
144− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use multiedit to change 'Hello, World!' to 'Hello, Crush!' and add a comment '// Greeting' above the fmt.Println line in main.go\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"text\":\"I'll first check the content of main.go, then use multiedit to make both changes.\",\"type\":\"text\"},{\"id\":\"toolu_01EkVHzmaPGJju2LRYbGM3gJ\",\"input\":{\"file_path\":\"main.go\"},\"name\":\"view\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01EkVHzmaPGJju2LRYbGM3gJ\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"\\u003cfile\\u003e\\n 1|package main\\n 2|\\n 3|import \\\"fmt\\\"\\n 4|\\n 5|func main() {\\n 6|\\tfmt.Println(\\\"Hello, World!\\\")\\n 7|}\\n\\u003c/file\\u003e\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/multiedit_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
145− headers:
146− Accept:
147− - application/json
148− Content-Type:
149− - application/json
150− User-Agent:
151− - Anthropic/Go 1.12.0
152− url: https://api.anthropic.com/v1/messages
153− method: POST
154− response:
155− proto: HTTP/2.0
156− proto_major: 2
157− proto_minor: 0
158− content_length: -1
159− body: |+
160− event: message_start
161− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01FWCXTK929EjksLY27954m7","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":141,"cache_read_input_tokens":8685,"cache_creation":{"ephemeral_5m_input_tokens":141,"ephemeral_1h_input_tokens":0},"output_tokens":25,"service_tier":"standard"}} }
162−
163− event: content_block_start
164− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01SwJeR8LmvPpgUvmyVq4DRp","name":"multiedit","input":{}} }
165−
166− event: content_block_delta
167− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
168−
169− event: content_block_delta
170− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\""} }
171−
172− event: content_block_delta
173− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"file_pat"} }
174−
175− event: content_block_delta
176− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"h\": \"m"} }
177−
178− event: content_block_delta
179− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ain.go\""} }
180−
181− event: content_block_delta
182− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":", \"edi"} }
183−
184− event: content_block_delta
185− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ts\": [{"}}
186−
187− event: content_block_delta
188− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\"old_str"} }
189−
190− event: content_block_delta
191− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ing"}}
192−
193− event: content_block_delta
194− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\":\"\\tfmt"} }
195−
196− event: content_block_delta
197− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":".Println(\\\""} }
198−
199− event: content_block_delta
200− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"Hel"} }
201−
202− event: content_block_delta
203− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"lo, Worl"} }
204−
205− event: content_block_delta
206− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"d!\\\")\""} }
207−
208− event: content_block_delta
209− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":",\"new_s"} }
210−
211− event: content_block_delta
212− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"tring"} }
213−
214− event: content_block_delta
215− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\":\"\\t// Gr"} }
216−
217− event: content_block_delta
218− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"eet"} }
219−
220− event: content_block_delta
221− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ing"} }
222−
223− event: content_block_delta
224− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\\n\\tf"} }
225−
226− event: content_block_delta
227− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"mt.Printl"} }
228−
229− event: content_block_delta
230− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"n(\\\"Hell"} }
231−
232− event: content_block_delta
233− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"o, Cru"} }
234−
235− event: content_block_delta
236− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"sh!\\\")\"}"} }
237−
238− event: content_block_delta
239− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"]}"} }
240−
241− event: content_block_stop
242− data: {"type":"content_block_stop","index":0 }
243−
244− event: message_delta
245− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":141,"cache_read_input_tokens":8685,"output_tokens":133} }
246−
247− event: message_stop
248− data: {"type":"message_stop" }
249−
250− headers:
251− Content-Type:
252− - text/event-stream; charset=utf-8
253− status: 200 OK
254− code: 200
255− duration: 2.222343667s
256−- id: 3
257− request:
258− proto: HTTP/1.1
259− proto_major: 1
260− proto_minor: 1
261− content_length: 33275
262− host: ""
263− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use multiedit to change 'Hello, World!' to 'Hello, Crush!' and add a comment '// Greeting' above the fmt.Println line in main.go\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"text\":\"I'll first check the content of main.go, then use multiedit to make both changes.\",\"type\":\"text\"},{\"id\":\"toolu_01EkVHzmaPGJju2LRYbGM3gJ\",\"input\":{\"file_path\":\"main.go\"},\"name\":\"view\",\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01EkVHzmaPGJju2LRYbGM3gJ\",\"content\":[{\"text\":\"\\u003cfile\\u003e\\n 1|package main\\n 2|\\n 3|import \\\"fmt\\\"\\n 4|\\n 5|func main() {\\n 6|\\tfmt.Println(\\\"Hello, World!\\\")\\n 7|}\\n\\u003c/file\\u003e\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_01SwJeR8LmvPpgUvmyVq4DRp\",\"input\":{\"edits\":[{\"new_string\":\"\\t// Greeting\\n\\tfmt.Println(\\\"Hello, Crush!\\\")\",\"old_string\":\"\\tfmt.Println(\\\"Hello, World!\\\")\"}],\"file_path\":\"main.go\"},\"name\":\"multiedit\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01SwJeR8LmvPpgUvmyVq4DRp\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"\\u003cresult\\u003e\\nApplied 1 edits to file: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/multiedit_tool/main.go\\n\\u003c/result\\u003e\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/multiedit_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
264− headers:
265− Accept:
266− - application/json
267− Content-Type:
268− - application/json
269− User-Agent:
270− - Anthropic/Go 1.12.0
271− url: https://api.anthropic.com/v1/messages
272− method: POST
273− response:
274− proto: HTTP/2.0
275− proto_major: 2
276− proto_minor: 0
277− content_length: -1
278− body: |+
279− event: message_start
280− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_018XV2bezokrWMT4B8rr8dnp","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":178,"cache_read_input_tokens":8826,"cache_creation":{"ephemeral_5m_input_tokens":178,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
281−
282− event: content_block_start
283− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
284−
285− event: content_block_delta
286− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Done"} }
287−
288− event: content_block_delta
289− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":". Changed \"Hello, World!\" to \"Hello"} }
290−
291− event: ping
292− data: {"type": "ping"}
293−
294− event: content_block_delta
295− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":", Crush!\" and added the comment above the println"} }
296−
297− event: content_block_delta
298− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"."} }
299−
300− event: content_block_stop
301− data: {"type":"content_block_stop","index":0 }
302−
303− event: message_delta
304− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":178,"cache_read_input_tokens":8826,"output_tokens":26}}
305−
306− event: message_stop
307− data: {"type":"message_stop" }
308−
309− headers:
310− Content-Type:
311− - text/event-stream; charset=utf-8
312− status: 200 OK
313− code: 200
314− duration: 2.106580459s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/parallel_tool_calls.yamldeleted−201
@@ -1,201 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 842
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nuse glob to find all .go files and use ls to list the current directory, it is very important that you run both tool calls in parallel\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01QG9K82nFdNjFtQk7NoK5QB","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":159,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Parallel"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Go File"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Search and Directory"} }
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Listing"} }
47−
48− event: content_block_stop
49− data: {"type":"content_block_stop","index":0 }
50−
51− event: message_delta
52− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":159,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":12} }
53−
54− event: message_stop
55− data: {"type":"message_stop" }
56−
57− headers:
58− Content-Type:
59− - text/event-stream; charset=utf-8
60− status: 200 OK
61− code: 200
62− duration: 514.665167ms
63−- id: 1
64− request:
65− proto: HTTP/1.1
66− proto_major: 1
67− proto_minor: 1
68− content_length: 32158
69− host: ""
70− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use glob to find all .go files and use ls to list the current directory, it is very important that you run both tool calls in parallel\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/parallel_tool_calls\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
71− headers:
72− Accept:
73− - application/json
74− Content-Type:
75− - application/json
76− User-Agent:
77− - Anthropic/Go 1.12.0
78− url: https://api.anthropic.com/v1/messages
79− method: POST
80− response:
81− proto: HTTP/2.0
82− proto_major: 2
83− proto_minor: 0
84− content_length: -1
85− body: |+
86− event: message_start
87− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_0145i9s7oaHwEazjgovKd81D","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1821,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1821,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
88−
89− event: content_block_start
90− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01TeEXyjpFCqWrAh2Wd8qBh7","name":"glob","input":{}} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"pat"} }
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"tern"} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\":"} }
103−
104− event: content_block_delta
105− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":" \"**/*"} }
106−
107− event: content_block_delta
108− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":".g"} }
109−
110− event: content_block_delta
111− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"o\"}"} }
112−
113− event: content_block_stop
114− data: {"type":"content_block_stop","index":0 }
115−
116− event: content_block_start
117− data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_01N8sSFCLzvYCd2uXbz4jUGT","name":"ls","input":{}} }
118−
119− event: content_block_delta
120− data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""} }
121−
122− event: content_block_delta
123− data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"path\": \""} }
124−
125− event: content_block_delta
126− data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":".\"}"} }
127−
128− event: content_block_stop
129− data: {"type":"content_block_stop","index":1 }
130−
131− event: message_delta
132− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1821,"cache_read_input_tokens":6853,"output_tokens":86} }
133−
134− event: message_stop
135− data: {"type":"message_stop" }
136−
137− headers:
138− Content-Type:
139− - text/event-stream; charset=utf-8
140− status: 200 OK
141− code: 200
142− duration: 2.443706708s
143−- id: 2
144− request:
145− proto: HTTP/1.1
146− proto_major: 1
147− proto_minor: 1
148− content_length: 32839
149− host: ""
150− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use glob to find all .go files and use ls to list the current directory, it is very important that you run both tool calls in parallel\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_01TeEXyjpFCqWrAh2Wd8qBh7\",\"input\":{\"pattern\":\"**/*.go\"},\"name\":\"glob\",\"type\":\"tool_use\"},{\"id\":\"toolu_01N8sSFCLzvYCd2uXbz4jUGT\",\"input\":{\"path\":\".\"},\"name\":\"ls\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01TeEXyjpFCqWrAh2Wd8qBh7\",\"content\":[{\"text\":\"/tmp/crush-test/TestCoderAgent/anthropic-sonnet/parallel_tool_calls/main.go\",\"type\":\"text\"}],\"type\":\"tool_result\"},{\"tool_use_id\":\"toolu_01N8sSFCLzvYCd2uXbz4jUGT\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"\\n- /tmp/crush-test/TestCoderAgent/anthropic-sonnet/parallel_tool_calls/\\n - go.mod\\n - main.go\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/parallel_tool_calls\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
151− headers:
152− Accept:
153− - application/json
154− Content-Type:
155− - application/json
156− User-Agent:
157− - Anthropic/Go 1.12.0
158− url: https://api.anthropic.com/v1/messages
159− method: POST
160− response:
161− proto: HTTP/2.0
162− proto_major: 2
163− proto_minor: 0
164− content_length: -1
165− body: |+
166− event: message_start
167− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01CfHH9AC59iAZSPJ4Ec3Khu","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":7,"cache_creation_input_tokens":207,"cache_read_input_tokens":8674,"cache_creation":{"ephemeral_5m_input_tokens":207,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
168−
169− event: content_block_start
170− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
171−
172− event: content_block_delta
173− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Foun"} }
174−
175− event: content_block_delta
176− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d 1 Go file:"} }
177−
178− event: ping
179− data: {"type": "ping"}
180−
181− event: content_block_delta
182− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" `main.go`\n\nCurrent directory contains"} }
183−
184− event: content_block_delta
185− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":": `go.mod` and `main.go`"} }
186−
187− event: content_block_stop
188− data: {"type":"content_block_stop","index":0 }
189−
190− event: message_delta
191− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":7,"cache_creation_input_tokens":207,"cache_read_input_tokens":8674,"output_tokens":31} }
192−
193− event: message_stop
194− data: {"type":"message_stop" }
195−
196− headers:
197− Content-Type:
198− - text/event-stream; charset=utf-8
199− status: 200 OK
200− code: 200
201− duration: 2.043650083s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/read_a_file.yamldeleted−183
@@ -1,183 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 723
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nRead the go mod\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01AosjrFVVXCqAidJohxn6E7","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":134,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Rea"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d Go"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Module"} }
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Details"}}
47−
48− event: content_block_stop
49− data: {"type":"content_block_stop","index":0 }
50−
51− event: message_delta
52− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":134,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":7}}
53−
54− event: message_stop
55− data: {"type":"message_stop" }
56−
57− headers:
58− Content-Type:
59− - text/event-stream; charset=utf-8
60− status: 200 OK
61− code: 200
62− duration: 550.275666ms
63−- id: 1
64− request:
65− proto: HTTP/1.1
66− proto_major: 1
67− proto_minor: 1
68− content_length: 32031
69− host: ""
70− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"Read the go mod\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/read_a_file\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
71− headers:
72− Accept:
73− - application/json
74− Content-Type:
75− - application/json
76− User-Agent:
77− - Anthropic/Go 1.12.0
78− url: https://api.anthropic.com/v1/messages
79− method: POST
80− response:
81− proto: HTTP/2.0
82− proto_major: 2
83− proto_minor: 0
84− content_length: -1
85− body: |+
86− event: message_start
87− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01EfY8UeWMNayyJJUGdNLeWM","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1796,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1796,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
88−
89− event: content_block_start
90− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_016p6McX7tVqThB1FwChHmMm","name":"view","input":{}} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""}}
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"file_path\""} }
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":": \"go.mod"} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\"}"} }
103−
104− event: content_block_stop
105− data: {"type":"content_block_stop","index":0 }
106−
107− event: message_delta
108− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1796,"cache_read_input_tokens":6853,"output_tokens":55} }
109−
110− event: message_stop
111− data: {"type":"message_stop" }
112−
113− headers:
114− Content-Type:
115− - text/event-stream; charset=utf-8
116− status: 200 OK
117− code: 200
118− duration: 2.078621417s
119−- id: 2
120− request:
121− proto: HTTP/1.1
122− proto_major: 1
123− proto_minor: 1
124− content_length: 32441
125− host: ""
126− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"Read the go mod\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_016p6McX7tVqThB1FwChHmMm\",\"input\":{\"file_path\":\"go.mod\"},\"name\":\"view\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_016p6McX7tVqThB1FwChHmMm\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"\\u003cfile\\u003e\\n 1|module example.com/testproject\\n 2|\\n 3|go 1.23\\n\\u003c/file\\u003e\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/read_a_file\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
127− headers:
128− Accept:
129− - application/json
130− Content-Type:
131− - application/json
132− User-Agent:
133− - Anthropic/Go 1.12.0
134− url: https://api.anthropic.com/v1/messages
135− method: POST
136− response:
137− proto: HTTP/2.0
138− proto_major: 2
139− proto_minor: 0
140− content_length: -1
141− body: |+
142− event: message_start
143− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_019XZCDz8LmAGBwQsusVMYtg","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":96,"cache_read_input_tokens":8649,"cache_creation":{"ephemeral_5m_input_tokens":96,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
144−
145− event: content_block_start
146− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
147−
148− event: content_block_delta
149− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"```"} }
150−
151− event: content_block_delta
152− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"\nmodule example.com/testproject\n\ngo 1.23"} }
153−
154− event: ping
155− data: {"type": "ping"}
156−
157− event: content_block_delta
158− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"\n```"} }
159−
160− event: ping
161− data: {"type": "ping"}
162−
163− event: content_block_stop
164− data: {"type":"content_block_stop","index":0 }
165−
166− event: ping
167− data: {"type": "ping"}
168−
169− event: ping
170− data: {"type": "ping"}
171−
172− event: message_delta
173− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":96,"cache_read_input_tokens":8649,"output_tokens":20} }
174−
175− event: message_stop
176− data: {"type":"message_stop" }
177−
178− headers:
179− Content-Type:
180− - text/event-stream; charset=utf-8
181− status: 200 OK
182− code: 200
183− duration: 2.382524875s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/simple_test.yamldeleted−109
@@ -1,109 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 713
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nHello\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01FAWvBoccVMmLTBJwcdyBep","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":131,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Quick"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Chat"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Start"} }
44−
45− event: content_block_stop
46− data: {"type":"content_block_stop","index":0 }
47−
48− event: message_delta
49− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":131,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":6} }
50−
51− event: message_stop
52− data: {"type":"message_stop" }
53−
54− headers:
55− Content-Type:
56− - text/event-stream; charset=utf-8
57− status: 200 OK
58− code: 200
59− duration: 733.150917ms
60−- id: 1
61− request:
62− proto: HTTP/1.1
63− proto_major: 1
64− proto_minor: 1
65− content_length: 32021
66− host: ""
67− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"Hello\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/simple_test\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
68− headers:
69− Accept:
70− - application/json
71− Content-Type:
72− - application/json
73− User-Agent:
74− - Anthropic/Go 1.12.0
75− url: https://api.anthropic.com/v1/messages
76− method: POST
77− response:
78− proto: HTTP/2.0
79− proto_major: 2
80− proto_minor: 0
81− content_length: -1
82− body: |+
83− event: message_start
84− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_016wHt1RPkbhRGGRDo89QjdQ","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":8644,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":8644,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard"}} }
85−
86− event: content_block_start
87− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
88−
89− event: content_block_delta
90− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello! How"} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" can I help you today?"} }
94−
95− event: content_block_stop
96− data: {"type":"content_block_stop","index":0 }
97−
98− event: message_delta
99− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":8644,"cache_read_input_tokens":0,"output_tokens":12}}
100−
101− event: message_stop
102− data: {"type":"message_stop" }
103−
104− headers:
105− Content-Type:
106− - text/event-stream; charset=utf-8
107− status: 200 OK
108− code: 200
109− duration: 2.528825917s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/sourcegraph_tool.yamldeleted−223
@@ -1,223 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 768
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nuse sourcegraph to search for ''func main'' in Go repositories\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_0137phYsnpb3ZLZ6xWV4o1qc","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Searching"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Go"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Repos"} }
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for Main"} }
47−
48− event: content_block_delta
49− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Functions"} }
50−
51− event: content_block_stop
52− data: {"type":"content_block_stop","index":0}
53−
54− event: message_delta
55− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":11} }
56−
57− event: message_stop
58− data: {"type":"message_stop" }
59−
60− headers:
61− Content-Type:
62− - text/event-stream; charset=utf-8
63− status: 200 OK
64− code: 200
65− duration: 561.671875ms
66−- id: 1
67− request:
68− proto: HTTP/1.1
69− proto_major: 1
70− proto_minor: 1
71− content_length: 32081
72− host: ""
73− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use sourcegraph to search for 'func main' in Go repositories\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/sourcegraph_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
74− headers:
75− Accept:
76− - application/json
77− Content-Type:
78− - application/json
79− User-Agent:
80− - Anthropic/Go 1.12.0
81− url: https://api.anthropic.com/v1/messages
82− method: POST
83− response:
84− proto: HTTP/2.0
85− proto_major: 2
86− proto_minor: 0
87− content_length: -1
88− body: |+
89− event: message_start
90− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01L5zZBpdDM2uiQ2eLwF7YxE","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1807,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1807,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
91−
92− event: content_block_start
93− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01SSVxWDkehx1WmUUkrDb3xg","name":"sourcegraph","input":{}} }
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\""} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"query"} }
103−
104− event: content_block_delta
105− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\": \"lang:go "} }
106−
107− event: content_block_delta
108− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"func "} }
109−
110− event: content_block_delta
111− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"main\""} }
112−
113− event: content_block_delta
114− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":", \""} }
115−
116− event: content_block_delta
117− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"count\": 10}"} }
118−
119− event: content_block_stop
120− data: {"type":"content_block_stop","index":0 }
121−
122− event: message_delta
123− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1807,"cache_read_input_tokens":6853,"output_tokens":74} }
124−
125− event: message_stop
126− data: {"type":"message_stop" }
127−
128− headers:
129− Content-Type:
130− - text/event-stream; charset=utf-8
131− status: 200 OK
132− code: 200
133− duration: 2.650093625s
134−- id: 2
135− request:
136− proto: HTTP/1.1
137− proto_major: 1
138− proto_minor: 1
139− content_length: 424
140− host: sourcegraph.com
141− body: '{"query":"query Search($query: String!) { search(query: $query, version: V2, patternType: keyword ) { results { matchCount, limitHit, resultCount, approximateResultCount, missing { name }, timedout { name }, indexUnavailable, results { __typename, ... on FileMatch { repository { name }, file { path, url, content }, lineMatches { preview, lineNumber, offsetAndLengths } } } } } }","variables":{"query":"lang:go func main"}}'
142− headers:
143− Content-Type:
144− - application/json
145− User-Agent:
146− - crush/1.0
147− url: https://sourcegraph.com/.api/graphql
148− method: POST
149− response:
150− proto: HTTP/2.0
151− proto_major: 2
152− proto_minor: 0
153− content_length: -1
154− uncompressed: true
155− body: '{"data":{"search":{"results":{"matchCount":30,"limitHit":true,"resultCount":30,"approximateResultCount":"30+","missing":[],"timedout":[],"indexUnavailable":false,"results":[{"__typename":"FileMatch","repository":{"name":"github.com/pingguoxueyuan/gostudy"},"file":{"path":"listen15/defer/main.go","url":"/github.com/pingguoxueyuan/gostudy/-/blob/listen15/defer/main.go","content":"package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc funcA() int {\n\tx := 5\n\tdefer func() {\n\t\tx += 1\n\t}()\n\treturn x\n}\n\nfunc funcB() (x int) {\n\tdefer func() {\n\t\tx += 1\n\t}()\n\treturn 5\n}\n\nfunc funcC() (y int) {\n\tx := 5\n\tdefer func() {\n\t\tx += 1\n\t}()\n\treturn x\n}\n\nfunc funcD() (x int) {\n\tdefer func(x int) {\n\t\tx += 1\n\t}(x)\n\treturn 5\n}\n\nfunc main() {\n\t//fmt.Println(funcA())\n\t//fmt.Println(funcB())\n\t//fmt.Println(funcC())\n\tfmt.Println(funcD())\n}\n"},"lineMatches":[{"preview":"func main() {","lineNumber":36,"offsetAndLengths":[[0,9]]},{"preview":"\t//fmt.Println(funcA())","lineNumber":37,"offsetAndLengths":[[15,4]]},{"preview":"\t//fmt.Println(funcB())","lineNumber":38,"offsetAndLengths":[[15,4]]},{"preview":"\t//fmt.Println(funcC())","lineNumber":39,"offsetAndLengths":[[15,4]]},{"preview":"\tfmt.Println(funcD())","lineNumber":40,"offsetAndLengths":[[13,4]]},{"preview":"func funcA() int {","lineNumber":6,"offsetAndLengths":[[0,4],[5,4]]},{"preview":"\tdefer func() {","lineNumber":8,"offsetAndLengths":[[7,4]]},{"preview":"package main","lineNumber":0,"offsetAndLengths":[[8,4]]},{"preview":"func funcB() (x int) {","lineNumber":14,"offsetAndLengths":[[0,4],[5,4]]},{"preview":"\tdefer func() {","lineNumber":15,"offsetAndLengths":[[7,4]]},{"preview":"func funcC() (y int) {","lineNumber":21,"offsetAndLengths":[[0,4],[5,4]]},{"preview":"\tdefer func() {","lineNumber":23,"offsetAndLengths":[[7,4]]},{"preview":"func funcD() (x int) {","lineNumber":29,"offsetAndLengths":[[0,4],[5,4]]},{"preview":"\tdefer func(x int) {","lineNumber":30,"offsetAndLengths":[[7,4]]}]},{"__typename":"FileMatch","repository":{"name":"github.com/Zhouchaowen/golang-tutorial"},"file":{"path":"12-library/8-error/ch_1/main.go","url":"/github.com/Zhouchaowen/golang-tutorial/-/blob/12-library/8-error/ch_1/main.go","content":"package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nfunc func1() error {\n\treturn errors.New(\"func1 error\")\n}\n\nfunc func2() error {\n\treturn fmt.Errorf(\"func2 error: %w\", func1())\n}\n\nfunc main() {\n\terr := func2()\n\tif err != nil {\n\t\tfmt.Println(err)\n\t}\n}\n"},"lineMatches":[{"preview":"func main() {","lineNumber":15,"offsetAndLengths":[[0,9]]},{"preview":"\terr := func2()","lineNumber":16,"offsetAndLengths":[[8,4]]},{"preview":"func func1() error {","lineNumber":7,"offsetAndLengths":[[0,4],[5,4]]},{"preview":"\treturn errors.New(\"func1 error\")","lineNumber":8,"offsetAndLengths":[[20,4]]},{"preview":"func func2() error {","lineNumber":11,"offsetAndLengths":[[0,4],[5,4]]},{"preview":"\treturn fmt.Errorf(\"func2 error: %w\", func1())","lineNumber":12,"offsetAndLengths":[[20,4],[38,4]]},{"preview":"package main","lineNumber":0,"offsetAndLengths":[[8,4]]}]},{"__typename":"FileMatch","repository":{"name":"github.com/GoesToEleven/lynda"},"file":{"path":"cc/00_language-fundamentals/14_functions/10_func-expression/01_before-func-expression/main.go","url":"/github.com/GoesToEleven/lynda/-/blob/cc/00_language-fundamentals/14_functions/10_func-expression/01_before-func-expression/main.go","content":"package main\n\nimport \"fmt\"\n\nfunc greeting() {\n\tfmt.Println(\"Hello world!\")\n}\n\nfunc main() {\n\tgreeting()\n}\n\n/*\nAll material is licensed under the Apache License Version 2.0, January 2004\nhttp://www.apache.org/licenses/LICENSE-2.0\n*/\n"},"lineMatches":[{"preview":"func main() {","lineNumber":8,"offsetAndLengths":[[0,9]]},{"preview":"package main","lineNumber":0,"offsetAndLengths":[[8,4]]}]}]}}}}'
156− headers:
157− Content-Type:
158− - application/json
159− status: 200 OK
160− code: 200
161− duration: 1.454512083s
162−- id: 3
163− request:
164− proto: HTTP/1.1
165− proto_major: 1
166− proto_minor: 1
167− content_length: 40202
168− host: ""
169− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use sourcegraph to search for 'func main' in Go repositories\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_01SSVxWDkehx1WmUUkrDb3xg\",\"input\":{\"count\":10,\"query\":\"lang:go func main\"},\"name\":\"sourcegraph\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01SSVxWDkehx1WmUUkrDb3xg\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"# Sourcegraph Search Results\\n\\nFound 30 matches across 30 results\\n(Result limit reached, try a more specific query)\\n\\n## Result 1: github.com/pingguoxueyuan/gostudy/listen15/defer/main.go\\n\\nURL: /github.com/pingguoxueyuan/gostudy/-/blob/listen15/defer/main.go\\n\\n```\\n26| \\t}()\\n27| \\treturn x\\n28| }\\n29| \\n30| func funcD() (x int) {\\n31| \\tdefer func(x int) {\\n32| \\t\\tx += 1\\n33| \\t}(x)\\n34| \\treturn 5\\n35| }\\n36| func main() {\\n37| func main() {\\n38| \\t//fmt.Println(funcA())\\n39| \\t//fmt.Println(funcB())\\n40| \\t//fmt.Println(funcC())\\n41| \\tfmt.Println(funcD())\\n42| }\\n43| \\n```\\n\\n```\\n27| \\treturn x\\n28| }\\n29| \\n30| func funcD() (x int) {\\n31| \\tdefer func(x int) {\\n32| \\t\\tx += 1\\n33| \\t}(x)\\n34| \\treturn 5\\n35| }\\n36| \\n37| \\t//fmt.Println(funcA())\\n38| \\t//fmt.Println(funcA())\\n39| \\t//fmt.Println(funcB())\\n40| \\t//fmt.Println(funcC())\\n41| \\tfmt.Println(funcD())\\n42| }\\n43| \\n```\\n\\n```\\n28| }\\n29| \\n30| func funcD() (x int) {\\n31| \\tdefer func(x int) {\\n32| \\t\\tx += 1\\n33| \\t}(x)\\n34| \\treturn 5\\n35| }\\n36| \\n37| func main() {\\n38| \\t//fmt.Println(funcB())\\n39| \\t//fmt.Println(funcB())\\n40| \\t//fmt.Println(funcC())\\n41| \\tfmt.Println(funcD())\\n42| }\\n43| \\n```\\n\\n```\\n29| \\n30| func funcD() (x int) {\\n31| \\tdefer func(x int) {\\n32| \\t\\tx += 1\\n33| \\t}(x)\\n34| \\treturn 5\\n35| }\\n36| \\n37| func main() {\\n38| \\t//fmt.Println(funcA())\\n39| \\t//fmt.Println(funcC())\\n40| \\t//fmt.Println(funcC())\\n41| \\tfmt.Println(funcD())\\n42| }\\n43| \\n```\\n\\n```\\n30| func funcD() (x int) {\\n31| \\tdefer func(x int) {\\n32| \\t\\tx += 1\\n33| \\t}(x)\\n34| \\treturn 5\\n35| }\\n36| \\n37| func main() {\\n38| \\t//fmt.Println(funcA())\\n39| \\t//fmt.Println(funcB())\\n40| \\tfmt.Println(funcD())\\n41| \\tfmt.Println(funcD())\\n42| }\\n43| \\n```\\n\\n```\\n1| package main\\n2| \\n3| import (\\n4| \\t\\\"fmt\\\"\\n5| )\\n6| func funcA() int {\\n7| func funcA() int {\\n8| \\tx := 5\\n9| \\tdefer func() {\\n10| \\t\\tx += 1\\n11| \\t}()\\n12| \\treturn x\\n13| }\\n14| \\n15| func funcB() (x int) {\\n16| \\tdefer func() {\\n```\\n\\n```\\n1| package main\\n2| \\n3| import (\\n4| \\t\\\"fmt\\\"\\n5| )\\n6| \\n7| func funcA() int {\\n8| \\tdefer func() {\\n9| \\tdefer func() {\\n10| \\t\\tx += 1\\n11| \\t}()\\n12| \\treturn x\\n13| }\\n14| \\n15| func funcB() (x int) {\\n16| \\tdefer func() {\\n17| \\t\\tx += 1\\n18| \\t}()\\n```\\n\\n```\\n0| package main\\n1| package main\\n2| \\n3| import (\\n4| \\t\\\"fmt\\\"\\n5| )\\n6| \\n7| func funcA() int {\\n8| \\tx := 5\\n9| \\tdefer func() {\\n10| \\t\\tx += 1\\n```\\n\\n```\\n4| \\t\\\"fmt\\\"\\n5| )\\n6| \\n7| func funcA() int {\\n8| \\tx := 5\\n9| \\tdefer func() {\\n10| \\t\\tx += 1\\n11| \\t}()\\n12| \\treturn x\\n13| }\\n14| func funcB() (x int) {\\n15| func funcB() (x int) {\\n16| \\tdefer func() {\\n17| \\t\\tx += 1\\n18| \\t}()\\n19| \\treturn 5\\n20| }\\n21| \\n22| func funcC() (y int) {\\n23| \\tx := 5\\n24| \\tdefer func() {\\n```\\n\\n```\\n5| )\\n6| \\n7| func funcA() int {\\n8| \\tx := 5\\n9| \\tdefer func() {\\n10| \\t\\tx += 1\\n11| \\t}()\\n12| \\treturn x\\n13| }\\n14| \\n15| \\tdefer func() {\\n16| \\tdefer func() {\\n17| \\t\\tx += 1\\n18| \\t}()\\n19| \\treturn 5\\n20| }\\n21| \\n22| func funcC() (y int) {\\n23| \\tx := 5\\n24| \\tdefer func() {\\n25| \\t\\tx += 1\\n```\\n\\n```\\n11| \\t}()\\n12| \\treturn x\\n13| }\\n14| \\n15| func funcB() (x int) {\\n16| \\tdefer func() {\\n17| \\t\\tx += 1\\n18| \\t}()\\n19| \\treturn 5\\n20| }\\n21| func funcC() (y int) {\\n22| func funcC() (y int) {\\n23| \\tx := 5\\n24| \\tdefer func() {\\n25| \\t\\tx += 1\\n26| \\t}()\\n27| \\treturn x\\n28| }\\n29| \\n30| func funcD() (x int) {\\n31| \\tdefer func(x int) {\\n```\\n\\n```\\n13| }\\n14| \\n15| func funcB() (x int) {\\n16| \\tdefer func() {\\n17| \\t\\tx += 1\\n18| \\t}()\\n19| \\treturn 5\\n20| }\\n21| \\n22| func funcC() (y int) {\\n23| \\tdefer func() {\\n24| \\tdefer func() {\\n25| \\t\\tx += 1\\n26| \\t}()\\n27| \\treturn x\\n28| }\\n29| \\n30| func funcD() (x int) {\\n31| \\tdefer func(x int) {\\n32| \\t\\tx += 1\\n33| \\t}(x)\\n```\\n\\n```\\n19| \\treturn 5\\n20| }\\n21| \\n22| func funcC() (y int) {\\n23| \\tx := 5\\n24| \\tdefer func() {\\n25| \\t\\tx += 1\\n26| \\t}()\\n27| \\treturn x\\n28| }\\n29| func funcD() (x int) {\\n30| func funcD() (x int) {\\n31| \\tdefer func(x int) {\\n32| \\t\\tx += 1\\n33| \\t}(x)\\n34| \\treturn 5\\n35| }\\n36| \\n37| func main() {\\n38| \\t//fmt.Println(funcA())\\n39| \\t//fmt.Println(funcB())\\n```\\n\\n```\\n20| }\\n21| \\n22| func funcC() (y int) {\\n23| \\tx := 5\\n24| \\tdefer func() {\\n25| \\t\\tx += 1\\n26| \\t}()\\n27| \\treturn x\\n28| }\\n29| \\n30| \\tdefer func(x int) {\\n31| \\tdefer func(x int) {\\n32| \\t\\tx += 1\\n33| \\t}(x)\\n34| \\treturn 5\\n35| }\\n36| \\n37| func main() {\\n38| \\t//fmt.Println(funcA())\\n39| \\t//fmt.Println(funcB())\\n40| \\t//fmt.Println(funcC())\\n```\\n\\n## Result 2: github.com/Zhouchaowen/golang-tutorial/12-library/8-error/ch_1/main.go\\n\\nURL: /github.com/Zhouchaowen/golang-tutorial/-/blob/12-library/8-error/ch_1/main.go\\n\\n```\\n5| \\t\\\"fmt\\\"\\n6| )\\n7| \\n8| func func1() error {\\n9| \\treturn errors.New(\\\"func1 error\\\")\\n10| }\\n11| \\n12| func func2() error {\\n13| \\treturn fmt.Errorf(\\\"func2 error: %w\\\", func1())\\n14| }\\n15| func main() {\\n16| func main() {\\n17| \\terr := func2()\\n18| \\tif err != nil {\\n19| \\t\\tfmt.Println(err)\\n20| \\t}\\n21| }\\n22| \\n```\\n\\n```\\n6| )\\n7| \\n8| func func1() error {\\n9| \\treturn errors.New(\\\"func1 error\\\")\\n10| }\\n11| \\n12| func func2() error {\\n13| \\treturn fmt.Errorf(\\\"func2 error: %w\\\", func1())\\n14| }\\n15| \\n16| \\terr := func2()\\n17| \\terr := func2()\\n18| \\tif err != nil {\\n19| \\t\\tfmt.Println(err)\\n20| \\t}\\n21| }\\n22| \\n```\\n\\n```\\n1| package main\\n2| \\n3| import (\\n4| \\t\\\"errors\\\"\\n5| \\t\\\"fmt\\\"\\n6| )\\n7| func func1() error {\\n8| func func1() error {\\n9| \\treturn errors.New(\\\"func1 error\\\")\\n10| }\\n11| \\n12| func func2() error {\\n13| \\treturn fmt.Errorf(\\\"func2 error: %w\\\", func1())\\n14| }\\n15| \\n16| func main() {\\n17| \\terr := func2()\\n```\\n\\n```\\n1| package main\\n2| \\n3| import (\\n4| \\t\\\"errors\\\"\\n5| \\t\\\"fmt\\\"\\n6| )\\n7| \\n8| \\treturn errors.New(\\\"func1 error\\\")\\n9| \\treturn errors.New(\\\"func1 error\\\")\\n10| }\\n11| \\n12| func func2() error {\\n13| \\treturn fmt.Errorf(\\\"func2 error: %w\\\", func1())\\n14| }\\n15| \\n16| func main() {\\n17| \\terr := func2()\\n18| \\tif err != nil {\\n```\\n\\n```\\n1| package main\\n2| \\n3| import (\\n4| \\t\\\"errors\\\"\\n5| \\t\\\"fmt\\\"\\n6| )\\n7| \\n8| func func1() error {\\n9| \\treturn errors.New(\\\"func1 error\\\")\\n10| }\\n11| func func2() error {\\n12| func func2() error {\\n13| \\treturn fmt.Errorf(\\\"func2 error: %w\\\", func1())\\n14| }\\n15| \\n16| func main() {\\n17| \\terr := func2()\\n18| \\tif err != nil {\\n19| \\t\\tfmt.Println(err)\\n20| \\t}\\n21| }\\n```\\n\\n```\\n2| \\n3| import (\\n4| \\t\\\"errors\\\"\\n5| \\t\\\"fmt\\\"\\n6| )\\n7| \\n8| func func1() error {\\n9| \\treturn errors.New(\\\"func1 error\\\")\\n10| }\\n11| \\n12| \\treturn fmt.Errorf(\\\"func2 error: %w\\\", func1())\\n13| \\treturn fmt.Errorf(\\\"func2 error: %w\\\", func1())\\n14| }\\n15| \\n16| func main() {\\n17| \\terr := func2()\\n18| \\tif err != nil {\\n19| \\t\\tfmt.Println(err)\\n20| \\t}\\n21| }\\n22| \\n```\\n\\n```\\n0| package main\\n1| package main\\n2| \\n3| import (\\n4| \\t\\\"errors\\\"\\n5| \\t\\\"fmt\\\"\\n6| )\\n7| \\n8| func func1() error {\\n9| \\treturn errors.New(\\\"func1 error\\\")\\n10| }\\n```\\n\\n## Result 3: github.com/GoesToEleven/lynda/cc/00_language-fundamentals/14_functions/10_func-expression/01_before-func-expression/main.go\\n\\nURL: /github.com/GoesToEleven/lynda/-/blob/cc/00_language-fundamentals/14_functions/10_func-expression/01_before-func-expression/main.go\\n\\n```\\n1| package main\\n2| \\n3| import \\\"fmt\\\"\\n4| \\n5| func greeting() {\\n6| \\tfmt.Println(\\\"Hello world!\\\")\\n7| }\\n8| func main() {\\n9| func main() {\\n10| \\tgreeting()\\n11| }\\n12| \\n13| /*\\n14| All material is licensed under the Apache License Version 2.0, January 2004\\n15| http://www.apache.org/licenses/LICENSE-2.0\\n16| */\\n17| \\n```\\n\\n```\\n0| package main\\n1| package main\\n2| \\n3| import \\\"fmt\\\"\\n4| \\n5| func greeting() {\\n6| \\tfmt.Println(\\\"Hello world!\\\")\\n7| }\\n8| \\n9| func main() {\\n10| \\tgreeting()\\n```\\n\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/sourcegraph_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
170− headers:
171− Accept:
172− - application/json
173− Content-Type:
174− - application/json
175− User-Agent:
176− - Anthropic/Go 1.12.0
177− url: https://api.anthropic.com/v1/messages
178− method: POST
179− response:
180− proto: HTTP/2.0
181− proto_major: 2
182− proto_minor: 0
183− content_length: -1
184− body: |+
185− event: message_start
186− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01LRLuMdSjNZajNN2EUxAd4C","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":3612,"cache_read_input_tokens":8660,"cache_creation":{"ephemeral_5m_input_tokens":3612,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
187−
188− event: content_block_start
189− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
190−
191− event: content_block_delta
192− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Foun"} }
193−
194− event: content_block_delta
195− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d 30 matches across 30 files. The"} }
196−
197− event: ping
198− data: {"type": "ping"}
199−
200− event: content_block_delta
201− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" search returned Go repositories containing `func main` declarations"} }
202−
203− event: content_block_delta
204− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":", including examples from tutorial repositories showing"} }
205−
206− event: content_block_delta
207− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" various Go language features like defer statements, error handling, and function expressions."} }
208−
209− event: content_block_stop
210− data: {"type":"content_block_stop","index":0 }
211−
212− event: message_delta
213− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":3612,"cache_read_input_tokens":8660,"output_tokens":47} }
214−
215− event: message_stop
216− data: {"type":"message_stop" }
217−
218− headers:
219− Content-Type:
220− - text/event-stream; charset=utf-8
221− status: 200 OK
222− code: 200
223− duration: 2.523495s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/update_a_file.yamldeleted−293
@@ -1,293 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 777
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nupdate the main.go file by changing the print to say hello from crush\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_0124XpcSuB61ZBx1SPUnu1Qb","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Update"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" main"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":".go Hello"}}
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Print"} }
47−
48− event: content_block_stop
49− data: {"type":"content_block_stop","index":0 }
50−
51− event: message_delta
52− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":9} }
53−
54− event: message_stop
55− data: {"type":"message_stop" }
56−
57− headers:
58− Content-Type:
59− - text/event-stream; charset=utf-8
60− status: 200 OK
61− code: 200
62− duration: 648.821083ms
63−- id: 1
64− request:
65− proto: HTTP/1.1
66− proto_major: 1
67− proto_minor: 1
68− content_length: 32087
69− host: ""
70− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"update the main.go file by changing the print to say hello from crush\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/update_a_file\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
71− headers:
72− Accept:
73− - application/json
74− Content-Type:
75− - application/json
76− User-Agent:
77− - Anthropic/Go 1.12.0
78− url: https://api.anthropic.com/v1/messages
79− method: POST
80− response:
81− proto: HTTP/2.0
82− proto_major: 2
83− proto_minor: 0
84− content_length: -1
85− body: |+
86− event: message_start
87− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01WDos6sXG37avomBTwjHnLi","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1807,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1807,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
88−
89− event: content_block_start
90− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_012eFK8SiD9DLuu1r9G1riKx","name":"view","input":{}} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\""} }
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"fi"} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"le_p"} }
103−
104− event: content_block_delta
105− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ath"} }
106−
107− event: content_block_delta
108− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\": \"main"} }
109−
110− event: content_block_delta
111− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":".go\"}"} }
112−
113− event: content_block_stop
114− data: {"type":"content_block_stop","index":0 }
115−
116− event: message_delta
117− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1807,"cache_read_input_tokens":6853,"output_tokens":55} }
118−
119− event: message_stop
120− data: {"type":"message_stop" }
121−
122− headers:
123− Content-Type:
124− - text/event-stream; charset=utf-8
125− status: 200 OK
126− code: 200
127− duration: 2.504401167s
128−- id: 2
129− request:
130− proto: HTTP/1.1
131− proto_major: 1
132− proto_minor: 1
133− content_length: 32569
134− host: ""
135− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"update the main.go file by changing the print to say hello from crush\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_012eFK8SiD9DLuu1r9G1riKx\",\"input\":{\"file_path\":\"main.go\"},\"name\":\"view\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_012eFK8SiD9DLuu1r9G1riKx\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"\\u003cfile\\u003e\\n 1|package main\\n 2|\\n 3|import \\\"fmt\\\"\\n 4|\\n 5|func main() {\\n 6|\\tfmt.Println(\\\"Hello, World!\\\")\\n 7|}\\n\\u003c/file\\u003e\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/update_a_file\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
136− headers:
137− Accept:
138− - application/json
139− Content-Type:
140− - application/json
141− User-Agent:
142− - Anthropic/Go 1.12.0
143− url: https://api.anthropic.com/v1/messages
144− method: POST
145− response:
146− proto: HTTP/2.0
147− proto_major: 2
148− proto_minor: 0
149− content_length: -1
150− body: |+
151− event: message_start
152− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_011Y6PAeHJdg3Ph6ZFLMNuwG","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":120,"cache_read_input_tokens":8660,"cache_creation":{"ephemeral_5m_input_tokens":120,"ephemeral_1h_input_tokens":0},"output_tokens":25,"service_tier":"standard"}} }
153−
154− event: content_block_start
155− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_019M2MmqUbzyvMfw9WaD3VFa","name":"edit","input":{}} }
156−
157− event: content_block_delta
158− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
159−
160− event: content_block_delta
161− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"file_p"} }
162−
163− event: content_block_delta
164− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ath\": \"mai"} }
165−
166− event: content_block_delta
167− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"n."} }
168−
169− event: content_block_delta
170− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"go\""} }
171−
172− event: content_block_delta
173− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":", \"old_"} }
174−
175− event: content_block_delta
176− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"stri"} }
177−
178− event: content_block_delta
179− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ng\": \"fu"} }
180−
181− event: content_block_delta
182− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"nc main() {\\"} }
183−
184− event: content_block_delta
185− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"n\\tfmt."} }
186−
187− event: content_block_delta
188− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"Println(\\\""} }
189−
190− event: content_block_delta
191− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"Hello, "} }
192−
193− event: content_block_delta
194− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"Wo"} }
195−
196− event: content_block_delta
197− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"rld!\\\")"} }
198−
199− event: content_block_delta
200− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\\n}\""} }
201−
202− event: content_block_delta
203− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":", \"new_stri"} }
204−
205− event: content_block_delta
206− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ng\": \"func "}}
207−
208− event: content_block_delta
209− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"main() {\\n\\"} }
210−
211− event: content_block_delta
212− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"tfmt.Pri"} }
213−
214− event: content_block_delta
215− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ntln(\\\"hello"} }
216−
217− event: content_block_delta
218− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":" from cr"} }
219−
220− event: content_block_delta
221− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ush\\\""} }
222−
223− event: content_block_delta
224− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":")\\"}}
225−
226− event: content_block_delta
227− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"n}\"}"} }
228−
229− event: content_block_stop
230− data: {"type":"content_block_stop","index":0 }
231−
232− event: message_delta
233− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":120,"cache_read_input_tokens":8660,"output_tokens":123}}
234−
235− event: message_stop
236− data: {"type":"message_stop" }
237−
238− headers:
239− Content-Type:
240− - text/event-stream; charset=utf-8
241− status: 200 OK
242− code: 200
243− duration: 2.590338541s
244−- id: 3
245− request:
246− proto: HTTP/1.1
247− proto_major: 1
248− proto_minor: 1
249− content_length: 33115
250− host: ""
251− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"update the main.go file by changing the print to say hello from crush\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_012eFK8SiD9DLuu1r9G1riKx\",\"input\":{\"file_path\":\"main.go\"},\"name\":\"view\",\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_012eFK8SiD9DLuu1r9G1riKx\",\"content\":[{\"text\":\"\\u003cfile\\u003e\\n 1|package main\\n 2|\\n 3|import \\\"fmt\\\"\\n 4|\\n 5|func main() {\\n 6|\\tfmt.Println(\\\"Hello, World!\\\")\\n 7|}\\n\\u003c/file\\u003e\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_019M2MmqUbzyvMfw9WaD3VFa\",\"input\":{\"file_path\":\"main.go\",\"new_string\":\"func main() {\\n\\tfmt.Println(\\\"hello from crush\\\")\\n}\",\"old_string\":\"func main() {\\n\\tfmt.Println(\\\"Hello, World!\\\")\\n}\"},\"name\":\"edit\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_019M2MmqUbzyvMfw9WaD3VFa\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"\\u003cresult\\u003e\\nContent replaced in file: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/update_a_file/main.go\\n\\u003c/result\\u003e\\n\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/update_a_file\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
252− headers:
253− Accept:
254− - application/json
255− Content-Type:
256− - application/json
257− User-Agent:
258− - Anthropic/Go 1.12.0
259− url: https://api.anthropic.com/v1/messages
260− method: POST
261− response:
262− proto: HTTP/2.0
263− proto_major: 2
264− proto_minor: 0
265− content_length: -1
266− body: |+
267− event: message_start
268− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_016L6sSaeRFwHpTNycXatjPG","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":175,"cache_read_input_tokens":8780,"cache_creation":{"ephemeral_5m_input_tokens":175,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
269−
270− event: content_block_start
271− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
272−
273− event: content_block_delta
274− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Done"} }
275−
276− event: content_block_delta
277− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"."} }
278−
279− event: content_block_stop
280− data: {"type":"content_block_stop","index":0 }
281−
282− event: message_delta
283− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":175,"cache_read_input_tokens":8780,"output_tokens":5} }
284−
285− event: message_stop
286− data: {"type":"message_stop" }
287−
288− headers:
289− Content-Type:
290− - text/event-stream; charset=utf-8
291− status: 200 OK
292− code: 200
293− duration: 3.520432916s
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/write_tool.yamldeleted−243
@@ -1,243 +0,0 @@
1−---
2−version: 2
3−interactions:
4−- id: 0
5− request:
6− proto: HTTP/1.1
7− proto_major: 1
8− proto_minor: 1
9− content_length: 817
10− host: ""
11− body: '{"max_tokens":40,"messages":[{"content":[{"text":"Generate a concise title for the following content:\n\nuse write to create a new file called config.json with content ''{\"name\": \"test\", \"version\": \"1.0.0\"}''\n \u003cthink\u003e\n\n\u003c/think\u003e","type":"text"}],"role":"user"}],"model":"claude-3-5-haiku-20241022","system":[{"text":"you will generate a short title based on the first message a user begins a conversation with\n\n\u003crules\u003e\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n\u003c/rules\u003e\n\n /no_think","type":"text"}],"stream":true}'
12− headers:
13− Accept:
14− - application/json
15− Content-Type:
16− - application/json
17− User-Agent:
18− - Anthropic/Go 1.12.0
19− url: https://api.anthropic.com/v1/messages
20− method: POST
21− response:
22− proto: HTTP/2.0
23− proto_major: 2
24− proto_minor: 0
25− content_length: -1
26− body: |+
27− event: message_start
28− data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01JMWchmGYjGvwhk1QHW8zM2","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":161,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
29−
30− event: content_block_start
31− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
32−
33− event: content_block_delta
34− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Create"} }
35−
36− event: content_block_delta
37− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" JSON"} }
38−
39− event: ping
40− data: {"type": "ping"}
41−
42− event: content_block_delta
43− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Configuration"} }
44−
45− event: content_block_delta
46− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" File"} }
47−
48− event: content_block_stop
49− data: {"type":"content_block_stop","index":0 }
50−
51− event: message_delta
52− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":161,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":7} }
53−
54− event: message_stop
55− data: {"type":"message_stop" }
56−
57− headers:
58− Content-Type:
59− - text/event-stream; charset=utf-8
60− status: 200 OK
61− code: 200
62− duration: 525.572291ms
63−- id: 1
64− request:
65− proto: HTTP/1.1
66− proto_major: 1
67− proto_minor: 1
68− content_length: 32124
69− host: ""
70− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use write to create a new file called config.json with content '{\\\"name\\\": \\\"test\\\", \\\"version\\\": \\\"1.0.0\\\"}'\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/write_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
71− headers:
72− Accept:
73− - application/json
74− Content-Type:
75− - application/json
76− User-Agent:
77− - Anthropic/Go 1.12.0
78− url: https://api.anthropic.com/v1/messages
79− method: POST
80− response:
81− proto: HTTP/2.0
82− proto_major: 2
83− proto_minor: 0
84− content_length: -1
85− body: |+
86− event: message_start
87− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_01GtViPWmhueXgG64JgCJ7m2","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1821,"cache_read_input_tokens":6853,"cache_creation":{"ephemeral_5m_input_tokens":1821,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
88−
89− event: content_block_start
90− data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_014LZ2qfDhfKZ43DAp3QDDGd","name":"write","input":{}} }
91−
92− event: content_block_delta
93− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} }
94−
95− event: content_block_delta
96− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"file_path"}}
97−
98− event: content_block_delta
99− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\": \"/tmp/cr"} }
100−
101− event: content_block_delta
102− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ush-t"} }
103−
104− event: content_block_delta
105− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"est/Te"} }
106−
107− event: content_block_delta
108− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"stCoderAgen"} }
109−
110− event: content_block_delta
111− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"t/anthrop"} }
112−
113− event: content_block_delta
114− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ic-"} }
115−
116− event: content_block_delta
117− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"son"} }
118−
119− event: content_block_delta
120− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"net/write"} }
121−
122− event: content_block_delta
123− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"_to"} }
124−
125− event: content_block_delta
126− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ol/co"} }
127−
128− event: content_block_delta
129− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"nfig.j"} }
130−
131− event: content_block_delta
132− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"so"} }
133−
134− event: content_block_delta
135− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"n\""} }
136−
137− event: content_block_delta
138− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":", \"co"} }
139−
140− event: content_block_delta
141− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ntent\": \""} }
142−
143− event: content_block_delta
144− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\\\"name\\\":"} }
145−
146− event: content_block_delta
147− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":" \\\"test\\\", \\"} }
148−
149− event: content_block_delta
150− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\"vers"} }
151−
152− event: content_block_delta
153− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ion\\\""} }
154−
155− event: content_block_delta
156− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":": \\"} }
157−
158− event: content_block_delta
159− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\"1.0.0\\\""} }
160−
161− event: content_block_delta
162− data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"}\"}"} }
163−
164− event: content_block_stop
165− data: {"type":"content_block_stop","index":0 }
166−
167− event: message_delta
168− data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1821,"cache_read_input_tokens":6853,"output_tokens":109}}
169−
170− event: message_stop
171− data: {"type":"message_stop" }
172−
173− headers:
174− Content-Type:
175− - text/event-stream; charset=utf-8
176− status: 200 OK
177− code: 200
178− duration: 3.78905875s
179−- id: 2
180− request:
181− proto: HTTP/1.1
182− proto_major: 1
183− proto_minor: 1
184− content_length: 32693
185− host: ""
186− body: "{\"max_tokens\":10000,\"messages\":[{\"content\":[{\"text\":\"use write to create a new file called config.json with content '{\\\"name\\\": \\\"test\\\", \\\"version\\\": \\\"1.0.0\\\"}'\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"id\":\"toolu_014LZ2qfDhfKZ43DAp3QDDGd\",\"input\":{\"content\":\"{\\\"name\\\": \\\"test\\\", \\\"version\\\": \\\"1.0.0\\\"}\",\"file_path\":\"/tmp/crush-test/TestCoderAgent/anthropic-sonnet/write_tool/config.json\"},\"name\":\"write\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_014LZ2qfDhfKZ43DAp3QDDGd\",\"cache_control\":{\"type\":\"ephemeral\"},\"content\":[{\"text\":\"\\u003cresult\\u003e\\nFile successfully written: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/write_tool/config.json\\n\\u003c/result\\u003e\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-5-20250929\",\"system\":[{\"text\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\nUse the instructions below and the tools available to you to assist the user.\\n\\n\\u003cmemory_instructions\\u003e\\nIf the current working directory contains a file used for memory, they will be automatically added to your context.\\n\\nThese file serves multiple purposes:\\n\\n- Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time\\n- Recording the user's code style preferences (naming conventions, preferred libraries, etc.)\\n- Maintaining useful information about the codebase structure and organization\\n\\nWhen you discover important information that could be useful for the future update/add the info the appropriate memory file.\\n\\nMake sure to follow the memory files instructions while working.\\n\\u003c/memory_instructions\\u003e\\n\\n\\u003ccommunication_style\\u003e\\n- Be concise and direct\\n- Keep responses under 4 lines unless details requested\\n- Answer without preamble/postamble (\\\"Here is...\\\", \\\"The answer is...\\\")\\n- One-word answers preferred when possible\\n- Never use emojis in your responses\\n- You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail\\n- User markdown formatting for responses when appropriate\\n\\n\\u003cexample\\u003e\\nuser: 2 + 2\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what is 2+2?\\nassistant: 4\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: is 11 a prime number?\\nassistant: true\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to list files in the current directory?\\nassistant: ls\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what command should I run to watch files in the current directory?\\nassistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]\\nnpm run dev\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: How many golf balls fit inside a jetta?\\nassistant: 150000\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: what files are in the directory src/?\\nassistant: [runs ls and sees foo.c, bar.c, baz.c]\\nuser: which file contains the implementation of foo?\\nassistant: src/foo.c\\n\\u003c/example\\u003e\\n\\n\\u003cexample\\u003e\\nuser: write tests for new feature\\nassistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]\\n\\u003c/example\\u003e\\n\\n\\u003c/communication_style\\u003e\\n\\n\\u003cproactiveness\\u003e\\nYou are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:\\n\\n- Doing the right thing when asked, including taking actions and follow-up actions\\n- Not surprising the user with actions you take without asking\\n - For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.\\n- Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.\\n\\u003c/proactiveness\\u003e\\n\\n\\u003cfollowing_conversations\\u003e\\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\\n\\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).\\n- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.\\n- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.\\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\\n\\u003c/following_conversations\\u003e\\n\\n\\u003ccode_style\\u003e\\n- Follow existing code style and patterns.\\n- Do not add any comments to code you write unless asked to do so.\\n- Thrive to write only code that is necessary to solve the given issue (less code is always better).\\n- Follow best practices for the language and framework used in the project.\\n\\u003c/code_style\\u003e\\n\\n\\u003cdoing_tasks\\u003e\\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\\n\\n- Use the available search tools to understand the codebase and the user's query.\\n- Plan out the implementation (create a todo list)\\n- Implement the solution using all tools available to you\\n- Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.\\n- When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CRUSH.md so that you will know to run it next time.\\n\\nNEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked.\\n\\u003c/doing_tasks\\u003e\\n\\n\\u003ctool_use\\u003e\\n- When doing file search, prefer to use the Agent tool, give the agent detailed instructions on what to search for and response format details.\\n- All tools are executed in parallel when multiple tool calls are sent in a single message. Only send multiple tool calls when they are safe to run in parallel (no dependencies between them).\\n- The user does not see the full output of the tool responses, so if you need the output of the tool for the response make sure to summarize it for the user.\\n\\u003c/tool_use\\u003e\\n\\n\\u003cenv\\u003e\\nWorking directory: /tmp/crush-test/TestCoderAgent/anthropic-sonnet/write_tool\\nIs directory a git repo: no \\nPlatform: linux\\nToday's date: 1/1/2025\\n\\u003c/env\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"},\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in milliseconds (max 600000)\",\"type\":\"integer\"}},\"required\":[\"command\"],\"type\":\"object\"},\"name\":\"bash\",\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\n\\n\\u003ccross_platform\\u003e\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n\\u003c/cross_platform\\u003e\\n\\n\\u003cexecution_steps\\u003e\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with \\u003ccwd\\u003e\\u003c/cwd\\u003e tags\\n\\u003c/execution_steps\\u003e\\n\\n\\u003cusage_notes\\u003e\\n- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '\\u0026\\u0026', avoid newlines except in quoted strings\\n- Shell state persists (env vars, virtual envs, cwd, etc.)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n\\u003c/usage_notes\\u003e\\n\\n\\u003cgit_commits\\u003e\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in \\u003ccommit_analysis\\u003e tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond git context\\n - Draft concise (1-2 sentences) message focusing on \\\"why\\\" not \\\"what\\\"\\n - Use clear language, accurate reflection (\\\"add\\\"=new feature, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix)\\n - Avoid generic messages, review draft\\n\\n4. Create commit with Crush signature using HEREDOC:\\n git commit -m \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n Commit message here.\\n\\n \U0001F498 Generated with Crush\\n\\n\\n Co-Authored-By: Crush \\u003ccrush@charm.land\\u003e\\n\\n EOF\\n )\\\"\\n\\n5. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n6. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response.\\n\\u003c/git_commits\\u003e\\n\\n\\u003cpull_requests\\u003e\\nUse gh command for ALL GitHub tasks. When user asks to create PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n3. Commit changes if needed\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in \\u003cpr_analysis\\u003e tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Clear, concise language\\n - Accurate reflection of changes and purpose\\n - Avoid generic summaries\\n - Review draft\\n\\n6. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat \\u0026lt;\\u0026lt;'EOF'\\n\\n ## Summary\\n\\n \\u0026lt;1-3 bullet points\\u003e\\n\\n ## Test plan\\n\\n [Checklist of TODOs...]\\n\\n\\n \U0001F498 Generated with Crush\\n\\n\\n EOF\\n )\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n\\u003c/pull_requests\\u003e\\n\\n\\u003cexamples\\u003e\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar \\u0026\\u0026 pytest tests\\n\\u003c/examples\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"},\"name\":\"download\",\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n\\u003cusage\\u003e\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Downloads any file type (binary or text)\\n- Auto-creates parent directories if missing\\n- Handles large files efficiently with streaming\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 100MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n- Will overwrite existing files without warning\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"},\"name\":\"edit\",\"description\":\"Edits files by replacing text, creating new files, or deleting content. For moving/renaming use Bash 'mv'. For large edits use Write tool.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. old_string: Text to replace (must match exactly including whitespace/indentation)\\n3. new_string: Replacement text\\n4. replace_all: Replace all occurrences (default false)\\n\\u003c/parameters\\u003e\\n\\n\\u003cspecial_cases\\u003e\\n- Create file: provide file_path + new_string, leave old_string empty\\n- Delete content: provide file_path + old_string, leave new_string empty\\n\\u003c/special_cases\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\nUNIQUENESS (when replace_all=false): old_string MUST uniquely identify target instance\\n\\n- Include 3-5 lines context BEFORE and AFTER change point\\n- Include exact whitespace, indentation, surrounding code\\n\\nSINGLE INSTANCE: Tool changes ONE instance when replace_all=false\\n\\n- For multiple instances: set replace_all=true OR make separate calls with unique context\\n- Plan calls carefully to avoid conflicts\\n\\nVERIFICATION: Before using\\n\\n- Check how many instances of target text exist\\n- Gather sufficient context for unique identification\\n- Plan separate calls or use replace_all\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\nTool fails if:\\n- old_string matches multiple locations and replace_all=false\\n- old_string doesn't match exactly (including whitespace)\\n- Insufficient context causes wrong instance change\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use forward slashes (/) for cross-platform compatibility\\n- Multiple edits to same file: send all in single message with multiple tool calls\\n\\u003c/best_practices\\u003e\\n\\n\\u003cwindows_notes\\u003e\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n\\u003c/windows_notes\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"},\"name\":\"multiedit\",\"description\":\"Makes multiple edits to a single file in one operation. Built on Edit tool for efficient multiple find-and-replace operations. Prefer over Edit tool for multiple edits to same file.\\n\\n\\u003cprerequisites\\u003e\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n\\u003c/prerequisites\\u003e\\n\\n\\u003cparameters\\u003e\\n1. file_path: Absolute path to file (required)\\n2. edits: Array of edit operations, each containing:\\n - old_string: Text to replace (must match exactly including whitespace/indentation)\\n - new_string: Replacement text\\n - replace_all: Replace all occurrences (optional, defaults to false)\\n\\u003c/parameters\\u003e\\n\\n\\u003coperation\\u003e\\n- Edits applied sequentially in provided order\\n- Each edit operates on result of previous edit\\n- All edits must be valid for operation to succeed - if any fails, none applied\\n- Ideal for several changes to different parts of same file\\n\\u003c/operation\\u003e\\n\\n\\u003ccritical_requirements\\u003e\\n1. All edits follow same requirements as single Edit tool\\n2. Edits are atomic - either all succeed or none applied\\n3. Plan edits carefully to avoid conflicts between sequential operations\\n\\u003c/critical_requirements\\u003e\\n\\n\\u003cwarnings\\u003e\\n- Tool fails if old_string doesn't match file contents exactly (including whitespace)\\n- Tool fails if old_string and new_string are identical\\n- Earlier edits may affect text that later edits try to find - plan sequence carefully\\n\\u003c/warnings\\u003e\\n\\n\\u003cbest_practices\\u003e\\n- Ensure all edits result in correct, idiomatic code\\n- Don't leave code in broken state\\n- Use absolute file paths (starting with /)\\n- Use replace_all for renaming variables across file\\n- Avoid adding emojis unless user explicitly requests\\n\\u003c/best_practices\\u003e\\n\\n\\u003cnew_file_creation\\u003e\\n- Provide new file path (including directory if needed)\\n- First edit: empty old_string, new file contents as new_string\\n- Subsequent edits: normal edit operations on created content\\n\\u003c/new_file_creation\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"},\"name\":\"fetch\",\"description\":\"Fetches content from URL and returns it in specified format.\\n\\n\\u003cusage\\u003e\\n- Provide URL to fetch content from\\n- Specify desired output format (text, markdown, or html)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Supports three output formats: text, markdown, html\\n- Auto-handles HTTP redirects\\n- Sets reasonable timeouts to prevent hanging\\n- Validates input parameters before requests\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max response size: 5MB\\n- Only supports HTTP and HTTPS protocols\\n- Cannot handle authentication or cookies\\n- Some websites may block automated requests\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use text format for plain text content or simple API responses\\n- Use markdown format for content that should be rendered with formatting\\n- Use html format when you need raw HTML structure\\n- Set appropriate timeouts for potentially slow websites\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"glob\",\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide glob pattern to match against file paths\\n- Optional starting directory (defaults to current working directory)\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cpattern_syntax\\u003e\\n- '\\\\*' matches any sequence of non-separator characters\\n- '\\\\*\\\\*' matches any sequence including separators\\n- '?' matches any single non-separator character\\n- '[...]' matches any character in brackets\\n- '[!...]' matches any character not in brackets\\n\\u003c/pattern_syntax\\u003e\\n\\n\\u003cexamples\\u003e\\n- '*.js' - JavaScript files in current directory\\n- '**/*.js' - JavaScript files in any subdirectory\\n- 'src/**/*.{ts,tsx}' - TypeScript files in src directory\\n- '*.{html,css,js}' - HTML, CSS, and JS files\\n\\u003c/examples\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Does not search file contents (use Grep for that)\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Path separators handled automatically (/ and \\\\ work)\\n- Uses ripgrep (rg) if available, otherwise Go implementation\\n- Patterns should use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Combine with Grep: find files with Glob, search contents with Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine pattern if needed\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"},\"name\":\"grep\",\"description\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n\\u003cusage\\u003e\\n- Provide regex pattern to search within file contents\\n- Set literal_text=true for exact text with special characters (recommended for non-regex users)\\n- Optional starting directory (defaults to current working directory)\\n- Optional include pattern to filter which files to search\\n- Results sorted with most recently modified files first\\n\\u003c/usage\\u003e\\n\\n\\u003cregex_syntax\\u003e\\nWhen literal_text=false (supports standard regex):\\n\\n- 'function' searches for literal text \\\"function\\\"\\n- 'log\\\\..\\\\*Error' finds text starting with \\\"log.\\\" and ending with \\\"Error\\\"\\n- 'import\\\\s+.\\\\*\\\\s+from' finds import statements in JavaScript/TypeScript\\n\\u003c/regex_syntax\\u003e\\n\\n\\u003cinclude_patterns\\u003e\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n\\u003c/include_patterns\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 100 files (newest first)\\n- Performance depends on number of files searched\\n- Very large binary files may be skipped\\n- Hidden files (starting with '.') skipped\\n\\u003c/limitations\\u003e\\n\\n\\u003cignore_support\\u003e\\n- Respects .gitignore patterns to skip ignored files/directories\\n- Respects .crushignore patterns for additional ignore rules\\n- Both ignore files auto-detected in search root directory\\n\\u003c/ignore_support\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Uses ripgrep (rg) if available for better performance\\n- Falls back to Go implementation if ripgrep unavailable\\n- File paths normalized automatically for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- For faster searches: use Glob to find relevant files first, then Grep\\n- For iterative exploration requiring multiple searches, consider Agent tool\\n- Check if results truncated and refine search pattern if needed\\n- Use literal_text=true for exact text with special characters (dots, parentheses, etc.)\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[\"path\"],\"type\":\"object\"},\"name\":\"ls\",\"description\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n\\u003cusage\\u003e\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Hierarchical view of files and directories\\n- Auto-skips hidden files/directories (starting with '.')\\n- Skips common system directories like __pycache__\\n- Can filter files matching specific patterns\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Results limited to 1000 files\\n- Large directories truncated\\n- No file sizes or permissions shown\\n- Cannot recursively list all directories in large projects\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Hidden file detection uses Unix convention (files starting with '.')\\n- Windows hidden files (with hidden attribute) not auto-skipped\\n- Common Windows directories (System32, Program Files) not in default ignore\\n- Path separators handled automatically (/ and \\\\ work)\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use Glob for finding files by name patterns instead of browsing\\n- Use Grep for searching file contents\\n- Combine with other tools for effective exploration\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"},\"name\":\"sourcegraph\",\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n\\u003cusage\\u003e\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n\\u003c/usage\\u003e\\n\\n\\u003cbasic_syntax\\u003e\\n- \\\"fmt.Println\\\" - exact matches\\n- \\\"file:.go fmt.Println\\\" - limit to Go files\\n- \\\"repo:^github\\\\.com/golang/go$ fmt.Println\\\" - specific repos\\n- \\\"lang:go fmt.Println\\\" - limit to Go code\\n- \\\"fmt.Println AND log.Fatal\\\" - combined terms\\n- \\\"fmt\\\\.(Print|Printf|Println)\\\" - regex patterns\\n- \\\"\\\\\\\"exact phrase\\\\\\\"\\\" - exact phrase matching\\n- \\\"-file:test\\\" or \\\"-repo:forks\\\" - exclude matches\\n\\u003c/basic_syntax\\u003e\\n\\n\\u003ckey_filters\\u003e\\nRepository: repo:name, repo:^exact$, repo:org/repo@branch, -repo:exclude, fork:yes, archived:yes, visibility:public\\nFile: file:\\\\.js$, file:internal/, -file:test, file:has.content(text)\\nContent: content:\\\"exact\\\", -content:\\\"unwanted\\\", case:yes\\nType: type:symbol, type:file, type:path, type:diff, type:commit\\nTime: after:\\\"1 month ago\\\", before:\\\"2023-01-01\\\", author:name, message:\\\"fix\\\"\\nResult: select:repo, select:file, select:content, count:100, timeout:30s\\n\\u003c/key_filters\\u003e\\n\\n\\u003cexamples\\u003e\\n- \\\"file:.go context.WithTimeout\\\" - Go code using context.WithTimeout\\n- \\\"lang:typescript useState type:symbol\\\" - TypeScript React useState hooks\\n- \\\"repo:^github\\\\.com/kubernetes/kubernetes$ pod list type:file\\\" - Kubernetes pod files\\n- \\\"file:Dockerfile (alpine OR ubuntu) -content:alpine:latest\\\" - Dockerfiles with base images\\n\\u003c/examples\\u003e\\n\\n\\u003cboolean_operators\\u003e\\n- \\\"term1 AND term2\\\" - both terms\\n- \\\"term1 OR term2\\\" - either term\\n- \\\"term1 NOT term2\\\" - term1 but not term2\\n- \\\"term1 and (term2 or term3)\\\" - grouping with parentheses\\n\\u003c/boolean_operators\\u003e\\n\\n\\u003climitations\\u003e\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n\\u003c/limitations\\u003e\\n\\n\\u003ctips\\u003e\\n- Use specific file extensions to narrow results\\n- Add repo: filters for targeted searches\\n- Use type:symbol for function/method definitions\\n- Use type:file to find relevant files\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 2000)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"},\"name\":\"view\",\"description\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n\\u003cusage\\u003e\\n- Provide file path to read\\n- Optional offset: start reading from specific line (0-based)\\n- Optional limit: control lines read (default 2000)\\n- Don't use for directories (use LS tool instead)\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Displays contents with line numbers\\n- Can read from any file position using offset\\n- Handles large files by limiting lines read\\n- Auto-truncates very long lines for display\\n- Suggests similar filenames when file not found\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines \\u003e2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Handles Windows (CRLF) and Unix (LF) line endings\\n- Works with forward slashes (/) and backslashes (\\\\)\\n- Auto-detects text encoding for common formats\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use with Glob to find files first\\n- For code exploration: Grep to find relevant files, then View to examine\\n- For large files: use offset parameter for specific sections\\n\\u003c/tips\\u003e\\n\"},{\"input_schema\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"},\"name\":\"write\",\"description\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n\\u003cusage\\u003e\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n\\u003c/usage\\u003e\\n\\n\\u003cfeatures\\u003e\\n- Creates new files or overwrites existing ones\\n- Auto-creates parent directories if missing\\n- Checks if file modified since last read for safety\\n- Avoids unnecessary writes when content unchanged\\n\\u003c/features\\u003e\\n\\n\\u003climitations\\u003e\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n\\u003c/limitations\\u003e\\n\\n\\u003ccross_platform\\u003e\\n- Use forward slashes (/) for compatibility\\n\\u003c/cross_platform\\u003e\\n\\n\\u003ctips\\u003e\\n- Use View tool first to examine existing files before modifying\\n- Use LS tool to verify location when creating new files\\n- Combine with Glob/Grep to find and modify multiple files\\n- Include descriptive comments when changing existing code\\n\\u003c/tips\\u003e\\n\",\"cache_control\":{\"type\":\"ephemeral\"}}],\"stream\":true}"
187− headers:
188− Accept:
189− - application/json
190− Content-Type:
191− - application/json
192− User-Agent:
193− - Anthropic/Go 1.12.0
194− url: https://api.anthropic.com/v1/messages
195− method: POST
196− response:
197− proto: HTTP/2.0
198− proto_major: 2
199− proto_minor: 0
200− content_length: -1
201− body: |+
202− event: message_start
203− data: {"type":"message_start","message":{"model":"claude-sonnet-4-5-20250929","id":"msg_012m9RadV58H14GKHAK3vy9V","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":5,"cache_creation_input_tokens":155,"cache_read_input_tokens":8674,"cache_creation":{"ephemeral_5m_input_tokens":155,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
204−
205− event: content_block_start
206− data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
207−
208− event: content_block_delta
209− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Create"} }
210−
211− event: content_block_delta
212− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d `config.json` with the specifie"}}
213−
214− event: ping
215− data: {"type": "ping"}
216−
217− event: content_block_delta
218− data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d content."}}
219−
220− event: ping
221− data: {"type": "ping"}
222−
223− event: content_block_stop
224− data: {"type":"content_block_stop","index":0}
225−
226− event: ping
227− data: {"type": "ping"}
228−
229− event: ping
230− data: {"type": "ping"}
231−
232− event: message_delta
233− data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":5,"cache_creation_input_tokens":155,"cache_read_input_tokens":8674,"output_tokens":14} }
234−
235− event: message_stop
236− data: {"type":"message_stop" }
237−
238− headers:
239− Content-Type:
240− - text/event-stream; charset=utf-8
241− status: 200 OK
242− code: 200
243− duration: 2.228601375s
internal/agent/testdata/TestCoderAgent/glm-5.1/bash_tool.yamlnew file+425
@@ -0,0 +1,425 @@
1+---
2+version: 2
3+interactions:
4+- id: 0
5+ request:
6+ proto: HTTP/1.1
7+ proto_major: 1
8+ proto_minor: 1
9+ content_length: 853
10+ host: ""
11+ body: '{"messages":[{"content":"You will generate a short title based on the first message a user begins a conversation with.\n\n<rules>\n- Keep the title in the same language that the user wrote their message in.\n- Ensure it is not more than 50 characters long.\n- The title should be a summary of the user''s message.\n- It should be one line long.\n- Do not use quotes or colons.\n- The entire text you return will be used as the title.\n- Never return anything that is more than one sentence (one line) long.\n</rules>\n\n /no_think","role":"system"},{"content":"Generate a concise title for the following content:\n\nuse bash to create a file named test.txt with content ''hello bash''. do not print its timestamp\n <think>\n\n</think>","role":"user"}],"model":"gpt-oss-120b","max_completion_tokens":40,"stream_options":{"include_usage":true},"stream":true}'
12+ headers:
13+ Accept:
14+ - application/json
15+ Content-Type:
16+ - application/json
17+ User-Agent:
18+ - Charm-Crush/devel (https://charm.land/crush)
19+ url: https://hyper.charm.land/v1/chat/completions
20+ method: POST
21+ response:
22+ proto: HTTP/2.0
23+ proto_major: 2
24+ proto_minor: 0
25+ content_length: -1
26+ uncompressed: true
27+ body: |+
28+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
29+
30+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"We"},"finish_reason":null}]}
31+
32+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" need"},"finish_reason":null}]}
33+
34+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" to"},"finish_reason":null}]}
35+
36+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" generate"},"finish_reason":null}]}
37+
38+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" a"},"finish_reason":null}]}
39+
40+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" short"},"finish_reason":null}]}
41+
42+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" title"},"finish_reason":null}]}
43+
44+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" based"},"finish_reason":null}]}
45+
46+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" on"},"finish_reason":null}]}
47+
48+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" the"},"finish_reason":null}]}
49+
50+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" user's"},"finish_reason":null}]}
51+
52+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" first"},"finish_reason":null}]}
53+
54+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" message"},"finish_reason":null}]}
55+
56+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
57+
58+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" The"},"finish_reason":null}]}
59+
60+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" user"},"finish_reason":null}]}
61+
62+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" wrote"},"finish_reason":null}]}
63+
64+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" in"},"finish_reason":null}]}
65+
66+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" English"},"finish_reason":null}]}
67+
68+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
69+
70+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Title"},"finish_reason":null}]}
71+
72+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" must"},"finish_reason":null}]}
73+
74+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" be"},"finish_reason":null}]}
75+
76+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \u003c="},"finish_reason":null}]}
77+
78+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"50"},"finish_reason":null}]}
79+
80+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" characters"},"finish_reason":null}]}
81+
82+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
83+
84+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" no"},"finish_reason":null}]}
85+
86+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" quotes"},"finish_reason":null}]}
87+
88+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"/"},"finish_reason":null}]}
89+
90+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"col"},"finish_reason":null}]}
91+
92+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"ons"},"finish_reason":null}]}
93+
94+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
95+
96+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" one"},"finish_reason":null}]}
97+
98+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" line"},"finish_reason":null}]}
99+
100+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
101+
102+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" no"},"finish_reason":null}]}
103+
104+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" more"},"finish_reason":null}]}
105+
106+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" than"},"finish_reason":null}]}
107+
108+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" one"},"finish_reason":null}]}
109+
110+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" sentence"},"finish_reason":null}]}
111+
112+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
113+
114+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Summ"},"finish_reason":null}]}
115+
116+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"ar"},"finish_reason":null}]}
117+
118+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"ize"},"finish_reason":null}]}
119+
120+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
121+
122+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
123+
124+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"bash"},"finish_reason":null}]}
125+
126+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" create"},"finish_reason":null}]}
127+
128+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" test"},"finish_reason":null}]}
129+
130+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".txt"},"finish_reason":null}]}
131+
132+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" with"},"finish_reason":null}]}
133+
134+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" hello"},"finish_reason":null}]}
135+
136+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" bash"},"finish_reason":null}]}
137+
138+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" without"},"finish_reason":null}]}
139+
140+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" timestamp"},"finish_reason":null}]}
141+
142+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\"."},"finish_reason":null}]}
143+
144+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Let's"},"finish_reason":null}]}
145+
146+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" craft"},"finish_reason":null}]}
147+
148+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
149+
150+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
151+
152+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Create"},"finish_reason":null}]}
153+
154+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" test"},"finish_reason":null}]}
155+
156+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".txt"},"finish_reason":null}]}
157+
158+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" with"},"finish_reason":null}]}
159+
160+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" hello"},"finish_reason":null}]}
161+
162+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" bash"},"finish_reason":null}]}
163+
164+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" using"},"finish_reason":null}]}
165+
166+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Bash"},"finish_reason":null}]}
167+
168+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\"."},"finish_reason":null}]}
169+
170+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" That's"},"finish_reason":null}]}
171+
172+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" under"},"finish_reason":null}]}
173+
174+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
175+
176+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"50"},"finish_reason":null}]}
177+
178+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
179+
180+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Count"},"finish_reason":null}]}
181+
182+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
183+
184+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
185+
186+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Create"},"finish_reason":null}]}
187+
188+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" test"},"finish_reason":null}]}
189+
190+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".txt"},"finish_reason":null}]}
191+
192+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" with"},"finish_reason":null}]}
193+
194+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" hello"},"finish_reason":null}]}
195+
196+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" bash"},"finish_reason":null}]}
197+
198+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" using"},"finish_reason":null}]}
199+
200+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Bash"},"finish_reason":null}]}
201+
202+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\""},"finish_reason":null}]}
203+
204+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ="},"finish_reason":null}]}
205+
206+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
207+
208+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"38"},"finish_reason":null}]}
209+
210+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" characters"},"finish_reason":null}]}
211+
212+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
213+
214+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" No"},"finish_reason":null}]}
215+
216+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" quotes"},"finish_reason":null}]}
217+
218+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
219+
220+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Good"},"finish_reason":null}]}
221+
222+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
223+
224+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":"Create"},"finish_reason":null}]}
225+
226+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" test"},"finish_reason":null}]}
227+
228+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":".txt"},"finish_reason":null}]}
229+
230+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" with"},"finish_reason":null}]}
231+
232+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" hello"},"finish_reason":null}]}
233+
234+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" bash"},"finish_reason":null}]}
235+
236+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" using"},"finish_reason":null}]}
237+
238+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" Bash"},"finish_reason":null}]}
239+
240+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
241+
242+ data: {"id":"chatcmpl-9b4429c7811fb2c7070cc503","object":"chat.completion.chunk","created":1782413792,"model":"gpt-oss-120b","choices":[],"usage":{"prompt_tokens":224,"completion_tokens":115,"total_tokens":339,"completion_tokens_details":{"reasoning_tokens":98},"cost":{"usd":0.00015733800000000003,"hypercredits":0.0031467600000000006},"remaining":{"hypercredits":0}}}
243+
244+ data: [DONE]
245+
246+ headers:
247+ Content-Type:
248+ - text/event-stream
249+ status: 200 OK
250+ code: 200
251+ duration: 700.546792ms
252+- id: 1
253+ request:
254+ proto: HTTP/1.1
255+ proto_major: 1
256+ proto_minor: 1
257+ content_length: 35672
258+ host: ""
259+ body: "{\"messages\":[{\"content\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\n\\n<critical_rules>\\nThese rules override everything else. Follow them strictly:\\n\\n1. **READ THE RELEVANT CONTEXT BEFORE EDITING**: Never edit a file you haven't already read the relevant context for in this conversation. Once read, you don't need to re-read unless it changed. Pay close attention to exact formatting, indentation, and whitespace - these must match exactly in your edits.\\n2. **BE AUTONOMOUS**: Don't ask questions - search, read, think, decide, act. Break complex tasks into steps and complete them all. Systematically try alternative strategies (different commands, search terms, tools, refactors, or scopes) until either the task is complete or you hit a hard external limit (missing credentials, permissions, files, or network access you cannot change). Only stop for actual blocking errors, not perceived difficulty.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification.\\n4. **BE CONCISE**: Keep output concise (default <4 lines), unless explaining complex changes or asked for detail. Conciseness applies to output only, not to thoroughness of work.\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks.\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\". When committing, follow the `<git_commits>` format from the bash tool description exactly, including any configured attribution lines.\\n7. **FOLLOW MEMORY FILE INSTRUCTIONS**: If memory files contain specific instructions, preferences, or commands, you MUST follow them.\\n8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so. Focus on *why* not *what*. NEVER communicate with the user through code comments.\\n9. **SECURITY FIRST**: Only assist with defensive security tasks. Refuse to create, modify, or improve code that may be used maliciously.\\n10. **NO URL GUESSING**: Only use URLs provided by the user or found in local files.\\n11. **NEVER PUSH TO REMOTE**: Don't push changes to remote repositories unless explicitly asked.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **TOOL CONSTRAINTS**: Only use documented tools. Never attempt 'apply_patch' or 'apply_diff' - they don't exist. Use 'edit' or 'multiedit' instead.\\n14. **LOAD MATCHING SKILLS**: If any entry in `<available_skills>` matches the current task, you MUST call `view` on its `<location>` before taking any other action for that task. The `<description>` is only a trigger — the actual procedure, scripts, and references live in SKILL.md. Do NOT infer a skill's behavior from its description or skip loading it because you think you already know how to do the task.\\n15. **LIMIT FILE READS**: Avoid reading entire files, as they can be very large. Read only the sections you need using 'offset' and 'limit' parameters.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- ALWAYS think and respond in the same spoken language the prompt was written in.\\n- Under 4 lines of text (tool use doesn't count)\\n- Conciseness is about **text only**: always fully implement the requested feature, tests, and wiring even if that requires many tool calls.\\n- No preamble (\\\"Here's...\\\", \\\"I'll...\\\")\\n- No postamble (\\\"Let me know...\\\", \\\"Hope this helps...\\\")\\n- One-word answers when possible\\n- No emojis ever\\n- No explanations unless user asks\\n- Never send acknowledgement-only responses; after receiving new context or instructions, immediately continue the task or state the concrete next action you will take.\\n- Use rich Markdown formatting (headings, bullet lists, tables, code fences) for any multi-sentence or explanatory answer; only use plain unformatted text if the user explicitly asks.\\n\\nExamples:\\nuser: what is 2+2?\\nassistant: 4\\n\\nuser: list files in src/\\nassistant: [uses ls tool]\\nfoo.c, bar.c, baz.c\\n\\nuser: which file has the foo implementation?\\nassistant: src/foo.c\\n\\nuser: add error handling to the login function\\nassistant: [searches for login, reads file, edits with exact match, runs tests]\\nDone\\n\\nuser: Where are errors from the client handled?\\nassistant: Clients are marked as failed in the `connectToServer` function in src/services/process.go:712.\\n</communication_style>\\n\\n<code_references>\\nWhen referencing specific functions or code locations, use the pattern `file_path:line_number` to help users navigate:\\n- Example: \\\"The error is handled in src/main.go:45\\\"\\n- Example: \\\"See the implementation in pkg/utils/helper.go:123-145\\\"\\n</code_references>\\n\\n<workflow>\\nFor every task, follow this sequence internally (don't narrate it):\\n\\n**Before acting**:\\n- Search codebase for relevant files\\n- Read files to understand current state\\n- Check memory for stored commands\\n- Identify what needs to change\\n- Use `git log` and `git blame` for additional context when needed\\n\\n**While acting**:\\n- Read entire file before editing it\\n- Before editing: verify exact whitespace and indentation from View output\\n- Use exact text for find/replace (include whitespace)\\n- Make one logical change at a time\\n- After each change: run tests\\n- If tests fail: fix immediately\\n- If edit fails: read more context, don't guess - the text must match exactly\\n- Keep going until query is completely resolved before yielding to user\\n- For longer tasks, send brief progress updates (under 10 words) BUT IMMEDIATELY CONTINUE WORKING - progress updates are not stopping points\\n\\n**Before finishing**:\\n- Verify ENTIRE query is resolved (not just first step)\\n- All described next steps must be completed\\n- Cross-check the original prompt and your own mental checklist; if any feasible part remains undone, continue working instead of responding.\\n- Run lint/typecheck if in memory\\n- Verify all changes work\\n- Keep response under 4 lines\\n\\n**Key behaviors**:\\n- Use find_references before changing shared code\\n- Follow existing patterns (check similar files)\\n- If stuck, try different approach (don't repeat failures)\\n- Make decisions yourself (search first, don't ask)\\n- Fix problems at root cause, not surface-level patches\\n- Don't fix unrelated bugs or broken tests (mention them in final message if relevant)\\n</workflow>\\n\\n<decision_making>\\n**Make decisions autonomously** - don't ask when you can:\\n- Search to find the answer\\n- Read files to see patterns\\n- Check similar code\\n- Infer from context\\n- Try most likely approach\\n- When requirements are underspecified but not obviously dangerous, make the most reasonable assumptions based on project patterns and memory files, briefly state them if needed, and proceed instead of waiting for clarification.\\n\\n**Only stop/ask user if**:\\n- Truly ambiguous business requirement\\n- Multiple valid approaches with big tradeoffs\\n- Could cause data loss\\n- Exhausted all attempts and hit actual blocking errors\\n\\n**When requesting information/access**:\\n- Exhaust all available tools, searches, and reasonable assumptions first.\\n- Never say \\\"Need more info\\\" without detail.\\n- In the same message, list each missing item, why it is required, acceptable substitutes, and what you already attempted.\\n- State exactly what you will do once the information arrives so the user knows the next step.\\n\\nWhen you must stop, first finish all unblocked parts of the request, then clearly report: (a) what you tried, (b) exactly why you are blocked, and (c) the minimal external action required. Don't stop just because one path failed—exhaust multiple plausible approaches first.\\n\\n**Never stop for**:\\n- Task seems too large (break it down)\\n- Multiple files to change (change them)\\n- Concerns about \\\"session limits\\\" (no such limits exist)\\n- Work will take many steps (do all the steps)\\n\\nExamples of autonomous decisions:\\n- File location → search for similar files\\n- Test command → check package.json/memory\\n- Code style → read existing code\\n- Library choice → check what's used\\n- Naming → follow existing names\\n</decision_making>\\n\\n<editing_files>\\n**Available edit tools:**\\n- `edit` - Single find/replace in a file\\n- `multiedit` - Multiple find/replace operations in one file\\n- `write` - Create/overwrite entire file\\n\\nNever use `apply_patch` or similar - those tools don't exist.\\n\\nCritical: ALWAYS read the relevant context of files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the relevant context first - note the EXACT indentation (spaces vs tabs, count)\\n2. Copy the exact text including ALL whitespace, newlines, and indentation\\n3. Include 3-5 lines of context before and after the target\\n4. Verify your old_string would appear exactly once in the file\\n5. If uncertain about whitespace, include more surrounding context\\n6. Verify edit succeeded\\n7. Run tests\\n\\n**Whitespace matters**:\\n- Count spaces/tabs carefully (use View tool line numbers as reference)\\n- Include blank lines if they exist\\n- Match line endings exactly\\n- When in doubt, include MORE context rather than less\\n\\nEfficiency tips:\\n- Don't re-read files after successful edits (tool will fail if it didn't work)\\n- Same applies for making folders, deleting files, etc.\\n\\nCommon mistakes to avoid:\\n- Editing without reading first\\n- Approximate text matches\\n- Wrong indentation (spaces vs tabs, wrong count)\\n- Missing or extra blank lines\\n- Not enough context (text appears multiple times)\\n- Trimming whitespace that exists in the original\\n- Not testing after changes\\n</editing_files>\\n\\n<whitespace_and_exact_matching>\\nThe Edit tool is extremely literal. \\\"Close enough\\\" will fail.\\n\\n**Before every edit**:\\n1. View the file and locate the exact lines to change\\n2. Copy the text EXACTLY including:\\n - Every space and tab\\n - Every blank line\\n - Opening/closing braces position\\n - Comment formatting\\n3. Include enough surrounding lines (3-5) to make it unique\\n4. Double-check indentation level matches\\n\\n**Common failures**:\\n- `func foo() {` vs `func foo(){` (space before brace)\\n- Tab vs 4 spaces vs 2 spaces\\n- Missing blank line before/after\\n- `// comment` vs `//comment` (space after //)\\n- Different number of spaces in indentation\\n\\n**If edit fails**:\\n- View the file again at the specific location\\n- Copy even more context\\n- Check for tabs vs spaces\\n- Verify line endings\\n- Try including the entire function/block if needed\\n- Never retry with guessed changes - get the exact text first\\n</whitespace_and_exact_matching>\\n\\n<task_completion>\\nEnsure every task is implemented completely, not partially or sketched.\\n\\n1. **Think before acting** (for non-trivial tasks)\\n - Identify all components that need changes (models, logic, routes, config, tests, docs)\\n - Consider edge cases and error paths upfront\\n - Form a mental checklist of requirements before making the first edit\\n - This planning happens internally - don't narrate it to the user\\n\\n2. **Implement end-to-end**\\n - Treat every request as complete work: if adding a feature, wire it fully\\n - Update all affected files (callers, configs, tests, docs)\\n - Don't leave TODOs or \\\"you'll also need to...\\\" - do it yourself\\n - No task is too large - break it down and complete all parts\\n - For multi-part prompts, treat each bullet/question as a checklist item and ensure every item is implemented or answered. Partial completion is not an acceptable final state.\\n\\n3. **Verify before finishing**\\n - Re-read the original request and verify each requirement is met\\n - Check for missing error handling, edge cases, or unwired code\\n - Run tests to confirm the implementation works\\n - Only say \\\"Done\\\" when truly done - never stop mid-task\\n</task_completion>\\n\\n<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause (isolate with debug logs or minimal reproduction if needed)\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\n7. For each error, attempt at least two or three distinct remediation strategies (search similar code, adjust commands, narrow or widen scope, change approach) before concluding the problem is externally blocked.\\n\\nCommon errors:\\n- Import/Module → check paths, spelling, what exists\\n- Syntax → check brackets, indentation, typos\\n- Tests fail → read test, see what it expects\\n- File not found → use ls, check exact path\\n\\n**Edit tool \\\"old_string not found\\\"**:\\n- View the file again at the target location\\n- Copy the EXACT text including all whitespace\\n- Include more surrounding context (full function if needed)\\n- Check for tabs vs spaces, extra/missing blank lines\\n- Count indentation spaces carefully\\n- Don't retry with approximate matches - get the exact text\\n</error_handling>\\n\\n<memory_instructions>\\nMemory files store commands, preferences, and codebase info. Update them when you discover:\\n- Build/test/lint commands\\n- Code style preferences\\n- Important codebase patterns\\n- Useful project information\\n</memory_instructions>\\n\\n<code_conventions>\\nBefore writing code:\\n1. Check if library exists (look at imports, package.json)\\n2. Read similar code for patterns\\n3. Match existing style\\n4. Use same libraries/frameworks\\n5. Follow security best practices (never log secrets)\\n6. Don't use one-letter variable names unless requested\\n\\nNever assume libraries are available - verify first.\\n\\n**Ambition vs. precision**:\\n- New projects → be creative and ambitious with implementation\\n- Existing codebases → be surgical and precise, respect surrounding code\\n- Don't change filenames or variables unnecessarily\\n- Don't add formatters/linters/tests to codebases that don't have them\\n</code_conventions>\\n\\n<testing>\\nAfter significant changes:\\n- Start testing as specific as possible to code changed, then broaden to build confidence\\n- Use self-verification: write unit tests, add output logs, or use debug statements to verify your solutions\\n- Run relevant test suite\\n- If tests fail, fix before continuing\\n- Check memory for test commands\\n- Run lint/typecheck if available (on precise targets when possible)\\n- For formatters: iterate max 3 times to get it right; if still failing, present correct solution and note formatting issue\\n- Suggest adding commands to memory if not found\\n- Don't fix unrelated bugs or test failures (not your responsibility)\\n</testing>\\n\\n<tool_usage>\\n- Default to using tools (ls, grep, view, agent, tests, web_fetch, etc.) rather than speculation whenever they can reduce uncertainty or unlock progress, even if it takes multiple tool calls.\\n- Search before assuming\\n- Read files before editing\\n- Always use absolute paths for file operations (editing, reading, writing)\\n- Use Agent tool for complex searches\\n- Run tools in parallel when safe (no dependencies)\\n- When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution\\n- Summarize tool output for user (they don't see it)\\n- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.\\n- Only use the tools you know exist.\\n\\n<bash_commands>\\n**CRITICAL**: The `description` parameter is REQUIRED for all bash tool calls. Always provide it.\\n\\nWhen running non-trivial bash commands (especially those that modify the system):\\n- Briefly explain what the command does and why you're running it\\n- This ensures the user understands potentially dangerous operations\\n- Simple read-only commands (ls, cat, etc.) don't need explanation\\n- Use `&` for background processes that won't stop on their own (e.g., `node server.js &`)\\n- Avoid interactive commands - use non-interactive versions (e.g., `npm init -y` not `npm init`)\\n- Combine related commands to save time (e.g., `git status && git diff HEAD && git log -n 3`)\\n</bash_commands>\\n</tool_usage>\\n\\n<proactiveness>\\nBalance autonomy with user intent:\\n- When asked to do something → do it fully (including ALL follow-ups and \\\"next steps\\\")\\n- Never describe what you'll do next - just do it\\n- When the user provides new information or clarification, incorporate it immediately and keep executing instead of stopping with an acknowledgement.\\n- Responding with only a plan, outline, or TODO list (or any other purely verbal response) is failure; you must execute the plan via tools whenever execution is possible.\\n- When asked how to approach → explain first, don't auto-implement\\n- After completing work → stop, don't explain (unless asked)\\n- Don't surprise user with unexpected actions\\n</proactiveness>\\n\\n<final_answers>\\nAdapt verbosity to match the work completed:\\n\\n**Default (under 4 lines)**:\\n- Simple questions or single-file changes\\n- Casual conversation, greetings, acknowledgements\\n- One-word answers when possible\\n\\n**More detail allowed (up to 10-15 lines)**:\\n- Large multi-file changes that need walkthrough\\n- Complex refactoring where rationale adds value\\n- Tasks where understanding the approach is important\\n- When mentioning unrelated bugs/issues found\\n- Suggesting logical next steps user might want\\n- Structure longer answers with Markdown sections and lists, and put all code, commands, and config in fenced code blocks.\\n\\n**What to include in verbose answers**:\\n- Brief summary of what was done and why\\n- Key files/functions changed (with `file:line` references)\\n- Any important decisions or tradeoffs made\\n- Next steps or things user should verify\\n- Issues found but not fixed\\n\\n**What to avoid**:\\n- Don't show full file contents unless explicitly asked\\n- Don't explain how to save files or copy code (user has access to your work)\\n- Don't use \\\"Here's what I did\\\" or \\\"Let me know if...\\\" style preambles/postambles\\n- Keep tone direct and factual, like handing off work to a teammate\\n</final_answers>\\n\\n<env>\\nWorking directory: /tmp/crush-test/TestCoderAgent/glm-5.1/bash_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n<available_skills>\\n <skill>\\n <name>crush-hooks</name>\\n <description>Use when the user wants to add, write, debug, or configure a Crush hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in crush.json.</description>\\n <location>crush://skills/crush-hooks/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n <skill>\\n <name>jq</name>\\n <description>Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.</description>\\n <location>crush://skills/jq/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n</available_skills>\\n\\n<skills_usage>\\nThe `<description>` of each skill is a TRIGGER — it tells you *when* a skill applies. It is NOT a specification of what the skill does or how to do it. The procedure, scripts, commands, references, and required flags live only in the SKILL.md body. You do not know what a skill actually does until you have read its SKILL.md.\\n\\nMANDATORY activation flow:\\n1. Scan `<available_skills>` against the current user task.\\n2. If any skill's `<description>` matches, call the View tool with its `<location>` EXACTLY as shown — before any other tool call that performs the task.\\n3. Read the entire SKILL.md and follow its instructions.\\n4. Only then execute the task, using the skill's prescribed commands/tools.\\n\\nDo NOT skip step 2 because you think you already know how to do the task. Do NOT infer a skill's behavior from its name or description. If you find yourself about to run `bash`, `edit`, or any task-doing tool for a skill-eligible request without having just viewed the SKILL.md, stop and load the skill first.\\n\\nBuiltin skills (type=builtin) use virtual `crush://skills/...` location identifiers. The \\\"crush://\\\" prefix is NOT a URL, network address, or MCP resource — it is a special internal identifier the View tool understands natively. Pass the `<location>` verbatim to View.\\n\\nDo not use MCP tools (including read_mcp_resource) to load skills.\\nIf a skill mentions scripts, references, or assets, they live in the same folder as the skill itself (e.g., scripts/, references/, assets/ subdirectories within the skill's folder).\\n</skills_usage>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"<system_reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.\\nIf you are working on tasks that would benefit from a todo list please use the \\\"todos\\\" tool to create one.\\nIf not, please feel free to ignore. Again do not mention this message to the user.</system_reminder>\",\"role\":\"user\"},{\"content\":\"use bash to create a file named test.txt with content 'hello bash'. do not print its timestamp\",\"role\":\"user\"}],\"model\":\"glm-5.1\",\"max_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Execute shell commands; long-running commands automatically move to background and return a shell ID.\\n\\n<cross_platform>\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n</cross_platform>\\n\\n<execution_steps>\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Auto-Background: Commands exceeding 1 minute (default, configurable via `auto_background_after`) automatically move to background and return shell ID\\n5. Output Processing: Truncate if exceeds 30000 characters\\n6. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\n- Command required, working_dir optional (defaults to current directory)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '&&', avoid newlines except in quoted strings\\n- Each command runs in independent shell (no state persistence between calls)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n</usage_notes>\\n\\n<background_execution>\\n- Set run_in_background=true to run commands in a separate background shell\\n- Returns a shell ID for managing the background process\\n- Use job_output tool to view current output from background shell\\n- Use job_kill tool to terminate a background shell\\n- IMPORTANT: NEVER use `&` at the end of commands to run in background - use run_in_background parameter instead\\n- Commands that should run in background:\\n * Long-running servers (e.g., `npm start`, `python -m http.server`, `node server.js`)\\n * Watch/monitoring tasks (e.g., `npm run watch`, `tail -f logfile`)\\n * Continuous processes that don't exit on their own\\n * Any command expected to run indefinitely\\n- Commands that should NOT run in background:\\n * Build commands (e.g., `npm run build`, `go build`)\\n * Test suites (e.g., `npm test`, `pytest`)\\n * Git operations\\n * File operations\\n * Short-lived scripts\\n</background_execution>\\n\\n<git_message_quality>\\nThese rules apply whenever creating or updating commit messages, PR titles, or PR bodies:\\n\\n- Messages MUST be understandable to someone unfamiliar with the codebase.\\n- Before creating or updating a message, verify this litmus test: a new contributor reading only the commit message or PR title/body should understand what problem this solves, why it matters, and the impact without opening files, reading the diff, or knowing internal code names.\\n- Avoid code identifiers, filenames, function names, and implementation details unless they are necessary for understanding the user-facing impact.\\n- Bad: \\\"Add NameFromHex with sync.Once lazy init\\\"\\n- Good: \\\"Improve color name lookup performance while keeping startup fast\\\"\\n</git_message_quality>\\n\\n<commit_messages>\\nCommit messages are for future readers scanning history. Before committing:\\n\\n- Follow <git_message_quality>.\\n- Draft a concise 1-2 sentence message focusing on why the change exists and what outcome it enables, not a list of files or implementation details.\\n- Use clear, accurate verbs (\\\"add\\\"=new capability, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix) and avoid generic messages.\\n- The first line MUST be under 72 characters.\\n- Add a body only when it is needed to explain the reasoning, tradeoffs, or important context; wrap body lines at 72 characters.\\n- If the change is internal-only, still describe the benefit or maintenance outcome rather than naming private code.\\n- Bad: \\\"fix: nil pointer in session.go\\\"\\n- Good: \\\"fix: prevent session loading from crashing on missing metadata\\\"\\n- Bad: \\\"refactor: move PromptBuilder into internal/agent\\\"\\n- Good: \\\"refactor: make prompt assembly easier to maintain\\\"\\n</commit_messages>\\n\\n<git_commits>\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in <commit_analysis> tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond the context of git\\n\\n4. Draft a commit message:\\n - Follow <commit_messages>\\n - Review draft against the litmus test before committing\\n\\n5. Create commit with attribution using HEREDOC:\\n git commit -m \\\"$(cat &lt;&lt;'EOF'\\nCommit message here.\\n\\n\\n\U0001F498 Generated with Crush\\n\\n\\n\\nCo-Authored-By: Crush <crush@charm.land>\\n\\nEOF\\n)\\\"\\n\\n6. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n7. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response, when rebasing always use -m.\\n</git_commits>\\n\\n<pull_requests>\\n\\n\\nWhen user asks you to create or update a PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n\\n3. Commit changes if needed\\n\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in <pr_analysis> tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n\\n6. Draft a PR message:\\n - Follow <git_message_quality>\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Use clear, concise language\\n - Provide an accurate reflection of changes and purpose\\n - Avoid generic summaries; messages should be thoughtful\\n - Review draft against the litmus test before creating or updating the PR\\n\\n7. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat &lt;&lt;'EOF'\\n\\n<summary>\\n\\n\U0001F498 Generated with Crush\\n\\nEOF\\n)\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"properties\":{\"auto_background_after\":{\"description\":\"Seconds to wait before automatically moving the command to a background job (default: 60)\",\"type\":\"integer\"},\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does, try to keep it under 30 characters or so\",\"type\":\"string\"},\"run_in_background\":{\"description\":\"Set to true (boolean) to run this command in the background. Use job_output to read the output later.\",\"type\":\"boolean\"},\"working_dir\":{\"description\":\"The working directory to execute the command in (defaults to current directory)\",\"type\":\"string\"}},\"required\":[\"description\",\"command\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Download a URL directly to a local file (binary-safe, streaming, max 600s timeout); overwrites without warning. For reading content into context use fetch.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"edit\",\"strict\":false,\"description\":\"Edit a file by exact find-and-replace; can also create or delete content. For renames/moves use bash. For large edits use write.\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiedit\",\"strict\":false,\"description\":\"Apply multiple find-and-replace edits to a single file in one operation; edits run sequentially. Prefer over edit for multiple changes to the same file. Same exact-match rules as edit apply.\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"properties\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"required\":[\"old_string\",\"new_string\"],\"type\":\"object\"},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"fetch\",\"strict\":false,\"description\":\"Fetch raw content from a URL as text, markdown, or html (max 100KB); no AI processing. For analysis or extraction use agentic_fetch.\\n\",\"parameters\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"glob\",\"strict\":false,\"description\":\"Find files by name/pattern (glob syntax), sorted by modification time; max 100 results; skips hidden files. Use grep to search file contents.\\n\",\"parameters\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"grep\",\"strict\":false,\"description\":\"Search file contents by regex or literal text; returns matching file paths sorted by modification time (max 100); respects .gitignore. Use glob to filter by filename, not contents.\\n\",\"parameters\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"ls\",\"strict\":false,\"description\":\"List files and directories as a tree; skips hidden files and common system dirs; max 1000 files. Use glob to find files by pattern, grep to search contents.\\n\",\"parameters\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{\"type\":\"string\"},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public GitHub repositories via Sourcegraph; supports regex, language/repo/file filters, and symbol search (max 20 results). Only searches public repos.\\n\",\"parameters\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"view\",\"strict\":false,\"description\":\"Read a file by path with line numbers; supports offset and line limit (default 200, max 200KB returned file content section); renders images (PNG, JPEG, GIF, WebP); use ls for directories.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 200)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"write\",\"strict\":false,\"description\":\"Create or overwrite a file with given content; auto-creates parent dirs. Cannot append. Read the file first to avoid conflicts. For surgical changes use edit or multiedit.\",\"parameters\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}"
260+ headers:
261+ Accept:
262+ - application/json
263+ Content-Type:
264+ - application/json
265+ User-Agent:
266+ - Charm-Crush/devel (https://charm.land/crush)
267+ url: https://hyper.charm.land/v1/chat/completions
268+ method: POST
269+ response:
270+ proto: HTTP/2.0
271+ proto_major: 2
272+ proto_minor: 0
273+ content_length: -1
274+ uncompressed: true
275+ body: |+
276+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
277+
278+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":"The"},"finish_reason":null}]}
279+
280+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" user"},"finish_reason":null}]}
281+
282+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" wants"},"finish_reason":null}]}
283+
284+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" me"},"finish_reason":null}]}
285+
286+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" to"},"finish_reason":null}]}
287+
288+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" create"},"finish_reason":null}]}
289+
290+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" a"},"finish_reason":null}]}
291+
292+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" file"},"finish_reason":null}]}
293+
294+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" named"},"finish_reason":null}]}
295+
296+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" test"},"finish_reason":null}]}
297+
298+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":".txt"},"finish_reason":null}]}
299+
300+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" with"},"finish_reason":null}]}
301+
302+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" content"},"finish_reason":null}]}
303+
304+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" '"},"finish_reason":null}]}
305+
306+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":"hello"},"finish_reason":null}]}
307+
308+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" bash"},"finish_reason":null}]}
309+
310+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":"'"},"finish_reason":null}]}
311+
312+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" using"},"finish_reason":null}]}
313+
314+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" the"},"finish_reason":null}]}
315+
316+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" bash"},"finish_reason":null}]}
317+
318+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" tool"},"finish_reason":null}]}
319+
320+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
321+
322+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" and"},"finish_reason":null}]}
323+
324+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" not"},"finish_reason":null}]}
325+
326+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" print"},"finish_reason":null}]}
327+
328+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" its"},"finish_reason":null}]}
329+
330+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" timestamp"},"finish_reason":null}]}
331+
332+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
333+
334+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"id":"call_51c682620b31061c","type":"function","index":0,"function":{"name":"bash","arguments":""}}]},"finish_reason":null}]}
335+
336+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"command\": \""}}]},"finish_reason":null}]}
337+
338+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"echo"}}]},"finish_reason":null}]}
339+
340+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" '"}}]},"finish_reason":null}]}
341+
342+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"hello"}}]},"finish_reason":null}]}
343+
344+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" bash"}}]},"finish_reason":null}]}
345+
346+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"'"}}]},"finish_reason":null}]}
347+
348+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" \u003e"}}]},"finish_reason":null}]}
349+
350+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" test"}}]},"finish_reason":null}]}
351+
352+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".txt"}}]},"finish_reason":null}]}
353+
354+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\""}}]},"finish_reason":null}]}
355+
356+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":", \"description\": \""}}]},"finish_reason":null}]}
357+
358+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Create"}}]},"finish_reason":null}]}
359+
360+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" test"}}]},"finish_reason":null}]}
361+
362+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".txt"}}]},"finish_reason":null}]}
363+
364+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" with"}}]},"finish_reason":null}]}
365+
366+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" content"}}]},"finish_reason":null}]}
367+
368+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\""}}]},"finish_reason":null}]}
369+
370+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"finish_reason":null}]}
371+
372+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}]}
373+
374+ data: {"id":"chatcmpl-5baef5f0d9ce99f46bc74840","object":"chat.completion.chunk","created":1782413793,"model":"glm-5.1","choices":[],"usage":{"prompt_tokens":686,"completion_tokens":56,"total_tokens":8221,"prompt_tokens_details":{"cached_tokens":7479},"completion_tokens_details":{"reasoning_tokens":32},"cost":{"usd":0.0013476,"hypercredits":0.026952},"remaining":{"hypercredits":0}}}
375+
376+ data: [DONE]
377+
378+ headers:
379+ Content-Type:
380+ - text/event-stream
381+ status: 200 OK
382+ code: 200
383+ duration: 1.461643167s
384+- id: 2
385+ request:
386+ proto: HTTP/1.1
387+ proto_major: 1
388+ proto_minor: 1
389+ content_length: 36122
390+ host: ""
391+ body: "{\"messages\":[{\"content\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\n\\n<critical_rules>\\nThese rules override everything else. Follow them strictly:\\n\\n1. **READ THE RELEVANT CONTEXT BEFORE EDITING**: Never edit a file you haven't already read the relevant context for in this conversation. Once read, you don't need to re-read unless it changed. Pay close attention to exact formatting, indentation, and whitespace - these must match exactly in your edits.\\n2. **BE AUTONOMOUS**: Don't ask questions - search, read, think, decide, act. Break complex tasks into steps and complete them all. Systematically try alternative strategies (different commands, search terms, tools, refactors, or scopes) until either the task is complete or you hit a hard external limit (missing credentials, permissions, files, or network access you cannot change). Only stop for actual blocking errors, not perceived difficulty.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification.\\n4. **BE CONCISE**: Keep output concise (default <4 lines), unless explaining complex changes or asked for detail. Conciseness applies to output only, not to thoroughness of work.\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks.\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\". When committing, follow the `<git_commits>` format from the bash tool description exactly, including any configured attribution lines.\\n7. **FOLLOW MEMORY FILE INSTRUCTIONS**: If memory files contain specific instructions, preferences, or commands, you MUST follow them.\\n8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so. Focus on *why* not *what*. NEVER communicate with the user through code comments.\\n9. **SECURITY FIRST**: Only assist with defensive security tasks. Refuse to create, modify, or improve code that may be used maliciously.\\n10. **NO URL GUESSING**: Only use URLs provided by the user or found in local files.\\n11. **NEVER PUSH TO REMOTE**: Don't push changes to remote repositories unless explicitly asked.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **TOOL CONSTRAINTS**: Only use documented tools. Never attempt 'apply_patch' or 'apply_diff' - they don't exist. Use 'edit' or 'multiedit' instead.\\n14. **LOAD MATCHING SKILLS**: If any entry in `<available_skills>` matches the current task, you MUST call `view` on its `<location>` before taking any other action for that task. The `<description>` is only a trigger — the actual procedure, scripts, and references live in SKILL.md. Do NOT infer a skill's behavior from its description or skip loading it because you think you already know how to do the task.\\n15. **LIMIT FILE READS**: Avoid reading entire files, as they can be very large. Read only the sections you need using 'offset' and 'limit' parameters.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- ALWAYS think and respond in the same spoken language the prompt was written in.\\n- Under 4 lines of text (tool use doesn't count)\\n- Conciseness is about **text only**: always fully implement the requested feature, tests, and wiring even if that requires many tool calls.\\n- No preamble (\\\"Here's...\\\", \\\"I'll...\\\")\\n- No postamble (\\\"Let me know...\\\", \\\"Hope this helps...\\\")\\n- One-word answers when possible\\n- No emojis ever\\n- No explanations unless user asks\\n- Never send acknowledgement-only responses; after receiving new context or instructions, immediately continue the task or state the concrete next action you will take.\\n- Use rich Markdown formatting (headings, bullet lists, tables, code fences) for any multi-sentence or explanatory answer; only use plain unformatted text if the user explicitly asks.\\n\\nExamples:\\nuser: what is 2+2?\\nassistant: 4\\n\\nuser: list files in src/\\nassistant: [uses ls tool]\\nfoo.c, bar.c, baz.c\\n\\nuser: which file has the foo implementation?\\nassistant: src/foo.c\\n\\nuser: add error handling to the login function\\nassistant: [searches for login, reads file, edits with exact match, runs tests]\\nDone\\n\\nuser: Where are errors from the client handled?\\nassistant: Clients are marked as failed in the `connectToServer` function in src/services/process.go:712.\\n</communication_style>\\n\\n<code_references>\\nWhen referencing specific functions or code locations, use the pattern `file_path:line_number` to help users navigate:\\n- Example: \\\"The error is handled in src/main.go:45\\\"\\n- Example: \\\"See the implementation in pkg/utils/helper.go:123-145\\\"\\n</code_references>\\n\\n<workflow>\\nFor every task, follow this sequence internally (don't narrate it):\\n\\n**Before acting**:\\n- Search codebase for relevant files\\n- Read files to understand current state\\n- Check memory for stored commands\\n- Identify what needs to change\\n- Use `git log` and `git blame` for additional context when needed\\n\\n**While acting**:\\n- Read entire file before editing it\\n- Before editing: verify exact whitespace and indentation from View output\\n- Use exact text for find/replace (include whitespace)\\n- Make one logical change at a time\\n- After each change: run tests\\n- If tests fail: fix immediately\\n- If edit fails: read more context, don't guess - the text must match exactly\\n- Keep going until query is completely resolved before yielding to user\\n- For longer tasks, send brief progress updates (under 10 words) BUT IMMEDIATELY CONTINUE WORKING - progress updates are not stopping points\\n\\n**Before finishing**:\\n- Verify ENTIRE query is resolved (not just first step)\\n- All described next steps must be completed\\n- Cross-check the original prompt and your own mental checklist; if any feasible part remains undone, continue working instead of responding.\\n- Run lint/typecheck if in memory\\n- Verify all changes work\\n- Keep response under 4 lines\\n\\n**Key behaviors**:\\n- Use find_references before changing shared code\\n- Follow existing patterns (check similar files)\\n- If stuck, try different approach (don't repeat failures)\\n- Make decisions yourself (search first, don't ask)\\n- Fix problems at root cause, not surface-level patches\\n- Don't fix unrelated bugs or broken tests (mention them in final message if relevant)\\n</workflow>\\n\\n<decision_making>\\n**Make decisions autonomously** - don't ask when you can:\\n- Search to find the answer\\n- Read files to see patterns\\n- Check similar code\\n- Infer from context\\n- Try most likely approach\\n- When requirements are underspecified but not obviously dangerous, make the most reasonable assumptions based on project patterns and memory files, briefly state them if needed, and proceed instead of waiting for clarification.\\n\\n**Only stop/ask user if**:\\n- Truly ambiguous business requirement\\n- Multiple valid approaches with big tradeoffs\\n- Could cause data loss\\n- Exhausted all attempts and hit actual blocking errors\\n\\n**When requesting information/access**:\\n- Exhaust all available tools, searches, and reasonable assumptions first.\\n- Never say \\\"Need more info\\\" without detail.\\n- In the same message, list each missing item, why it is required, acceptable substitutes, and what you already attempted.\\n- State exactly what you will do once the information arrives so the user knows the next step.\\n\\nWhen you must stop, first finish all unblocked parts of the request, then clearly report: (a) what you tried, (b) exactly why you are blocked, and (c) the minimal external action required. Don't stop just because one path failed—exhaust multiple plausible approaches first.\\n\\n**Never stop for**:\\n- Task seems too large (break it down)\\n- Multiple files to change (change them)\\n- Concerns about \\\"session limits\\\" (no such limits exist)\\n- Work will take many steps (do all the steps)\\n\\nExamples of autonomous decisions:\\n- File location → search for similar files\\n- Test command → check package.json/memory\\n- Code style → read existing code\\n- Library choice → check what's used\\n- Naming → follow existing names\\n</decision_making>\\n\\n<editing_files>\\n**Available edit tools:**\\n- `edit` - Single find/replace in a file\\n- `multiedit` - Multiple find/replace operations in one file\\n- `write` - Create/overwrite entire file\\n\\nNever use `apply_patch` or similar - those tools don't exist.\\n\\nCritical: ALWAYS read the relevant context of files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the relevant context first - note the EXACT indentation (spaces vs tabs, count)\\n2. Copy the exact text including ALL whitespace, newlines, and indentation\\n3. Include 3-5 lines of context before and after the target\\n4. Verify your old_string would appear exactly once in the file\\n5. If uncertain about whitespace, include more surrounding context\\n6. Verify edit succeeded\\n7. Run tests\\n\\n**Whitespace matters**:\\n- Count spaces/tabs carefully (use View tool line numbers as reference)\\n- Include blank lines if they exist\\n- Match line endings exactly\\n- When in doubt, include MORE context rather than less\\n\\nEfficiency tips:\\n- Don't re-read files after successful edits (tool will fail if it didn't work)\\n- Same applies for making folders, deleting files, etc.\\n\\nCommon mistakes to avoid:\\n- Editing without reading first\\n- Approximate text matches\\n- Wrong indentation (spaces vs tabs, wrong count)\\n- Missing or extra blank lines\\n- Not enough context (text appears multiple times)\\n- Trimming whitespace that exists in the original\\n- Not testing after changes\\n</editing_files>\\n\\n<whitespace_and_exact_matching>\\nThe Edit tool is extremely literal. \\\"Close enough\\\" will fail.\\n\\n**Before every edit**:\\n1. View the file and locate the exact lines to change\\n2. Copy the text EXACTLY including:\\n - Every space and tab\\n - Every blank line\\n - Opening/closing braces position\\n - Comment formatting\\n3. Include enough surrounding lines (3-5) to make it unique\\n4. Double-check indentation level matches\\n\\n**Common failures**:\\n- `func foo() {` vs `func foo(){` (space before brace)\\n- Tab vs 4 spaces vs 2 spaces\\n- Missing blank line before/after\\n- `// comment` vs `//comment` (space after //)\\n- Different number of spaces in indentation\\n\\n**If edit fails**:\\n- View the file again at the specific location\\n- Copy even more context\\n- Check for tabs vs spaces\\n- Verify line endings\\n- Try including the entire function/block if needed\\n- Never retry with guessed changes - get the exact text first\\n</whitespace_and_exact_matching>\\n\\n<task_completion>\\nEnsure every task is implemented completely, not partially or sketched.\\n\\n1. **Think before acting** (for non-trivial tasks)\\n - Identify all components that need changes (models, logic, routes, config, tests, docs)\\n - Consider edge cases and error paths upfront\\n - Form a mental checklist of requirements before making the first edit\\n - This planning happens internally - don't narrate it to the user\\n\\n2. **Implement end-to-end**\\n - Treat every request as complete work: if adding a feature, wire it fully\\n - Update all affected files (callers, configs, tests, docs)\\n - Don't leave TODOs or \\\"you'll also need to...\\\" - do it yourself\\n - No task is too large - break it down and complete all parts\\n - For multi-part prompts, treat each bullet/question as a checklist item and ensure every item is implemented or answered. Partial completion is not an acceptable final state.\\n\\n3. **Verify before finishing**\\n - Re-read the original request and verify each requirement is met\\n - Check for missing error handling, edge cases, or unwired code\\n - Run tests to confirm the implementation works\\n - Only say \\\"Done\\\" when truly done - never stop mid-task\\n</task_completion>\\n\\n<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause (isolate with debug logs or minimal reproduction if needed)\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\n7. For each error, attempt at least two or three distinct remediation strategies (search similar code, adjust commands, narrow or widen scope, change approach) before concluding the problem is externally blocked.\\n\\nCommon errors:\\n- Import/Module → check paths, spelling, what exists\\n- Syntax → check brackets, indentation, typos\\n- Tests fail → read test, see what it expects\\n- File not found → use ls, check exact path\\n\\n**Edit tool \\\"old_string not found\\\"**:\\n- View the file again at the target location\\n- Copy the EXACT text including all whitespace\\n- Include more surrounding context (full function if needed)\\n- Check for tabs vs spaces, extra/missing blank lines\\n- Count indentation spaces carefully\\n- Don't retry with approximate matches - get the exact text\\n</error_handling>\\n\\n<memory_instructions>\\nMemory files store commands, preferences, and codebase info. Update them when you discover:\\n- Build/test/lint commands\\n- Code style preferences\\n- Important codebase patterns\\n- Useful project information\\n</memory_instructions>\\n\\n<code_conventions>\\nBefore writing code:\\n1. Check if library exists (look at imports, package.json)\\n2. Read similar code for patterns\\n3. Match existing style\\n4. Use same libraries/frameworks\\n5. Follow security best practices (never log secrets)\\n6. Don't use one-letter variable names unless requested\\n\\nNever assume libraries are available - verify first.\\n\\n**Ambition vs. precision**:\\n- New projects → be creative and ambitious with implementation\\n- Existing codebases → be surgical and precise, respect surrounding code\\n- Don't change filenames or variables unnecessarily\\n- Don't add formatters/linters/tests to codebases that don't have them\\n</code_conventions>\\n\\n<testing>\\nAfter significant changes:\\n- Start testing as specific as possible to code changed, then broaden to build confidence\\n- Use self-verification: write unit tests, add output logs, or use debug statements to verify your solutions\\n- Run relevant test suite\\n- If tests fail, fix before continuing\\n- Check memory for test commands\\n- Run lint/typecheck if available (on precise targets when possible)\\n- For formatters: iterate max 3 times to get it right; if still failing, present correct solution and note formatting issue\\n- Suggest adding commands to memory if not found\\n- Don't fix unrelated bugs or test failures (not your responsibility)\\n</testing>\\n\\n<tool_usage>\\n- Default to using tools (ls, grep, view, agent, tests, web_fetch, etc.) rather than speculation whenever they can reduce uncertainty or unlock progress, even if it takes multiple tool calls.\\n- Search before assuming\\n- Read files before editing\\n- Always use absolute paths for file operations (editing, reading, writing)\\n- Use Agent tool for complex searches\\n- Run tools in parallel when safe (no dependencies)\\n- When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution\\n- Summarize tool output for user (they don't see it)\\n- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.\\n- Only use the tools you know exist.\\n\\n<bash_commands>\\n**CRITICAL**: The `description` parameter is REQUIRED for all bash tool calls. Always provide it.\\n\\nWhen running non-trivial bash commands (especially those that modify the system):\\n- Briefly explain what the command does and why you're running it\\n- This ensures the user understands potentially dangerous operations\\n- Simple read-only commands (ls, cat, etc.) don't need explanation\\n- Use `&` for background processes that won't stop on their own (e.g., `node server.js &`)\\n- Avoid interactive commands - use non-interactive versions (e.g., `npm init -y` not `npm init`)\\n- Combine related commands to save time (e.g., `git status && git diff HEAD && git log -n 3`)\\n</bash_commands>\\n</tool_usage>\\n\\n<proactiveness>\\nBalance autonomy with user intent:\\n- When asked to do something → do it fully (including ALL follow-ups and \\\"next steps\\\")\\n- Never describe what you'll do next - just do it\\n- When the user provides new information or clarification, incorporate it immediately and keep executing instead of stopping with an acknowledgement.\\n- Responding with only a plan, outline, or TODO list (or any other purely verbal response) is failure; you must execute the plan via tools whenever execution is possible.\\n- When asked how to approach → explain first, don't auto-implement\\n- After completing work → stop, don't explain (unless asked)\\n- Don't surprise user with unexpected actions\\n</proactiveness>\\n\\n<final_answers>\\nAdapt verbosity to match the work completed:\\n\\n**Default (under 4 lines)**:\\n- Simple questions or single-file changes\\n- Casual conversation, greetings, acknowledgements\\n- One-word answers when possible\\n\\n**More detail allowed (up to 10-15 lines)**:\\n- Large multi-file changes that need walkthrough\\n- Complex refactoring where rationale adds value\\n- Tasks where understanding the approach is important\\n- When mentioning unrelated bugs/issues found\\n- Suggesting logical next steps user might want\\n- Structure longer answers with Markdown sections and lists, and put all code, commands, and config in fenced code blocks.\\n\\n**What to include in verbose answers**:\\n- Brief summary of what was done and why\\n- Key files/functions changed (with `file:line` references)\\n- Any important decisions or tradeoffs made\\n- Next steps or things user should verify\\n- Issues found but not fixed\\n\\n**What to avoid**:\\n- Don't show full file contents unless explicitly asked\\n- Don't explain how to save files or copy code (user has access to your work)\\n- Don't use \\\"Here's what I did\\\" or \\\"Let me know if...\\\" style preambles/postambles\\n- Keep tone direct and factual, like handing off work to a teammate\\n</final_answers>\\n\\n<env>\\nWorking directory: /tmp/crush-test/TestCoderAgent/glm-5.1/bash_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n<available_skills>\\n <skill>\\n <name>crush-hooks</name>\\n <description>Use when the user wants to add, write, debug, or configure a Crush hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in crush.json.</description>\\n <location>crush://skills/crush-hooks/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n <skill>\\n <name>jq</name>\\n <description>Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.</description>\\n <location>crush://skills/jq/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n</available_skills>\\n\\n<skills_usage>\\nThe `<description>` of each skill is a TRIGGER — it tells you *when* a skill applies. It is NOT a specification of what the skill does or how to do it. The procedure, scripts, commands, references, and required flags live only in the SKILL.md body. You do not know what a skill actually does until you have read its SKILL.md.\\n\\nMANDATORY activation flow:\\n1. Scan `<available_skills>` against the current user task.\\n2. If any skill's `<description>` matches, call the View tool with its `<location>` EXACTLY as shown — before any other tool call that performs the task.\\n3. Read the entire SKILL.md and follow its instructions.\\n4. Only then execute the task, using the skill's prescribed commands/tools.\\n\\nDo NOT skip step 2 because you think you already know how to do the task. Do NOT infer a skill's behavior from its name or description. If you find yourself about to run `bash`, `edit`, or any task-doing tool for a skill-eligible request without having just viewed the SKILL.md, stop and load the skill first.\\n\\nBuiltin skills (type=builtin) use virtual `crush://skills/...` location identifiers. The \\\"crush://\\\" prefix is NOT a URL, network address, or MCP resource — it is a special internal identifier the View tool understands natively. Pass the `<location>` verbatim to View.\\n\\nDo not use MCP tools (including read_mcp_resource) to load skills.\\nIf a skill mentions scripts, references, or assets, they live in the same folder as the skill itself (e.g., scripts/, references/, assets/ subdirectories within the skill's folder).\\n</skills_usage>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"<system_reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.\\nIf you are working on tasks that would benefit from a todo list please use the \\\"todos\\\" tool to create one.\\nIf not, please feel free to ignore. Again do not mention this message to the user.</system_reminder>\",\"role\":\"user\"},{\"content\":\"use bash to create a file named test.txt with content 'hello bash'. do not print its timestamp\",\"role\":\"user\"},{\"tool_calls\":[{\"id\":\"call_51c682620b31061c\",\"function\":{\"arguments\":\"{\\\"command\\\": \\\"echo 'hello bash' > test.txt\\\", \\\"description\\\": \\\"Create test.txt with content\\\"}\",\"name\":\"bash\"},\"type\":\"function\"}],\"role\":\"assistant\",\"reasoning_content\":\"The user wants me to create a file named test.txt with content 'hello bash' using the bash tool, and not print its timestamp.\"},{\"content\":\"no output\",\"tool_call_id\":\"call_51c682620b31061c\",\"role\":\"tool\"}],\"model\":\"glm-5.1\",\"max_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Execute shell commands; long-running commands automatically move to background and return a shell ID.\\n\\n<cross_platform>\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n</cross_platform>\\n\\n<execution_steps>\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Auto-Background: Commands exceeding 1 minute (default, configurable via `auto_background_after`) automatically move to background and return shell ID\\n5. Output Processing: Truncate if exceeds 30000 characters\\n6. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\n- Command required, working_dir optional (defaults to current directory)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '&&', avoid newlines except in quoted strings\\n- Each command runs in independent shell (no state persistence between calls)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n</usage_notes>\\n\\n<background_execution>\\n- Set run_in_background=true to run commands in a separate background shell\\n- Returns a shell ID for managing the background process\\n- Use job_output tool to view current output from background shell\\n- Use job_kill tool to terminate a background shell\\n- IMPORTANT: NEVER use `&` at the end of commands to run in background - use run_in_background parameter instead\\n- Commands that should run in background:\\n * Long-running servers (e.g., `npm start`, `python -m http.server`, `node server.js`)\\n * Watch/monitoring tasks (e.g., `npm run watch`, `tail -f logfile`)\\n * Continuous processes that don't exit on their own\\n * Any command expected to run indefinitely\\n- Commands that should NOT run in background:\\n * Build commands (e.g., `npm run build`, `go build`)\\n * Test suites (e.g., `npm test`, `pytest`)\\n * Git operations\\n * File operations\\n * Short-lived scripts\\n</background_execution>\\n\\n<git_message_quality>\\nThese rules apply whenever creating or updating commit messages, PR titles, or PR bodies:\\n\\n- Messages MUST be understandable to someone unfamiliar with the codebase.\\n- Before creating or updating a message, verify this litmus test: a new contributor reading only the commit message or PR title/body should understand what problem this solves, why it matters, and the impact without opening files, reading the diff, or knowing internal code names.\\n- Avoid code identifiers, filenames, function names, and implementation details unless they are necessary for understanding the user-facing impact.\\n- Bad: \\\"Add NameFromHex with sync.Once lazy init\\\"\\n- Good: \\\"Improve color name lookup performance while keeping startup fast\\\"\\n</git_message_quality>\\n\\n<commit_messages>\\nCommit messages are for future readers scanning history. Before committing:\\n\\n- Follow <git_message_quality>.\\n- Draft a concise 1-2 sentence message focusing on why the change exists and what outcome it enables, not a list of files or implementation details.\\n- Use clear, accurate verbs (\\\"add\\\"=new capability, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix) and avoid generic messages.\\n- The first line MUST be under 72 characters.\\n- Add a body only when it is needed to explain the reasoning, tradeoffs, or important context; wrap body lines at 72 characters.\\n- If the change is internal-only, still describe the benefit or maintenance outcome rather than naming private code.\\n- Bad: \\\"fix: nil pointer in session.go\\\"\\n- Good: \\\"fix: prevent session loading from crashing on missing metadata\\\"\\n- Bad: \\\"refactor: move PromptBuilder into internal/agent\\\"\\n- Good: \\\"refactor: make prompt assembly easier to maintain\\\"\\n</commit_messages>\\n\\n<git_commits>\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in <commit_analysis> tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond the context of git\\n\\n4. Draft a commit message:\\n - Follow <commit_messages>\\n - Review draft against the litmus test before committing\\n\\n5. Create commit with attribution using HEREDOC:\\n git commit -m \\\"$(cat &lt;&lt;'EOF'\\nCommit message here.\\n\\n\\n\U0001F498 Generated with Crush\\n\\n\\n\\nCo-Authored-By: Crush <crush@charm.land>\\n\\nEOF\\n)\\\"\\n\\n6. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n7. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response, when rebasing always use -m.\\n</git_commits>\\n\\n<pull_requests>\\n\\n\\nWhen user asks you to create or update a PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n\\n3. Commit changes if needed\\n\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in <pr_analysis> tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n\\n6. Draft a PR message:\\n - Follow <git_message_quality>\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Use clear, concise language\\n - Provide an accurate reflection of changes and purpose\\n - Avoid generic summaries; messages should be thoughtful\\n - Review draft against the litmus test before creating or updating the PR\\n\\n7. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat &lt;&lt;'EOF'\\n\\n<summary>\\n\\n\U0001F498 Generated with Crush\\n\\nEOF\\n)\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"properties\":{\"auto_background_after\":{\"description\":\"Seconds to wait before automatically moving the command to a background job (default: 60)\",\"type\":\"integer\"},\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does, try to keep it under 30 characters or so\",\"type\":\"string\"},\"run_in_background\":{\"description\":\"Set to true (boolean) to run this command in the background. Use job_output to read the output later.\",\"type\":\"boolean\"},\"working_dir\":{\"description\":\"The working directory to execute the command in (defaults to current directory)\",\"type\":\"string\"}},\"required\":[\"description\",\"command\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Download a URL directly to a local file (binary-safe, streaming, max 600s timeout); overwrites without warning. For reading content into context use fetch.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"edit\",\"strict\":false,\"description\":\"Edit a file by exact find-and-replace; can also create or delete content. For renames/moves use bash. For large edits use write.\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiedit\",\"strict\":false,\"description\":\"Apply multiple find-and-replace edits to a single file in one operation; edits run sequentially. Prefer over edit for multiple changes to the same file. Same exact-match rules as edit apply.\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"properties\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"required\":[\"old_string\",\"new_string\"],\"type\":\"object\"},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"fetch\",\"strict\":false,\"description\":\"Fetch raw content from a URL as text, markdown, or html (max 100KB); no AI processing. For analysis or extraction use agentic_fetch.\\n\",\"parameters\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"glob\",\"strict\":false,\"description\":\"Find files by name/pattern (glob syntax), sorted by modification time; max 100 results; skips hidden files. Use grep to search file contents.\\n\",\"parameters\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"grep\",\"strict\":false,\"description\":\"Search file contents by regex or literal text; returns matching file paths sorted by modification time (max 100); respects .gitignore. Use glob to filter by filename, not contents.\\n\",\"parameters\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"ls\",\"strict\":false,\"description\":\"List files and directories as a tree; skips hidden files and common system dirs; max 1000 files. Use glob to find files by pattern, grep to search contents.\\n\",\"parameters\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{\"type\":\"string\"},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public GitHub repositories via Sourcegraph; supports regex, language/repo/file filters, and symbol search (max 20 results). Only searches public repos.\\n\",\"parameters\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"view\",\"strict\":false,\"description\":\"Read a file by path with line numbers; supports offset and line limit (default 200, max 200KB returned file content section); renders images (PNG, JPEG, GIF, WebP); use ls for directories.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 200)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"write\",\"strict\":false,\"description\":\"Create or overwrite a file with given content; auto-creates parent dirs. Cannot append. Read the file first to avoid conflicts. For surgical changes use edit or multiedit.\",\"parameters\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}"
392+ headers:
393+ Accept:
394+ - application/json
395+ Content-Type:
396+ - application/json
397+ User-Agent:
398+ - Charm-Crush/devel (https://charm.land/crush)
399+ url: https://hyper.charm.land/v1/chat/completions
400+ method: POST
401+ response:
402+ proto: HTTP/2.0
403+ proto_major: 2
404+ proto_minor: 0
405+ content_length: -1
406+ uncompressed: true
407+ body: |+
408+ data: {"id":"chatcmpl-985f3df336cbf13a5d358129","object":"chat.completion.chunk","created":1782413794,"model":"glm-5.1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
409+
410+ data: {"id":"chatcmpl-985f3df336cbf13a5d358129","object":"chat.completion.chunk","created":1782413794,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"Done"},"finish_reason":null}]}
411+
412+ data: {"id":"chatcmpl-985f3df336cbf13a5d358129","object":"chat.completion.chunk","created":1782413794,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}]}
413+
414+ data: {"id":"chatcmpl-985f3df336cbf13a5d358129","object":"chat.completion.chunk","created":1782413794,"model":"glm-5.1","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
415+
416+ data: {"id":"chatcmpl-985f3df336cbf13a5d358129","object":"chat.completion.chunk","created":1782413794,"model":"glm-5.1","choices":[],"usage":{"prompt_tokens":720,"completion_tokens":4,"total_tokens":8203,"prompt_tokens_details":{"cached_tokens":7479},"cost":{"usd":0.0010255999999999998,"hypercredits":0.020511999999999996},"remaining":{"hypercredits":0}}}
417+
418+ data: [DONE]
419+
420+ headers:
421+ Content-Type:
422+ - text/event-stream
423+ status: 200 OK
424+ code: 200
425+ duration: 1.122182833s
internal/agent/testdata/TestCoderAgent/glm-5.1/download_tool.yamlnew file+483
@@ -0,0 +1,483 @@
1+---
2+version: 2
3+interactions:
4+- id: 0
5+ request:
6+ proto: HTTP/1.1
7+ proto_major: 1
8+ proto_minor: 1
9+ content_length: 35697
10+ host: ""
11+ body: "{\"messages\":[{\"content\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\n\\n<critical_rules>\\nThese rules override everything else. Follow them strictly:\\n\\n1. **READ THE RELEVANT CONTEXT BEFORE EDITING**: Never edit a file you haven't already read the relevant context for in this conversation. Once read, you don't need to re-read unless it changed. Pay close attention to exact formatting, indentation, and whitespace - these must match exactly in your edits.\\n2. **BE AUTONOMOUS**: Don't ask questions - search, read, think, decide, act. Break complex tasks into steps and complete them all. Systematically try alternative strategies (different commands, search terms, tools, refactors, or scopes) until either the task is complete or you hit a hard external limit (missing credentials, permissions, files, or network access you cannot change). Only stop for actual blocking errors, not perceived difficulty.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification.\\n4. **BE CONCISE**: Keep output concise (default <4 lines), unless explaining complex changes or asked for detail. Conciseness applies to output only, not to thoroughness of work.\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks.\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\". When committing, follow the `<git_commits>` format from the bash tool description exactly, including any configured attribution lines.\\n7. **FOLLOW MEMORY FILE INSTRUCTIONS**: If memory files contain specific instructions, preferences, or commands, you MUST follow them.\\n8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so. Focus on *why* not *what*. NEVER communicate with the user through code comments.\\n9. **SECURITY FIRST**: Only assist with defensive security tasks. Refuse to create, modify, or improve code that may be used maliciously.\\n10. **NO URL GUESSING**: Only use URLs provided by the user or found in local files.\\n11. **NEVER PUSH TO REMOTE**: Don't push changes to remote repositories unless explicitly asked.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **TOOL CONSTRAINTS**: Only use documented tools. Never attempt 'apply_patch' or 'apply_diff' - they don't exist. Use 'edit' or 'multiedit' instead.\\n14. **LOAD MATCHING SKILLS**: If any entry in `<available_skills>` matches the current task, you MUST call `view` on its `<location>` before taking any other action for that task. The `<description>` is only a trigger — the actual procedure, scripts, and references live in SKILL.md. Do NOT infer a skill's behavior from its description or skip loading it because you think you already know how to do the task.\\n15. **LIMIT FILE READS**: Avoid reading entire files, as they can be very large. Read only the sections you need using 'offset' and 'limit' parameters.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- ALWAYS think and respond in the same spoken language the prompt was written in.\\n- Under 4 lines of text (tool use doesn't count)\\n- Conciseness is about **text only**: always fully implement the requested feature, tests, and wiring even if that requires many tool calls.\\n- No preamble (\\\"Here's...\\\", \\\"I'll...\\\")\\n- No postamble (\\\"Let me know...\\\", \\\"Hope this helps...\\\")\\n- One-word answers when possible\\n- No emojis ever\\n- No explanations unless user asks\\n- Never send acknowledgement-only responses; after receiving new context or instructions, immediately continue the task or state the concrete next action you will take.\\n- Use rich Markdown formatting (headings, bullet lists, tables, code fences) for any multi-sentence or explanatory answer; only use plain unformatted text if the user explicitly asks.\\n\\nExamples:\\nuser: what is 2+2?\\nassistant: 4\\n\\nuser: list files in src/\\nassistant: [uses ls tool]\\nfoo.c, bar.c, baz.c\\n\\nuser: which file has the foo implementation?\\nassistant: src/foo.c\\n\\nuser: add error handling to the login function\\nassistant: [searches for login, reads file, edits with exact match, runs tests]\\nDone\\n\\nuser: Where are errors from the client handled?\\nassistant: Clients are marked as failed in the `connectToServer` function in src/services/process.go:712.\\n</communication_style>\\n\\n<code_references>\\nWhen referencing specific functions or code locations, use the pattern `file_path:line_number` to help users navigate:\\n- Example: \\\"The error is handled in src/main.go:45\\\"\\n- Example: \\\"See the implementation in pkg/utils/helper.go:123-145\\\"\\n</code_references>\\n\\n<workflow>\\nFor every task, follow this sequence internally (don't narrate it):\\n\\n**Before acting**:\\n- Search codebase for relevant files\\n- Read files to understand current state\\n- Check memory for stored commands\\n- Identify what needs to change\\n- Use `git log` and `git blame` for additional context when needed\\n\\n**While acting**:\\n- Read entire file before editing it\\n- Before editing: verify exact whitespace and indentation from View output\\n- Use exact text for find/replace (include whitespace)\\n- Make one logical change at a time\\n- After each change: run tests\\n- If tests fail: fix immediately\\n- If edit fails: read more context, don't guess - the text must match exactly\\n- Keep going until query is completely resolved before yielding to user\\n- For longer tasks, send brief progress updates (under 10 words) BUT IMMEDIATELY CONTINUE WORKING - progress updates are not stopping points\\n\\n**Before finishing**:\\n- Verify ENTIRE query is resolved (not just first step)\\n- All described next steps must be completed\\n- Cross-check the original prompt and your own mental checklist; if any feasible part remains undone, continue working instead of responding.\\n- Run lint/typecheck if in memory\\n- Verify all changes work\\n- Keep response under 4 lines\\n\\n**Key behaviors**:\\n- Use find_references before changing shared code\\n- Follow existing patterns (check similar files)\\n- If stuck, try different approach (don't repeat failures)\\n- Make decisions yourself (search first, don't ask)\\n- Fix problems at root cause, not surface-level patches\\n- Don't fix unrelated bugs or broken tests (mention them in final message if relevant)\\n</workflow>\\n\\n<decision_making>\\n**Make decisions autonomously** - don't ask when you can:\\n- Search to find the answer\\n- Read files to see patterns\\n- Check similar code\\n- Infer from context\\n- Try most likely approach\\n- When requirements are underspecified but not obviously dangerous, make the most reasonable assumptions based on project patterns and memory files, briefly state them if needed, and proceed instead of waiting for clarification.\\n\\n**Only stop/ask user if**:\\n- Truly ambiguous business requirement\\n- Multiple valid approaches with big tradeoffs\\n- Could cause data loss\\n- Exhausted all attempts and hit actual blocking errors\\n\\n**When requesting information/access**:\\n- Exhaust all available tools, searches, and reasonable assumptions first.\\n- Never say \\\"Need more info\\\" without detail.\\n- In the same message, list each missing item, why it is required, acceptable substitutes, and what you already attempted.\\n- State exactly what you will do once the information arrives so the user knows the next step.\\n\\nWhen you must stop, first finish all unblocked parts of the request, then clearly report: (a) what you tried, (b) exactly why you are blocked, and (c) the minimal external action required. Don't stop just because one path failed—exhaust multiple plausible approaches first.\\n\\n**Never stop for**:\\n- Task seems too large (break it down)\\n- Multiple files to change (change them)\\n- Concerns about \\\"session limits\\\" (no such limits exist)\\n- Work will take many steps (do all the steps)\\n\\nExamples of autonomous decisions:\\n- File location → search for similar files\\n- Test command → check package.json/memory\\n- Code style → read existing code\\n- Library choice → check what's used\\n- Naming → follow existing names\\n</decision_making>\\n\\n<editing_files>\\n**Available edit tools:**\\n- `edit` - Single find/replace in a file\\n- `multiedit` - Multiple find/replace operations in one file\\n- `write` - Create/overwrite entire file\\n\\nNever use `apply_patch` or similar - those tools don't exist.\\n\\nCritical: ALWAYS read the relevant context of files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the relevant context first - note the EXACT indentation (spaces vs tabs, count)\\n2. Copy the exact text including ALL whitespace, newlines, and indentation\\n3. Include 3-5 lines of context before and after the target\\n4. Verify your old_string would appear exactly once in the file\\n5. If uncertain about whitespace, include more surrounding context\\n6. Verify edit succeeded\\n7. Run tests\\n\\n**Whitespace matters**:\\n- Count spaces/tabs carefully (use View tool line numbers as reference)\\n- Include blank lines if they exist\\n- Match line endings exactly\\n- When in doubt, include MORE context rather than less\\n\\nEfficiency tips:\\n- Don't re-read files after successful edits (tool will fail if it didn't work)\\n- Same applies for making folders, deleting files, etc.\\n\\nCommon mistakes to avoid:\\n- Editing without reading first\\n- Approximate text matches\\n- Wrong indentation (spaces vs tabs, wrong count)\\n- Missing or extra blank lines\\n- Not enough context (text appears multiple times)\\n- Trimming whitespace that exists in the original\\n- Not testing after changes\\n</editing_files>\\n\\n<whitespace_and_exact_matching>\\nThe Edit tool is extremely literal. \\\"Close enough\\\" will fail.\\n\\n**Before every edit**:\\n1. View the file and locate the exact lines to change\\n2. Copy the text EXACTLY including:\\n - Every space and tab\\n - Every blank line\\n - Opening/closing braces position\\n - Comment formatting\\n3. Include enough surrounding lines (3-5) to make it unique\\n4. Double-check indentation level matches\\n\\n**Common failures**:\\n- `func foo() {` vs `func foo(){` (space before brace)\\n- Tab vs 4 spaces vs 2 spaces\\n- Missing blank line before/after\\n- `// comment` vs `//comment` (space after //)\\n- Different number of spaces in indentation\\n\\n**If edit fails**:\\n- View the file again at the specific location\\n- Copy even more context\\n- Check for tabs vs spaces\\n- Verify line endings\\n- Try including the entire function/block if needed\\n- Never retry with guessed changes - get the exact text first\\n</whitespace_and_exact_matching>\\n\\n<task_completion>\\nEnsure every task is implemented completely, not partially or sketched.\\n\\n1. **Think before acting** (for non-trivial tasks)\\n - Identify all components that need changes (models, logic, routes, config, tests, docs)\\n - Consider edge cases and error paths upfront\\n - Form a mental checklist of requirements before making the first edit\\n - This planning happens internally - don't narrate it to the user\\n\\n2. **Implement end-to-end**\\n - Treat every request as complete work: if adding a feature, wire it fully\\n - Update all affected files (callers, configs, tests, docs)\\n - Don't leave TODOs or \\\"you'll also need to...\\\" - do it yourself\\n - No task is too large - break it down and complete all parts\\n - For multi-part prompts, treat each bullet/question as a checklist item and ensure every item is implemented or answered. Partial completion is not an acceptable final state.\\n\\n3. **Verify before finishing**\\n - Re-read the original request and verify each requirement is met\\n - Check for missing error handling, edge cases, or unwired code\\n - Run tests to confirm the implementation works\\n - Only say \\\"Done\\\" when truly done - never stop mid-task\\n</task_completion>\\n\\n<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause (isolate with debug logs or minimal reproduction if needed)\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\n7. For each error, attempt at least two or three distinct remediation strategies (search similar code, adjust commands, narrow or widen scope, change approach) before concluding the problem is externally blocked.\\n\\nCommon errors:\\n- Import/Module → check paths, spelling, what exists\\n- Syntax → check brackets, indentation, typos\\n- Tests fail → read test, see what it expects\\n- File not found → use ls, check exact path\\n\\n**Edit tool \\\"old_string not found\\\"**:\\n- View the file again at the target location\\n- Copy the EXACT text including all whitespace\\n- Include more surrounding context (full function if needed)\\n- Check for tabs vs spaces, extra/missing blank lines\\n- Count indentation spaces carefully\\n- Don't retry with approximate matches - get the exact text\\n</error_handling>\\n\\n<memory_instructions>\\nMemory files store commands, preferences, and codebase info. Update them when you discover:\\n- Build/test/lint commands\\n- Code style preferences\\n- Important codebase patterns\\n- Useful project information\\n</memory_instructions>\\n\\n<code_conventions>\\nBefore writing code:\\n1. Check if library exists (look at imports, package.json)\\n2. Read similar code for patterns\\n3. Match existing style\\n4. Use same libraries/frameworks\\n5. Follow security best practices (never log secrets)\\n6. Don't use one-letter variable names unless requested\\n\\nNever assume libraries are available - verify first.\\n\\n**Ambition vs. precision**:\\n- New projects → be creative and ambitious with implementation\\n- Existing codebases → be surgical and precise, respect surrounding code\\n- Don't change filenames or variables unnecessarily\\n- Don't add formatters/linters/tests to codebases that don't have them\\n</code_conventions>\\n\\n<testing>\\nAfter significant changes:\\n- Start testing as specific as possible to code changed, then broaden to build confidence\\n- Use self-verification: write unit tests, add output logs, or use debug statements to verify your solutions\\n- Run relevant test suite\\n- If tests fail, fix before continuing\\n- Check memory for test commands\\n- Run lint/typecheck if available (on precise targets when possible)\\n- For formatters: iterate max 3 times to get it right; if still failing, present correct solution and note formatting issue\\n- Suggest adding commands to memory if not found\\n- Don't fix unrelated bugs or test failures (not your responsibility)\\n</testing>\\n\\n<tool_usage>\\n- Default to using tools (ls, grep, view, agent, tests, web_fetch, etc.) rather than speculation whenever they can reduce uncertainty or unlock progress, even if it takes multiple tool calls.\\n- Search before assuming\\n- Read files before editing\\n- Always use absolute paths for file operations (editing, reading, writing)\\n- Use Agent tool for complex searches\\n- Run tools in parallel when safe (no dependencies)\\n- When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution\\n- Summarize tool output for user (they don't see it)\\n- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.\\n- Only use the tools you know exist.\\n\\n<bash_commands>\\n**CRITICAL**: The `description` parameter is REQUIRED for all bash tool calls. Always provide it.\\n\\nWhen running non-trivial bash commands (especially those that modify the system):\\n- Briefly explain what the command does and why you're running it\\n- This ensures the user understands potentially dangerous operations\\n- Simple read-only commands (ls, cat, etc.) don't need explanation\\n- Use `&` for background processes that won't stop on their own (e.g., `node server.js &`)\\n- Avoid interactive commands - use non-interactive versions (e.g., `npm init -y` not `npm init`)\\n- Combine related commands to save time (e.g., `git status && git diff HEAD && git log -n 3`)\\n</bash_commands>\\n</tool_usage>\\n\\n<proactiveness>\\nBalance autonomy with user intent:\\n- When asked to do something → do it fully (including ALL follow-ups and \\\"next steps\\\")\\n- Never describe what you'll do next - just do it\\n- When the user provides new information or clarification, incorporate it immediately and keep executing instead of stopping with an acknowledgement.\\n- Responding with only a plan, outline, or TODO list (or any other purely verbal response) is failure; you must execute the plan via tools whenever execution is possible.\\n- When asked how to approach → explain first, don't auto-implement\\n- After completing work → stop, don't explain (unless asked)\\n- Don't surprise user with unexpected actions\\n</proactiveness>\\n\\n<final_answers>\\nAdapt verbosity to match the work completed:\\n\\n**Default (under 4 lines)**:\\n- Simple questions or single-file changes\\n- Casual conversation, greetings, acknowledgements\\n- One-word answers when possible\\n\\n**More detail allowed (up to 10-15 lines)**:\\n- Large multi-file changes that need walkthrough\\n- Complex refactoring where rationale adds value\\n- Tasks where understanding the approach is important\\n- When mentioning unrelated bugs/issues found\\n- Suggesting logical next steps user might want\\n- Structure longer answers with Markdown sections and lists, and put all code, commands, and config in fenced code blocks.\\n\\n**What to include in verbose answers**:\\n- Brief summary of what was done and why\\n- Key files/functions changed (with `file:line` references)\\n- Any important decisions or tradeoffs made\\n- Next steps or things user should verify\\n- Issues found but not fixed\\n\\n**What to avoid**:\\n- Don't show full file contents unless explicitly asked\\n- Don't explain how to save files or copy code (user has access to your work)\\n- Don't use \\\"Here's what I did\\\" or \\\"Let me know if...\\\" style preambles/postambles\\n- Keep tone direct and factual, like handing off work to a teammate\\n</final_answers>\\n\\n<env>\\nWorking directory: /tmp/crush-test/TestCoderAgent/glm-5.1/download_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n<available_skills>\\n <skill>\\n <name>crush-hooks</name>\\n <description>Use when the user wants to add, write, debug, or configure a Crush hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in crush.json.</description>\\n <location>crush://skills/crush-hooks/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n <skill>\\n <name>jq</name>\\n <description>Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.</description>\\n <location>crush://skills/jq/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n</available_skills>\\n\\n<skills_usage>\\nThe `<description>` of each skill is a TRIGGER — it tells you *when* a skill applies. It is NOT a specification of what the skill does or how to do it. The procedure, scripts, commands, references, and required flags live only in the SKILL.md body. You do not know what a skill actually does until you have read its SKILL.md.\\n\\nMANDATORY activation flow:\\n1. Scan `<available_skills>` against the current user task.\\n2. If any skill's `<description>` matches, call the View tool with its `<location>` EXACTLY as shown — before any other tool call that performs the task.\\n3. Read the entire SKILL.md and follow its instructions.\\n4. Only then execute the task, using the skill's prescribed commands/tools.\\n\\nDo NOT skip step 2 because you think you already know how to do the task. Do NOT infer a skill's behavior from its name or description. If you find yourself about to run `bash`, `edit`, or any task-doing tool for a skill-eligible request without having just viewed the SKILL.md, stop and load the skill first.\\n\\nBuiltin skills (type=builtin) use virtual `crush://skills/...` location identifiers. The \\\"crush://\\\" prefix is NOT a URL, network address, or MCP resource — it is a special internal identifier the View tool understands natively. Pass the `<location>` verbatim to View.\\n\\nDo not use MCP tools (including read_mcp_resource) to load skills.\\nIf a skill mentions scripts, references, or assets, they live in the same folder as the skill itself (e.g., scripts/, references/, assets/ subdirectories within the skill's folder).\\n</skills_usage>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"<system_reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.\\nIf you are working on tasks that would benefit from a todo list please use the \\\"todos\\\" tool to create one.\\nIf not, please feel free to ignore. Again do not mention this message to the user.</system_reminder>\",\"role\":\"user\"},{\"content\":\"download the file from https://example-files.online-convert.com/document/txt/example.txt and save it as example.txt\",\"role\":\"user\"}],\"model\":\"glm-5.1\",\"max_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Execute shell commands; long-running commands automatically move to background and return a shell ID.\\n\\n<cross_platform>\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n</cross_platform>\\n\\n<execution_steps>\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Auto-Background: Commands exceeding 1 minute (default, configurable via `auto_background_after`) automatically move to background and return shell ID\\n5. Output Processing: Truncate if exceeds 30000 characters\\n6. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\n- Command required, working_dir optional (defaults to current directory)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '&&', avoid newlines except in quoted strings\\n- Each command runs in independent shell (no state persistence between calls)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n</usage_notes>\\n\\n<background_execution>\\n- Set run_in_background=true to run commands in a separate background shell\\n- Returns a shell ID for managing the background process\\n- Use job_output tool to view current output from background shell\\n- Use job_kill tool to terminate a background shell\\n- IMPORTANT: NEVER use `&` at the end of commands to run in background - use run_in_background parameter instead\\n- Commands that should run in background:\\n * Long-running servers (e.g., `npm start`, `python -m http.server`, `node server.js`)\\n * Watch/monitoring tasks (e.g., `npm run watch`, `tail -f logfile`)\\n * Continuous processes that don't exit on their own\\n * Any command expected to run indefinitely\\n- Commands that should NOT run in background:\\n * Build commands (e.g., `npm run build`, `go build`)\\n * Test suites (e.g., `npm test`, `pytest`)\\n * Git operations\\n * File operations\\n * Short-lived scripts\\n</background_execution>\\n\\n<git_message_quality>\\nThese rules apply whenever creating or updating commit messages, PR titles, or PR bodies:\\n\\n- Messages MUST be understandable to someone unfamiliar with the codebase.\\n- Before creating or updating a message, verify this litmus test: a new contributor reading only the commit message or PR title/body should understand what problem this solves, why it matters, and the impact without opening files, reading the diff, or knowing internal code names.\\n- Avoid code identifiers, filenames, function names, and implementation details unless they are necessary for understanding the user-facing impact.\\n- Bad: \\\"Add NameFromHex with sync.Once lazy init\\\"\\n- Good: \\\"Improve color name lookup performance while keeping startup fast\\\"\\n</git_message_quality>\\n\\n<commit_messages>\\nCommit messages are for future readers scanning history. Before committing:\\n\\n- Follow <git_message_quality>.\\n- Draft a concise 1-2 sentence message focusing on why the change exists and what outcome it enables, not a list of files or implementation details.\\n- Use clear, accurate verbs (\\\"add\\\"=new capability, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix) and avoid generic messages.\\n- The first line MUST be under 72 characters.\\n- Add a body only when it is needed to explain the reasoning, tradeoffs, or important context; wrap body lines at 72 characters.\\n- If the change is internal-only, still describe the benefit or maintenance outcome rather than naming private code.\\n- Bad: \\\"fix: nil pointer in session.go\\\"\\n- Good: \\\"fix: prevent session loading from crashing on missing metadata\\\"\\n- Bad: \\\"refactor: move PromptBuilder into internal/agent\\\"\\n- Good: \\\"refactor: make prompt assembly easier to maintain\\\"\\n</commit_messages>\\n\\n<git_commits>\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in <commit_analysis> tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond the context of git\\n\\n4. Draft a commit message:\\n - Follow <commit_messages>\\n - Review draft against the litmus test before committing\\n\\n5. Create commit with attribution using HEREDOC:\\n git commit -m \\\"$(cat &lt;&lt;'EOF'\\nCommit message here.\\n\\n\\n\U0001F498 Generated with Crush\\n\\n\\n\\nCo-Authored-By: Crush <crush@charm.land>\\n\\nEOF\\n)\\\"\\n\\n6. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n7. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response, when rebasing always use -m.\\n</git_commits>\\n\\n<pull_requests>\\n\\n\\nWhen user asks you to create or update a PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n\\n3. Commit changes if needed\\n\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in <pr_analysis> tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n\\n6. Draft a PR message:\\n - Follow <git_message_quality>\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Use clear, concise language\\n - Provide an accurate reflection of changes and purpose\\n - Avoid generic summaries; messages should be thoughtful\\n - Review draft against the litmus test before creating or updating the PR\\n\\n7. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat &lt;&lt;'EOF'\\n\\n<summary>\\n\\n\U0001F498 Generated with Crush\\n\\nEOF\\n)\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"properties\":{\"auto_background_after\":{\"description\":\"Seconds to wait before automatically moving the command to a background job (default: 60)\",\"type\":\"integer\"},\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does, try to keep it under 30 characters or so\",\"type\":\"string\"},\"run_in_background\":{\"description\":\"Set to true (boolean) to run this command in the background. Use job_output to read the output later.\",\"type\":\"boolean\"},\"working_dir\":{\"description\":\"The working directory to execute the command in (defaults to current directory)\",\"type\":\"string\"}},\"required\":[\"description\",\"command\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Download a URL directly to a local file (binary-safe, streaming, max 600s timeout); overwrites without warning. For reading content into context use fetch.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"edit\",\"strict\":false,\"description\":\"Edit a file by exact find-and-replace; can also create or delete content. For renames/moves use bash. For large edits use write.\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiedit\",\"strict\":false,\"description\":\"Apply multiple find-and-replace edits to a single file in one operation; edits run sequentially. Prefer over edit for multiple changes to the same file. Same exact-match rules as edit apply.\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"properties\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"required\":[\"old_string\",\"new_string\"],\"type\":\"object\"},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"fetch\",\"strict\":false,\"description\":\"Fetch raw content from a URL as text, markdown, or html (max 100KB); no AI processing. For analysis or extraction use agentic_fetch.\\n\",\"parameters\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"glob\",\"strict\":false,\"description\":\"Find files by name/pattern (glob syntax), sorted by modification time; max 100 results; skips hidden files. Use grep to search file contents.\\n\",\"parameters\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"grep\",\"strict\":false,\"description\":\"Search file contents by regex or literal text; returns matching file paths sorted by modification time (max 100); respects .gitignore. Use glob to filter by filename, not contents.\\n\",\"parameters\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"ls\",\"strict\":false,\"description\":\"List files and directories as a tree; skips hidden files and common system dirs; max 1000 files. Use glob to find files by pattern, grep to search contents.\\n\",\"parameters\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{\"type\":\"string\"},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public GitHub repositories via Sourcegraph; supports regex, language/repo/file filters, and symbol search (max 20 results). Only searches public repos.\\n\",\"parameters\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"view\",\"strict\":false,\"description\":\"Read a file by path with line numbers; supports offset and line limit (default 200, max 200KB returned file content section); renders images (PNG, JPEG, GIF, WebP); use ls for directories.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 200)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"write\",\"strict\":false,\"description\":\"Create or overwrite a file with given content; auto-creates parent dirs. Cannot append. Read the file first to avoid conflicts. For surgical changes use edit or multiedit.\",\"parameters\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}"
12+ headers:
13+ Accept:
14+ - application/json
15+ Content-Type:
16+ - application/json
17+ User-Agent:
18+ - Charm-Crush/devel (https://charm.land/crush)
19+ url: https://hyper.charm.land/v1/chat/completions
20+ method: POST
21+ response:
22+ proto: HTTP/2.0
23+ proto_major: 2
24+ proto_minor: 0
25+ content_length: -1
26+ uncompressed: true
27+ body: |+
28+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
29+
30+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":"The"},"finish_reason":null}]}
31+
32+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" user"},"finish_reason":null}]}
33+
34+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" wants"},"finish_reason":null}]}
35+
36+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" to"},"finish_reason":null}]}
37+
38+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" download"},"finish_reason":null}]}
39+
40+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" a"},"finish_reason":null}]}
41+
42+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" file"},"finish_reason":null}]}
43+
44+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" from"},"finish_reason":null}]}
45+
46+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" a"},"finish_reason":null}]}
47+
48+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" URL"},"finish_reason":null}]}
49+
50+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" and"},"finish_reason":null}]}
51+
52+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" save"},"finish_reason":null}]}
53+
54+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" it"},"finish_reason":null}]}
55+
56+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" as"},"finish_reason":null}]}
57+
58+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" example"},"finish_reason":null}]}
59+
60+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":".txt"},"finish_reason":null}]}
61+
62+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
63+
64+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"id":"call_4cbf337c01e5b47c","type":"function","index":0,"function":{"name":"download","arguments":""}}]},"finish_reason":null}]}
65+
66+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"file_path\": \""}}]},"finish_reason":null}]}
67+
68+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/tmp"}}]},"finish_reason":null}]}
69+
70+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/c"}}]},"finish_reason":null}]}
71+
72+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"rush"}}]},"finish_reason":null}]}
73+
74+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"-test"}}]},"finish_reason":null}]}
75+
76+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/Test"}}]},"finish_reason":null}]}
77+
78+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Coder"}}]},"finish_reason":null}]}
79+
80+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Agent"}}]},"finish_reason":null}]}
81+
82+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/g"}}]},"finish_reason":null}]}
83+
84+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"lm"}}]},"finish_reason":null}]}
85+
86+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"-"}}]},"finish_reason":null}]}
87+
88+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"5"}}]},"finish_reason":null}]}
89+
90+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"."}}]},"finish_reason":null}]}
91+
92+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"1"}}]},"finish_reason":null}]}
93+
94+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/download"}}]},"finish_reason":null}]}
95+
96+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"_tool"}}]},"finish_reason":null}]}
97+
98+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/example"}}]},"finish_reason":null}]}
99+
100+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".txt"}}]},"finish_reason":null}]}
101+
102+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\""}}]},"finish_reason":null}]}
103+
104+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":", \"url\": \""}}]},"finish_reason":null}]}
105+
106+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"https"}}]},"finish_reason":null}]}
107+
108+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"://"}}]},"finish_reason":null}]}
109+
110+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"example"}}]},"finish_reason":null}]}
111+
112+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"-files"}}]},"finish_reason":null}]}
113+
114+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".online"}}]},"finish_reason":null}]}
115+
116+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"-"}}]},"finish_reason":null}]}
117+
118+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"convert"}}]},"finish_reason":null}]}
119+
120+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".com"}}]},"finish_reason":null}]}
121+
122+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/document"}}]},"finish_reason":null}]}
123+
124+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/t"}}]},"finish_reason":null}]}
125+
126+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"xt"}}]},"finish_reason":null}]}
127+
128+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/example"}}]},"finish_reason":null}]}
129+
130+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".txt"}}]},"finish_reason":null}]}
131+
132+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\""}}]},"finish_reason":null}]}
133+
134+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"finish_reason":null}]}
135+
136+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}]}
137+
138+ data: {"id":"chatcmpl-cc0c9ef25b702fedc808d605","object":"chat.completion.chunk","created":1782413796,"model":"glm-5.1","choices":[],"usage":{"prompt_tokens":689,"completion_tokens":63,"total_tokens":8231,"prompt_tokens_details":{"cached_tokens":7479},"completion_tokens_details":{"reasoning_tokens":18},"cost":{"usd":0.001321,"hypercredits":0.026419999999999996},"remaining":{"hypercredits":0}}}
139+
140+ data: [DONE]
141+
142+ headers:
143+ Content-Type:
144+ - text/event-stream
145+ status: 200 OK
146+ code: 200
147+ duration: 936.027666ms
148+- id: 1
149+ request:
150+ proto: HTTP/1.1
151+ proto_major: 1
152+ proto_minor: 1
153+ content_length: 874
154+ host: ""
155+ body: '{"messages":[{"content":"You will generate a short title based on the first message a user begins a conversation with.\n\n<rules>\n- Keep the title in the same language that the user wrote their message in.\n- Ensure it is not more than 50 characters long.\n- The title should be a summary of the user''s message.\n- It should be one line long.\n- Do not use quotes or colons.\n- The entire text you return will be used as the title.\n- Never return anything that is more than one sentence (one line) long.\n</rules>\n\n /no_think","role":"system"},{"content":"Generate a concise title for the following content:\n\ndownload the file from https://example-files.online-convert.com/document/txt/example.txt and save it as example.txt\n <think>\n\n</think>","role":"user"}],"model":"gpt-oss-120b","max_completion_tokens":40,"stream_options":{"include_usage":true},"stream":true}'
156+ headers:
157+ Accept:
158+ - application/json
159+ Content-Type:
160+ - application/json
161+ User-Agent:
162+ - Charm-Crush/devel (https://charm.land/crush)
163+ url: https://hyper.charm.land/v1/chat/completions
164+ method: POST
165+ response:
166+ proto: HTTP/2.0
167+ proto_major: 2
168+ proto_minor: 0
169+ content_length: -1
170+ uncompressed: true
171+ body: |+
172+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
173+
174+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"The"},"finish_reason":null}]}
175+
176+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" user"},"finish_reason":null}]}
177+
178+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" asks"},"finish_reason":null}]}
179+
180+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
181+
182+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
183+
184+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Generate"},"finish_reason":null}]}
185+
186+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" a"},"finish_reason":null}]}
187+
188+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" concise"},"finish_reason":null}]}
189+
190+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" title"},"finish_reason":null}]}
191+
192+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" for"},"finish_reason":null}]}
193+
194+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" the"},"finish_reason":null}]}
195+
196+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" following"},"finish_reason":null}]}
197+
198+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" content"},"finish_reason":null}]}
199+
200+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
201+
202+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" download"},"finish_reason":null}]}
203+
204+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" the"},"finish_reason":null}]}
205+
206+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" file"},"finish_reason":null}]}
207+
208+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" from"},"finish_reason":null}]}
209+
210+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" https"},"finish_reason":null}]}
211+
212+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"://"},"finish_reason":null}]}
213+
214+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"example"},"finish_reason":null}]}
215+
216+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"-files"},"finish_reason":null}]}
217+
218+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".online"},"finish_reason":null}]}
219+
220+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"-con"},"finish_reason":null}]}
221+
222+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"vert"},"finish_reason":null}]}
223+
224+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".com"},"finish_reason":null}]}
225+
226+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"/document"},"finish_reason":null}]}
227+
228+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"/t"},"finish_reason":null}]}
229+
230+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"xt"},"finish_reason":null}]}
231+
232+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"/example"},"finish_reason":null}]}
233+
234+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".txt"},"finish_reason":null}]}
235+
236+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" and"},"finish_reason":null}]}
237+
238+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" save"},"finish_reason":null}]}
239+
240+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" it"},"finish_reason":null}]}
241+
242+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" as"},"finish_reason":null}]}
243+
244+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" example"},"finish_reason":null}]}
245+
246+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".txt"},"finish_reason":null}]}
247+
248+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\"."},"finish_reason":null}]}
249+
250+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Need"},"finish_reason":null}]}
251+
252+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" a"},"finish_reason":null}]}
253+
254+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" short"},"finish_reason":null}]}
255+
256+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" title"},"finish_reason":null}]}
257+
258+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
259+
260+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" same"},"finish_reason":null}]}
261+
262+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" language"},"finish_reason":null}]}
263+
264+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ("},"finish_reason":null}]}
265+
266+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"English"},"finish_reason":null}]}
267+
268+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"),"},"finish_reason":null}]}
269+
270+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \u003c="},"finish_reason":null}]}
271+
272+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"50"},"finish_reason":null}]}
273+
274+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" chars"},"finish_reason":null}]}
275+
276+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
277+
278+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" one"},"finish_reason":null}]}
279+
280+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" line"},"finish_reason":null}]}
281+
282+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
283+
284+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" no"},"finish_reason":null}]}
285+
286+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" quotes"},"finish_reason":null}]}
287+
288+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
289+
290+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" no"},"finish_reason":null}]}
291+
292+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" colon"},"finish_reason":null}]}
293+
294+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
295+
296+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Something"},"finish_reason":null}]}
297+
298+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" like"},"finish_reason":null}]}
299+
300+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
301+
302+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Download"},"finish_reason":null}]}
303+
304+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" and"},"finish_reason":null}]}
305+
306+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Save"},"finish_reason":null}]}
307+
308+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" example"},"finish_reason":null}]}
309+
310+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".txt"},"finish_reason":null}]}
311+
312+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" from"},"finish_reason":null}]}
313+
314+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" URL"},"finish_reason":null}]}
315+
316+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\"."},"finish_reason":null}]}
317+
318+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Count"},"finish_reason":null}]}
319+
320+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" characters"},"finish_reason":null}]}
321+
322+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
323+
324+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
325+
326+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Download"},"finish_reason":null}]}
327+
328+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" and"},"finish_reason":null}]}
329+
330+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Save"},"finish_reason":null}]}
331+
332+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" example"},"finish_reason":null}]}
333+
334+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".txt"},"finish_reason":null}]}
335+
336+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" from"},"finish_reason":null}]}
337+
338+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" URL"},"finish_reason":null}]}
339+
340+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\""},"finish_reason":null}]}
341+
342+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ="},"finish_reason":null}]}
343+
344+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
345+
346+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"38"},"finish_reason":null}]}
347+
348+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" characters"},"finish_reason":null}]}
349+
350+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
351+
352+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Good"},"finish_reason":null}]}
353+
354+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
355+
356+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":"Download"},"finish_reason":null}]}
357+
358+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" and"},"finish_reason":null}]}
359+
360+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" Save"},"finish_reason":null}]}
361+
362+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" example"},"finish_reason":null}]}
363+
364+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":".txt"},"finish_reason":null}]}
365+
366+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" from"},"finish_reason":null}]}
367+
368+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" URL"},"finish_reason":null}]}
369+
370+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
371+
372+ data: {"id":"chatcmpl-cacd42b690dbfa0c757a15f0","object":"chat.completion.chunk","created":1782413796,"model":"gpt-oss-120b","choices":[],"usage":{"prompt_tokens":160,"completion_tokens":108,"total_tokens":336,"prompt_tokens_details":{"cached_tokens":68},"completion_tokens_details":{"reasoning_tokens":103},"cost":{"usd":0.000145462,"hypercredits":0.00290924},"remaining":{"hypercredits":0}}}
373+
374+ data: [DONE]
375+
376+ headers:
377+ Content-Type:
378+ - text/event-stream
379+ status: 200 OK
380+ code: 200
381+ duration: 1.326897958s
382+- id: 2
383+ request:
384+ proto: HTTP/1.1
385+ proto_major: 1
386+ proto_minor: 1
387+ content_length: 0
388+ host: example-files.online-convert.com
389+ headers:
390+ User-Agent:
391+ - crush/1.0
392+ url: https://example-files.online-convert.com/document/txt/example.txt
393+ method: GET
394+ response:
395+ proto: HTTP/2.0
396+ proto_major: 2
397+ proto_minor: 0
398+ content_length: -1
399+ uncompressed: true
400+ body: |-
401+ TXT test file
402+ Purpose: Provide example of this file type
403+ Document file type: TXT
404+ Version: 1.0
405+ Remark:
406+
407+ Example content:
408+ The names "John Doe" for males, "Jane Doe" or "Jane Roe" for females, or "Jonnie Doe" and "Janie Doe" for children, or just "Doe" non-gender-specifically are used as placeholder names for a party whose true identity is unknown or must be withheld in a legal action, case, or discussion. The names are also used to refer to acorpse or hospital patient whose identity is unknown. This practice is widely used in the United States and Canada, but is rarely used in other English-speaking countries including the United Kingdom itself, from where the use of "John Doe" in a legal context originates. The names Joe Bloggs or John Smith are used in the UK instead, as well as in Australia and New Zealand.
409+
410+ John Doe is sometimes used to refer to a typical male in other contexts as well, in a similar manner to John Q. Public, known in Great Britain as Joe Public, John Smith or Joe Bloggs. For example, the first name listed on a form is often John Doe, along with a fictional address or other fictional information to provide an example of how to fill in the form. The name is also used frequently in popular culture, for example in the Frank Capra film Meet John Doe. John Doe was also the name of a 2002 American television series.
411+
412+ Similarly, a child or baby whose identity is unknown may be referred to as Baby Doe. A notorious murder case in Kansas City, Missouri, referred to the baby victim as Precious Doe. Other unidentified female murder victims are Cali Doe and Princess Doe. Additional persons may be called James Doe, Judy Doe, etc. However, to avoid possible confusion, if two anonymous or unknown parties are cited in a specific case or action, the surnames Doe and Roe may be used simultaneously; for example, "John Doe v. Jane Roe". If several anonymous parties are referenced, they may simply be labelled John Doe #1, John Doe #2, etc. (the U.S. Operation Delego cited 21 (numbered) "John Doe"s) or labelled with other variants of Doe / Roe / Poe / etc. Other early alternatives such as John Stiles and Richard Miles are now rarely used, and Mary Major has been used in some American federal cases.
413+
414+
415+
416+ File created by https://www.online-convert.com
417+ More example files: https://www.online-convert.com/file-type
418+ Text of Example content: Wikipedia (https://en.wikipedia.org/wiki/John_Doe)
419+ License: Attribution-ShareAlike 4.0 (https://creativecommons.org/licenses/by-sa/4.0/)
420+
421+ Feel free to use and share the file according to the license above.
422+ headers:
423+ Content-Type:
424+ - text/plain; charset=UTF-8
425+ status: 200 OK
426+ code: 200
427+ duration: 893.137459ms
428+- id: 3
429+ request:
430+ proto: HTTP/1.1
431+ proto_major: 1
432+ proto_minor: 1
433+ content_length: 36247
434+ host: ""
435+ body: "{\"messages\":[{\"content\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\n\\n<critical_rules>\\nThese rules override everything else. Follow them strictly:\\n\\n1. **READ THE RELEVANT CONTEXT BEFORE EDITING**: Never edit a file you haven't already read the relevant context for in this conversation. Once read, you don't need to re-read unless it changed. Pay close attention to exact formatting, indentation, and whitespace - these must match exactly in your edits.\\n2. **BE AUTONOMOUS**: Don't ask questions - search, read, think, decide, act. Break complex tasks into steps and complete them all. Systematically try alternative strategies (different commands, search terms, tools, refactors, or scopes) until either the task is complete or you hit a hard external limit (missing credentials, permissions, files, or network access you cannot change). Only stop for actual blocking errors, not perceived difficulty.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification.\\n4. **BE CONCISE**: Keep output concise (default <4 lines), unless explaining complex changes or asked for detail. Conciseness applies to output only, not to thoroughness of work.\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks.\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\". When committing, follow the `<git_commits>` format from the bash tool description exactly, including any configured attribution lines.\\n7. **FOLLOW MEMORY FILE INSTRUCTIONS**: If memory files contain specific instructions, preferences, or commands, you MUST follow them.\\n8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so. Focus on *why* not *what*. NEVER communicate with the user through code comments.\\n9. **SECURITY FIRST**: Only assist with defensive security tasks. Refuse to create, modify, or improve code that may be used maliciously.\\n10. **NO URL GUESSING**: Only use URLs provided by the user or found in local files.\\n11. **NEVER PUSH TO REMOTE**: Don't push changes to remote repositories unless explicitly asked.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **TOOL CONSTRAINTS**: Only use documented tools. Never attempt 'apply_patch' or 'apply_diff' - they don't exist. Use 'edit' or 'multiedit' instead.\\n14. **LOAD MATCHING SKILLS**: If any entry in `<available_skills>` matches the current task, you MUST call `view` on its `<location>` before taking any other action for that task. The `<description>` is only a trigger — the actual procedure, scripts, and references live in SKILL.md. Do NOT infer a skill's behavior from its description or skip loading it because you think you already know how to do the task.\\n15. **LIMIT FILE READS**: Avoid reading entire files, as they can be very large. Read only the sections you need using 'offset' and 'limit' parameters.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- ALWAYS think and respond in the same spoken language the prompt was written in.\\n- Under 4 lines of text (tool use doesn't count)\\n- Conciseness is about **text only**: always fully implement the requested feature, tests, and wiring even if that requires many tool calls.\\n- No preamble (\\\"Here's...\\\", \\\"I'll...\\\")\\n- No postamble (\\\"Let me know...\\\", \\\"Hope this helps...\\\")\\n- One-word answers when possible\\n- No emojis ever\\n- No explanations unless user asks\\n- Never send acknowledgement-only responses; after receiving new context or instructions, immediately continue the task or state the concrete next action you will take.\\n- Use rich Markdown formatting (headings, bullet lists, tables, code fences) for any multi-sentence or explanatory answer; only use plain unformatted text if the user explicitly asks.\\n\\nExamples:\\nuser: what is 2+2?\\nassistant: 4\\n\\nuser: list files in src/\\nassistant: [uses ls tool]\\nfoo.c, bar.c, baz.c\\n\\nuser: which file has the foo implementation?\\nassistant: src/foo.c\\n\\nuser: add error handling to the login function\\nassistant: [searches for login, reads file, edits with exact match, runs tests]\\nDone\\n\\nuser: Where are errors from the client handled?\\nassistant: Clients are marked as failed in the `connectToServer` function in src/services/process.go:712.\\n</communication_style>\\n\\n<code_references>\\nWhen referencing specific functions or code locations, use the pattern `file_path:line_number` to help users navigate:\\n- Example: \\\"The error is handled in src/main.go:45\\\"\\n- Example: \\\"See the implementation in pkg/utils/helper.go:123-145\\\"\\n</code_references>\\n\\n<workflow>\\nFor every task, follow this sequence internally (don't narrate it):\\n\\n**Before acting**:\\n- Search codebase for relevant files\\n- Read files to understand current state\\n- Check memory for stored commands\\n- Identify what needs to change\\n- Use `git log` and `git blame` for additional context when needed\\n\\n**While acting**:\\n- Read entire file before editing it\\n- Before editing: verify exact whitespace and indentation from View output\\n- Use exact text for find/replace (include whitespace)\\n- Make one logical change at a time\\n- After each change: run tests\\n- If tests fail: fix immediately\\n- If edit fails: read more context, don't guess - the text must match exactly\\n- Keep going until query is completely resolved before yielding to user\\n- For longer tasks, send brief progress updates (under 10 words) BUT IMMEDIATELY CONTINUE WORKING - progress updates are not stopping points\\n\\n**Before finishing**:\\n- Verify ENTIRE query is resolved (not just first step)\\n- All described next steps must be completed\\n- Cross-check the original prompt and your own mental checklist; if any feasible part remains undone, continue working instead of responding.\\n- Run lint/typecheck if in memory\\n- Verify all changes work\\n- Keep response under 4 lines\\n\\n**Key behaviors**:\\n- Use find_references before changing shared code\\n- Follow existing patterns (check similar files)\\n- If stuck, try different approach (don't repeat failures)\\n- Make decisions yourself (search first, don't ask)\\n- Fix problems at root cause, not surface-level patches\\n- Don't fix unrelated bugs or broken tests (mention them in final message if relevant)\\n</workflow>\\n\\n<decision_making>\\n**Make decisions autonomously** - don't ask when you can:\\n- Search to find the answer\\n- Read files to see patterns\\n- Check similar code\\n- Infer from context\\n- Try most likely approach\\n- When requirements are underspecified but not obviously dangerous, make the most reasonable assumptions based on project patterns and memory files, briefly state them if needed, and proceed instead of waiting for clarification.\\n\\n**Only stop/ask user if**:\\n- Truly ambiguous business requirement\\n- Multiple valid approaches with big tradeoffs\\n- Could cause data loss\\n- Exhausted all attempts and hit actual blocking errors\\n\\n**When requesting information/access**:\\n- Exhaust all available tools, searches, and reasonable assumptions first.\\n- Never say \\\"Need more info\\\" without detail.\\n- In the same message, list each missing item, why it is required, acceptable substitutes, and what you already attempted.\\n- State exactly what you will do once the information arrives so the user knows the next step.\\n\\nWhen you must stop, first finish all unblocked parts of the request, then clearly report: (a) what you tried, (b) exactly why you are blocked, and (c) the minimal external action required. Don't stop just because one path failed—exhaust multiple plausible approaches first.\\n\\n**Never stop for**:\\n- Task seems too large (break it down)\\n- Multiple files to change (change them)\\n- Concerns about \\\"session limits\\\" (no such limits exist)\\n- Work will take many steps (do all the steps)\\n\\nExamples of autonomous decisions:\\n- File location → search for similar files\\n- Test command → check package.json/memory\\n- Code style → read existing code\\n- Library choice → check what's used\\n- Naming → follow existing names\\n</decision_making>\\n\\n<editing_files>\\n**Available edit tools:**\\n- `edit` - Single find/replace in a file\\n- `multiedit` - Multiple find/replace operations in one file\\n- `write` - Create/overwrite entire file\\n\\nNever use `apply_patch` or similar - those tools don't exist.\\n\\nCritical: ALWAYS read the relevant context of files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the relevant context first - note the EXACT indentation (spaces vs tabs, count)\\n2. Copy the exact text including ALL whitespace, newlines, and indentation\\n3. Include 3-5 lines of context before and after the target\\n4. Verify your old_string would appear exactly once in the file\\n5. If uncertain about whitespace, include more surrounding context\\n6. Verify edit succeeded\\n7. Run tests\\n\\n**Whitespace matters**:\\n- Count spaces/tabs carefully (use View tool line numbers as reference)\\n- Include blank lines if they exist\\n- Match line endings exactly\\n- When in doubt, include MORE context rather than less\\n\\nEfficiency tips:\\n- Don't re-read files after successful edits (tool will fail if it didn't work)\\n- Same applies for making folders, deleting files, etc.\\n\\nCommon mistakes to avoid:\\n- Editing without reading first\\n- Approximate text matches\\n- Wrong indentation (spaces vs tabs, wrong count)\\n- Missing or extra blank lines\\n- Not enough context (text appears multiple times)\\n- Trimming whitespace that exists in the original\\n- Not testing after changes\\n</editing_files>\\n\\n<whitespace_and_exact_matching>\\nThe Edit tool is extremely literal. \\\"Close enough\\\" will fail.\\n\\n**Before every edit**:\\n1. View the file and locate the exact lines to change\\n2. Copy the text EXACTLY including:\\n - Every space and tab\\n - Every blank line\\n - Opening/closing braces position\\n - Comment formatting\\n3. Include enough surrounding lines (3-5) to make it unique\\n4. Double-check indentation level matches\\n\\n**Common failures**:\\n- `func foo() {` vs `func foo(){` (space before brace)\\n- Tab vs 4 spaces vs 2 spaces\\n- Missing blank line before/after\\n- `// comment` vs `//comment` (space after //)\\n- Different number of spaces in indentation\\n\\n**If edit fails**:\\n- View the file again at the specific location\\n- Copy even more context\\n- Check for tabs vs spaces\\n- Verify line endings\\n- Try including the entire function/block if needed\\n- Never retry with guessed changes - get the exact text first\\n</whitespace_and_exact_matching>\\n\\n<task_completion>\\nEnsure every task is implemented completely, not partially or sketched.\\n\\n1. **Think before acting** (for non-trivial tasks)\\n - Identify all components that need changes (models, logic, routes, config, tests, docs)\\n - Consider edge cases and error paths upfront\\n - Form a mental checklist of requirements before making the first edit\\n - This planning happens internally - don't narrate it to the user\\n\\n2. **Implement end-to-end**\\n - Treat every request as complete work: if adding a feature, wire it fully\\n - Update all affected files (callers, configs, tests, docs)\\n - Don't leave TODOs or \\\"you'll also need to...\\\" - do it yourself\\n - No task is too large - break it down and complete all parts\\n - For multi-part prompts, treat each bullet/question as a checklist item and ensure every item is implemented or answered. Partial completion is not an acceptable final state.\\n\\n3. **Verify before finishing**\\n - Re-read the original request and verify each requirement is met\\n - Check for missing error handling, edge cases, or unwired code\\n - Run tests to confirm the implementation works\\n - Only say \\\"Done\\\" when truly done - never stop mid-task\\n</task_completion>\\n\\n<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause (isolate with debug logs or minimal reproduction if needed)\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\n7. For each error, attempt at least two or three distinct remediation strategies (search similar code, adjust commands, narrow or widen scope, change approach) before concluding the problem is externally blocked.\\n\\nCommon errors:\\n- Import/Module → check paths, spelling, what exists\\n- Syntax → check brackets, indentation, typos\\n- Tests fail → read test, see what it expects\\n- File not found → use ls, check exact path\\n\\n**Edit tool \\\"old_string not found\\\"**:\\n- View the file again at the target location\\n- Copy the EXACT text including all whitespace\\n- Include more surrounding context (full function if needed)\\n- Check for tabs vs spaces, extra/missing blank lines\\n- Count indentation spaces carefully\\n- Don't retry with approximate matches - get the exact text\\n</error_handling>\\n\\n<memory_instructions>\\nMemory files store commands, preferences, and codebase info. Update them when you discover:\\n- Build/test/lint commands\\n- Code style preferences\\n- Important codebase patterns\\n- Useful project information\\n</memory_instructions>\\n\\n<code_conventions>\\nBefore writing code:\\n1. Check if library exists (look at imports, package.json)\\n2. Read similar code for patterns\\n3. Match existing style\\n4. Use same libraries/frameworks\\n5. Follow security best practices (never log secrets)\\n6. Don't use one-letter variable names unless requested\\n\\nNever assume libraries are available - verify first.\\n\\n**Ambition vs. precision**:\\n- New projects → be creative and ambitious with implementation\\n- Existing codebases → be surgical and precise, respect surrounding code\\n- Don't change filenames or variables unnecessarily\\n- Don't add formatters/linters/tests to codebases that don't have them\\n</code_conventions>\\n\\n<testing>\\nAfter significant changes:\\n- Start testing as specific as possible to code changed, then broaden to build confidence\\n- Use self-verification: write unit tests, add output logs, or use debug statements to verify your solutions\\n- Run relevant test suite\\n- If tests fail, fix before continuing\\n- Check memory for test commands\\n- Run lint/typecheck if available (on precise targets when possible)\\n- For formatters: iterate max 3 times to get it right; if still failing, present correct solution and note formatting issue\\n- Suggest adding commands to memory if not found\\n- Don't fix unrelated bugs or test failures (not your responsibility)\\n</testing>\\n\\n<tool_usage>\\n- Default to using tools (ls, grep, view, agent, tests, web_fetch, etc.) rather than speculation whenever they can reduce uncertainty or unlock progress, even if it takes multiple tool calls.\\n- Search before assuming\\n- Read files before editing\\n- Always use absolute paths for file operations (editing, reading, writing)\\n- Use Agent tool for complex searches\\n- Run tools in parallel when safe (no dependencies)\\n- When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution\\n- Summarize tool output for user (they don't see it)\\n- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.\\n- Only use the tools you know exist.\\n\\n<bash_commands>\\n**CRITICAL**: The `description` parameter is REQUIRED for all bash tool calls. Always provide it.\\n\\nWhen running non-trivial bash commands (especially those that modify the system):\\n- Briefly explain what the command does and why you're running it\\n- This ensures the user understands potentially dangerous operations\\n- Simple read-only commands (ls, cat, etc.) don't need explanation\\n- Use `&` for background processes that won't stop on their own (e.g., `node server.js &`)\\n- Avoid interactive commands - use non-interactive versions (e.g., `npm init -y` not `npm init`)\\n- Combine related commands to save time (e.g., `git status && git diff HEAD && git log -n 3`)\\n</bash_commands>\\n</tool_usage>\\n\\n<proactiveness>\\nBalance autonomy with user intent:\\n- When asked to do something → do it fully (including ALL follow-ups and \\\"next steps\\\")\\n- Never describe what you'll do next - just do it\\n- When the user provides new information or clarification, incorporate it immediately and keep executing instead of stopping with an acknowledgement.\\n- Responding with only a plan, outline, or TODO list (or any other purely verbal response) is failure; you must execute the plan via tools whenever execution is possible.\\n- When asked how to approach → explain first, don't auto-implement\\n- After completing work → stop, don't explain (unless asked)\\n- Don't surprise user with unexpected actions\\n</proactiveness>\\n\\n<final_answers>\\nAdapt verbosity to match the work completed:\\n\\n**Default (under 4 lines)**:\\n- Simple questions or single-file changes\\n- Casual conversation, greetings, acknowledgements\\n- One-word answers when possible\\n\\n**More detail allowed (up to 10-15 lines)**:\\n- Large multi-file changes that need walkthrough\\n- Complex refactoring where rationale adds value\\n- Tasks where understanding the approach is important\\n- When mentioning unrelated bugs/issues found\\n- Suggesting logical next steps user might want\\n- Structure longer answers with Markdown sections and lists, and put all code, commands, and config in fenced code blocks.\\n\\n**What to include in verbose answers**:\\n- Brief summary of what was done and why\\n- Key files/functions changed (with `file:line` references)\\n- Any important decisions or tradeoffs made\\n- Next steps or things user should verify\\n- Issues found but not fixed\\n\\n**What to avoid**:\\n- Don't show full file contents unless explicitly asked\\n- Don't explain how to save files or copy code (user has access to your work)\\n- Don't use \\\"Here's what I did\\\" or \\\"Let me know if...\\\" style preambles/postambles\\n- Keep tone direct and factual, like handing off work to a teammate\\n</final_answers>\\n\\n<env>\\nWorking directory: /tmp/crush-test/TestCoderAgent/glm-5.1/download_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n<available_skills>\\n <skill>\\n <name>crush-hooks</name>\\n <description>Use when the user wants to add, write, debug, or configure a Crush hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in crush.json.</description>\\n <location>crush://skills/crush-hooks/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n <skill>\\n <name>jq</name>\\n <description>Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.</description>\\n <location>crush://skills/jq/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n</available_skills>\\n\\n<skills_usage>\\nThe `<description>` of each skill is a TRIGGER — it tells you *when* a skill applies. It is NOT a specification of what the skill does or how to do it. The procedure, scripts, commands, references, and required flags live only in the SKILL.md body. You do not know what a skill actually does until you have read its SKILL.md.\\n\\nMANDATORY activation flow:\\n1. Scan `<available_skills>` against the current user task.\\n2. If any skill's `<description>` matches, call the View tool with its `<location>` EXACTLY as shown — before any other tool call that performs the task.\\n3. Read the entire SKILL.md and follow its instructions.\\n4. Only then execute the task, using the skill's prescribed commands/tools.\\n\\nDo NOT skip step 2 because you think you already know how to do the task. Do NOT infer a skill's behavior from its name or description. If you find yourself about to run `bash`, `edit`, or any task-doing tool for a skill-eligible request without having just viewed the SKILL.md, stop and load the skill first.\\n\\nBuiltin skills (type=builtin) use virtual `crush://skills/...` location identifiers. The \\\"crush://\\\" prefix is NOT a URL, network address, or MCP resource — it is a special internal identifier the View tool understands natively. Pass the `<location>` verbatim to View.\\n\\nDo not use MCP tools (including read_mcp_resource) to load skills.\\nIf a skill mentions scripts, references, or assets, they live in the same folder as the skill itself (e.g., scripts/, references/, assets/ subdirectories within the skill's folder).\\n</skills_usage>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"<system_reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.\\nIf you are working on tasks that would benefit from a todo list please use the \\\"todos\\\" tool to create one.\\nIf not, please feel free to ignore. Again do not mention this message to the user.</system_reminder>\",\"role\":\"user\"},{\"content\":\"download the file from https://example-files.online-convert.com/document/txt/example.txt and save it as example.txt\",\"role\":\"user\"},{\"tool_calls\":[{\"id\":\"call_4cbf337c01e5b47c\",\"function\":{\"arguments\":\"{\\\"file_path\\\": \\\"/tmp/crush-test/TestCoderAgent/glm-5.1/download_tool/example.txt\\\", \\\"url\\\": \\\"https://example-files.online-convert.com/document/txt/example.txt\\\"}\",\"name\":\"download\"},\"type\":\"function\"}],\"role\":\"assistant\",\"reasoning_content\":\"The user wants to download a file from a URL and save it as example.txt.\"},{\"content\":\"Successfully downloaded 2574 bytes to example.txt (Content-Type: text/plain; charset=UTF-8)\",\"tool_call_id\":\"call_4cbf337c01e5b47c\",\"role\":\"tool\"}],\"model\":\"glm-5.1\",\"max_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Execute shell commands; long-running commands automatically move to background and return a shell ID.\\n\\n<cross_platform>\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n</cross_platform>\\n\\n<execution_steps>\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Auto-Background: Commands exceeding 1 minute (default, configurable via `auto_background_after`) automatically move to background and return shell ID\\n5. Output Processing: Truncate if exceeds 30000 characters\\n6. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\n- Command required, working_dir optional (defaults to current directory)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '&&', avoid newlines except in quoted strings\\n- Each command runs in independent shell (no state persistence between calls)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n</usage_notes>\\n\\n<background_execution>\\n- Set run_in_background=true to run commands in a separate background shell\\n- Returns a shell ID for managing the background process\\n- Use job_output tool to view current output from background shell\\n- Use job_kill tool to terminate a background shell\\n- IMPORTANT: NEVER use `&` at the end of commands to run in background - use run_in_background parameter instead\\n- Commands that should run in background:\\n * Long-running servers (e.g., `npm start`, `python -m http.server`, `node server.js`)\\n * Watch/monitoring tasks (e.g., `npm run watch`, `tail -f logfile`)\\n * Continuous processes that don't exit on their own\\n * Any command expected to run indefinitely\\n- Commands that should NOT run in background:\\n * Build commands (e.g., `npm run build`, `go build`)\\n * Test suites (e.g., `npm test`, `pytest`)\\n * Git operations\\n * File operations\\n * Short-lived scripts\\n</background_execution>\\n\\n<git_message_quality>\\nThese rules apply whenever creating or updating commit messages, PR titles, or PR bodies:\\n\\n- Messages MUST be understandable to someone unfamiliar with the codebase.\\n- Before creating or updating a message, verify this litmus test: a new contributor reading only the commit message or PR title/body should understand what problem this solves, why it matters, and the impact without opening files, reading the diff, or knowing internal code names.\\n- Avoid code identifiers, filenames, function names, and implementation details unless they are necessary for understanding the user-facing impact.\\n- Bad: \\\"Add NameFromHex with sync.Once lazy init\\\"\\n- Good: \\\"Improve color name lookup performance while keeping startup fast\\\"\\n</git_message_quality>\\n\\n<commit_messages>\\nCommit messages are for future readers scanning history. Before committing:\\n\\n- Follow <git_message_quality>.\\n- Draft a concise 1-2 sentence message focusing on why the change exists and what outcome it enables, not a list of files or implementation details.\\n- Use clear, accurate verbs (\\\"add\\\"=new capability, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix) and avoid generic messages.\\n- The first line MUST be under 72 characters.\\n- Add a body only when it is needed to explain the reasoning, tradeoffs, or important context; wrap body lines at 72 characters.\\n- If the change is internal-only, still describe the benefit or maintenance outcome rather than naming private code.\\n- Bad: \\\"fix: nil pointer in session.go\\\"\\n- Good: \\\"fix: prevent session loading from crashing on missing metadata\\\"\\n- Bad: \\\"refactor: move PromptBuilder into internal/agent\\\"\\n- Good: \\\"refactor: make prompt assembly easier to maintain\\\"\\n</commit_messages>\\n\\n<git_commits>\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in <commit_analysis> tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond the context of git\\n\\n4. Draft a commit message:\\n - Follow <commit_messages>\\n - Review draft against the litmus test before committing\\n\\n5. Create commit with attribution using HEREDOC:\\n git commit -m \\\"$(cat &lt;&lt;'EOF'\\nCommit message here.\\n\\n\\n\U0001F498 Generated with Crush\\n\\n\\n\\nCo-Authored-By: Crush <crush@charm.land>\\n\\nEOF\\n)\\\"\\n\\n6. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n7. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response, when rebasing always use -m.\\n</git_commits>\\n\\n<pull_requests>\\n\\n\\nWhen user asks you to create or update a PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n\\n3. Commit changes if needed\\n\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in <pr_analysis> tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n\\n6. Draft a PR message:\\n - Follow <git_message_quality>\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Use clear, concise language\\n - Provide an accurate reflection of changes and purpose\\n - Avoid generic summaries; messages should be thoughtful\\n - Review draft against the litmus test before creating or updating the PR\\n\\n7. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat &lt;&lt;'EOF'\\n\\n<summary>\\n\\n\U0001F498 Generated with Crush\\n\\nEOF\\n)\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"properties\":{\"auto_background_after\":{\"description\":\"Seconds to wait before automatically moving the command to a background job (default: 60)\",\"type\":\"integer\"},\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does, try to keep it under 30 characters or so\",\"type\":\"string\"},\"run_in_background\":{\"description\":\"Set to true (boolean) to run this command in the background. Use job_output to read the output later.\",\"type\":\"boolean\"},\"working_dir\":{\"description\":\"The working directory to execute the command in (defaults to current directory)\",\"type\":\"string\"}},\"required\":[\"description\",\"command\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Download a URL directly to a local file (binary-safe, streaming, max 600s timeout); overwrites without warning. For reading content into context use fetch.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"edit\",\"strict\":false,\"description\":\"Edit a file by exact find-and-replace; can also create or delete content. For renames/moves use bash. For large edits use write.\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiedit\",\"strict\":false,\"description\":\"Apply multiple find-and-replace edits to a single file in one operation; edits run sequentially. Prefer over edit for multiple changes to the same file. Same exact-match rules as edit apply.\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"properties\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"required\":[\"old_string\",\"new_string\"],\"type\":\"object\"},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"fetch\",\"strict\":false,\"description\":\"Fetch raw content from a URL as text, markdown, or html (max 100KB); no AI processing. For analysis or extraction use agentic_fetch.\\n\",\"parameters\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"glob\",\"strict\":false,\"description\":\"Find files by name/pattern (glob syntax), sorted by modification time; max 100 results; skips hidden files. Use grep to search file contents.\\n\",\"parameters\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"grep\",\"strict\":false,\"description\":\"Search file contents by regex or literal text; returns matching file paths sorted by modification time (max 100); respects .gitignore. Use glob to filter by filename, not contents.\\n\",\"parameters\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"ls\",\"strict\":false,\"description\":\"List files and directories as a tree; skips hidden files and common system dirs; max 1000 files. Use glob to find files by pattern, grep to search contents.\\n\",\"parameters\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{\"type\":\"string\"},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public GitHub repositories via Sourcegraph; supports regex, language/repo/file filters, and symbol search (max 20 results). Only searches public repos.\\n\",\"parameters\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"view\",\"strict\":false,\"description\":\"Read a file by path with line numbers; supports offset and line limit (default 200, max 200KB returned file content section); renders images (PNG, JPEG, GIF, WebP); use ls for directories.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 200)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"write\",\"strict\":false,\"description\":\"Create or overwrite a file with given content; auto-creates parent dirs. Cannot append. Read the file first to avoid conflicts. For surgical changes use edit or multiedit.\",\"parameters\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}"
436+ headers:
437+ Accept:
438+ - application/json
439+ Content-Type:
440+ - application/json
441+ User-Agent:
442+ - Charm-Crush/devel (https://charm.land/crush)
443+ url: https://hyper.charm.land/v1/chat/completions
444+ method: POST
445+ response:
446+ proto: HTTP/2.0
447+ proto_major: 2
448+ proto_minor: 0
449+ content_length: -1
450+ uncompressed: true
451+ body: |+
452+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
453+
454+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"Download"},"finish_reason":null}]}
455+
456+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"ed"},"finish_reason":null}]}
457+
458+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" and"},"finish_reason":null}]}
459+
460+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" saved"},"finish_reason":null}]}
461+
462+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" as"},"finish_reason":null}]}
463+
464+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" `"},"finish_reason":null}]}
465+
466+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"example"},"finish_reason":null}]}
467+
468+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":".txt"},"finish_reason":null}]}
469+
470+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"`."},"finish_reason":null}]}
471+
472+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
473+
474+ data: {"id":"chatcmpl-4bda680be45220e2a1b071f0","object":"chat.completion.chunk","created":1782413799,"model":"glm-5.1","choices":[],"usage":{"prompt_tokens":73,"completion_tokens":11,"total_tokens":8251,"prompt_tokens_details":{"cached_tokens":8167},"cost":{"usd":0.0001506,"hypercredits":0.003012},"remaining":{"hypercredits":0}}}
475+
476+ data: [DONE]
477+
478+ headers:
479+ Content-Type:
480+ - text/event-stream
481+ status: 200 OK
482+ code: 200
483+ duration: 1.486211917s
internal/agent/testdata/TestCoderAgent/glm-5.1/fetch_tool.yamlnew file+650
@@ -0,0 +1,650 @@
1+---
2+version: 2
3+interactions:
4+- id: 0
5+ request:
6+ proto: HTTP/1.1
7+ proto_major: 1
8+ proto_minor: 1
9+ content_length: 35715
10+ host: ""
11+ body: "{\"messages\":[{\"content\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\n\\n<critical_rules>\\nThese rules override everything else. Follow them strictly:\\n\\n1. **READ THE RELEVANT CONTEXT BEFORE EDITING**: Never edit a file you haven't already read the relevant context for in this conversation. Once read, you don't need to re-read unless it changed. Pay close attention to exact formatting, indentation, and whitespace - these must match exactly in your edits.\\n2. **BE AUTONOMOUS**: Don't ask questions - search, read, think, decide, act. Break complex tasks into steps and complete them all. Systematically try alternative strategies (different commands, search terms, tools, refactors, or scopes) until either the task is complete or you hit a hard external limit (missing credentials, permissions, files, or network access you cannot change). Only stop for actual blocking errors, not perceived difficulty.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification.\\n4. **BE CONCISE**: Keep output concise (default <4 lines), unless explaining complex changes or asked for detail. Conciseness applies to output only, not to thoroughness of work.\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks.\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\". When committing, follow the `<git_commits>` format from the bash tool description exactly, including any configured attribution lines.\\n7. **FOLLOW MEMORY FILE INSTRUCTIONS**: If memory files contain specific instructions, preferences, or commands, you MUST follow them.\\n8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so. Focus on *why* not *what*. NEVER communicate with the user through code comments.\\n9. **SECURITY FIRST**: Only assist with defensive security tasks. Refuse to create, modify, or improve code that may be used maliciously.\\n10. **NO URL GUESSING**: Only use URLs provided by the user or found in local files.\\n11. **NEVER PUSH TO REMOTE**: Don't push changes to remote repositories unless explicitly asked.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **TOOL CONSTRAINTS**: Only use documented tools. Never attempt 'apply_patch' or 'apply_diff' - they don't exist. Use 'edit' or 'multiedit' instead.\\n14. **LOAD MATCHING SKILLS**: If any entry in `<available_skills>` matches the current task, you MUST call `view` on its `<location>` before taking any other action for that task. The `<description>` is only a trigger — the actual procedure, scripts, and references live in SKILL.md. Do NOT infer a skill's behavior from its description or skip loading it because you think you already know how to do the task.\\n15. **LIMIT FILE READS**: Avoid reading entire files, as they can be very large. Read only the sections you need using 'offset' and 'limit' parameters.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- ALWAYS think and respond in the same spoken language the prompt was written in.\\n- Under 4 lines of text (tool use doesn't count)\\n- Conciseness is about **text only**: always fully implement the requested feature, tests, and wiring even if that requires many tool calls.\\n- No preamble (\\\"Here's...\\\", \\\"I'll...\\\")\\n- No postamble (\\\"Let me know...\\\", \\\"Hope this helps...\\\")\\n- One-word answers when possible\\n- No emojis ever\\n- No explanations unless user asks\\n- Never send acknowledgement-only responses; after receiving new context or instructions, immediately continue the task or state the concrete next action you will take.\\n- Use rich Markdown formatting (headings, bullet lists, tables, code fences) for any multi-sentence or explanatory answer; only use plain unformatted text if the user explicitly asks.\\n\\nExamples:\\nuser: what is 2+2?\\nassistant: 4\\n\\nuser: list files in src/\\nassistant: [uses ls tool]\\nfoo.c, bar.c, baz.c\\n\\nuser: which file has the foo implementation?\\nassistant: src/foo.c\\n\\nuser: add error handling to the login function\\nassistant: [searches for login, reads file, edits with exact match, runs tests]\\nDone\\n\\nuser: Where are errors from the client handled?\\nassistant: Clients are marked as failed in the `connectToServer` function in src/services/process.go:712.\\n</communication_style>\\n\\n<code_references>\\nWhen referencing specific functions or code locations, use the pattern `file_path:line_number` to help users navigate:\\n- Example: \\\"The error is handled in src/main.go:45\\\"\\n- Example: \\\"See the implementation in pkg/utils/helper.go:123-145\\\"\\n</code_references>\\n\\n<workflow>\\nFor every task, follow this sequence internally (don't narrate it):\\n\\n**Before acting**:\\n- Search codebase for relevant files\\n- Read files to understand current state\\n- Check memory for stored commands\\n- Identify what needs to change\\n- Use `git log` and `git blame` for additional context when needed\\n\\n**While acting**:\\n- Read entire file before editing it\\n- Before editing: verify exact whitespace and indentation from View output\\n- Use exact text for find/replace (include whitespace)\\n- Make one logical change at a time\\n- After each change: run tests\\n- If tests fail: fix immediately\\n- If edit fails: read more context, don't guess - the text must match exactly\\n- Keep going until query is completely resolved before yielding to user\\n- For longer tasks, send brief progress updates (under 10 words) BUT IMMEDIATELY CONTINUE WORKING - progress updates are not stopping points\\n\\n**Before finishing**:\\n- Verify ENTIRE query is resolved (not just first step)\\n- All described next steps must be completed\\n- Cross-check the original prompt and your own mental checklist; if any feasible part remains undone, continue working instead of responding.\\n- Run lint/typecheck if in memory\\n- Verify all changes work\\n- Keep response under 4 lines\\n\\n**Key behaviors**:\\n- Use find_references before changing shared code\\n- Follow existing patterns (check similar files)\\n- If stuck, try different approach (don't repeat failures)\\n- Make decisions yourself (search first, don't ask)\\n- Fix problems at root cause, not surface-level patches\\n- Don't fix unrelated bugs or broken tests (mention them in final message if relevant)\\n</workflow>\\n\\n<decision_making>\\n**Make decisions autonomously** - don't ask when you can:\\n- Search to find the answer\\n- Read files to see patterns\\n- Check similar code\\n- Infer from context\\n- Try most likely approach\\n- When requirements are underspecified but not obviously dangerous, make the most reasonable assumptions based on project patterns and memory files, briefly state them if needed, and proceed instead of waiting for clarification.\\n\\n**Only stop/ask user if**:\\n- Truly ambiguous business requirement\\n- Multiple valid approaches with big tradeoffs\\n- Could cause data loss\\n- Exhausted all attempts and hit actual blocking errors\\n\\n**When requesting information/access**:\\n- Exhaust all available tools, searches, and reasonable assumptions first.\\n- Never say \\\"Need more info\\\" without detail.\\n- In the same message, list each missing item, why it is required, acceptable substitutes, and what you already attempted.\\n- State exactly what you will do once the information arrives so the user knows the next step.\\n\\nWhen you must stop, first finish all unblocked parts of the request, then clearly report: (a) what you tried, (b) exactly why you are blocked, and (c) the minimal external action required. Don't stop just because one path failed—exhaust multiple plausible approaches first.\\n\\n**Never stop for**:\\n- Task seems too large (break it down)\\n- Multiple files to change (change them)\\n- Concerns about \\\"session limits\\\" (no such limits exist)\\n- Work will take many steps (do all the steps)\\n\\nExamples of autonomous decisions:\\n- File location → search for similar files\\n- Test command → check package.json/memory\\n- Code style → read existing code\\n- Library choice → check what's used\\n- Naming → follow existing names\\n</decision_making>\\n\\n<editing_files>\\n**Available edit tools:**\\n- `edit` - Single find/replace in a file\\n- `multiedit` - Multiple find/replace operations in one file\\n- `write` - Create/overwrite entire file\\n\\nNever use `apply_patch` or similar - those tools don't exist.\\n\\nCritical: ALWAYS read the relevant context of files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the relevant context first - note the EXACT indentation (spaces vs tabs, count)\\n2. Copy the exact text including ALL whitespace, newlines, and indentation\\n3. Include 3-5 lines of context before and after the target\\n4. Verify your old_string would appear exactly once in the file\\n5. If uncertain about whitespace, include more surrounding context\\n6. Verify edit succeeded\\n7. Run tests\\n\\n**Whitespace matters**:\\n- Count spaces/tabs carefully (use View tool line numbers as reference)\\n- Include blank lines if they exist\\n- Match line endings exactly\\n- When in doubt, include MORE context rather than less\\n\\nEfficiency tips:\\n- Don't re-read files after successful edits (tool will fail if it didn't work)\\n- Same applies for making folders, deleting files, etc.\\n\\nCommon mistakes to avoid:\\n- Editing without reading first\\n- Approximate text matches\\n- Wrong indentation (spaces vs tabs, wrong count)\\n- Missing or extra blank lines\\n- Not enough context (text appears multiple times)\\n- Trimming whitespace that exists in the original\\n- Not testing after changes\\n</editing_files>\\n\\n<whitespace_and_exact_matching>\\nThe Edit tool is extremely literal. \\\"Close enough\\\" will fail.\\n\\n**Before every edit**:\\n1. View the file and locate the exact lines to change\\n2. Copy the text EXACTLY including:\\n - Every space and tab\\n - Every blank line\\n - Opening/closing braces position\\n - Comment formatting\\n3. Include enough surrounding lines (3-5) to make it unique\\n4. Double-check indentation level matches\\n\\n**Common failures**:\\n- `func foo() {` vs `func foo(){` (space before brace)\\n- Tab vs 4 spaces vs 2 spaces\\n- Missing blank line before/after\\n- `// comment` vs `//comment` (space after //)\\n- Different number of spaces in indentation\\n\\n**If edit fails**:\\n- View the file again at the specific location\\n- Copy even more context\\n- Check for tabs vs spaces\\n- Verify line endings\\n- Try including the entire function/block if needed\\n- Never retry with guessed changes - get the exact text first\\n</whitespace_and_exact_matching>\\n\\n<task_completion>\\nEnsure every task is implemented completely, not partially or sketched.\\n\\n1. **Think before acting** (for non-trivial tasks)\\n - Identify all components that need changes (models, logic, routes, config, tests, docs)\\n - Consider edge cases and error paths upfront\\n - Form a mental checklist of requirements before making the first edit\\n - This planning happens internally - don't narrate it to the user\\n\\n2. **Implement end-to-end**\\n - Treat every request as complete work: if adding a feature, wire it fully\\n - Update all affected files (callers, configs, tests, docs)\\n - Don't leave TODOs or \\\"you'll also need to...\\\" - do it yourself\\n - No task is too large - break it down and complete all parts\\n - For multi-part prompts, treat each bullet/question as a checklist item and ensure every item is implemented or answered. Partial completion is not an acceptable final state.\\n\\n3. **Verify before finishing**\\n - Re-read the original request and verify each requirement is met\\n - Check for missing error handling, edge cases, or unwired code\\n - Run tests to confirm the implementation works\\n - Only say \\\"Done\\\" when truly done - never stop mid-task\\n</task_completion>\\n\\n<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause (isolate with debug logs or minimal reproduction if needed)\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\n7. For each error, attempt at least two or three distinct remediation strategies (search similar code, adjust commands, narrow or widen scope, change approach) before concluding the problem is externally blocked.\\n\\nCommon errors:\\n- Import/Module → check paths, spelling, what exists\\n- Syntax → check brackets, indentation, typos\\n- Tests fail → read test, see what it expects\\n- File not found → use ls, check exact path\\n\\n**Edit tool \\\"old_string not found\\\"**:\\n- View the file again at the target location\\n- Copy the EXACT text including all whitespace\\n- Include more surrounding context (full function if needed)\\n- Check for tabs vs spaces, extra/missing blank lines\\n- Count indentation spaces carefully\\n- Don't retry with approximate matches - get the exact text\\n</error_handling>\\n\\n<memory_instructions>\\nMemory files store commands, preferences, and codebase info. Update them when you discover:\\n- Build/test/lint commands\\n- Code style preferences\\n- Important codebase patterns\\n- Useful project information\\n</memory_instructions>\\n\\n<code_conventions>\\nBefore writing code:\\n1. Check if library exists (look at imports, package.json)\\n2. Read similar code for patterns\\n3. Match existing style\\n4. Use same libraries/frameworks\\n5. Follow security best practices (never log secrets)\\n6. Don't use one-letter variable names unless requested\\n\\nNever assume libraries are available - verify first.\\n\\n**Ambition vs. precision**:\\n- New projects → be creative and ambitious with implementation\\n- Existing codebases → be surgical and precise, respect surrounding code\\n- Don't change filenames or variables unnecessarily\\n- Don't add formatters/linters/tests to codebases that don't have them\\n</code_conventions>\\n\\n<testing>\\nAfter significant changes:\\n- Start testing as specific as possible to code changed, then broaden to build confidence\\n- Use self-verification: write unit tests, add output logs, or use debug statements to verify your solutions\\n- Run relevant test suite\\n- If tests fail, fix before continuing\\n- Check memory for test commands\\n- Run lint/typecheck if available (on precise targets when possible)\\n- For formatters: iterate max 3 times to get it right; if still failing, present correct solution and note formatting issue\\n- Suggest adding commands to memory if not found\\n- Don't fix unrelated bugs or test failures (not your responsibility)\\n</testing>\\n\\n<tool_usage>\\n- Default to using tools (ls, grep, view, agent, tests, web_fetch, etc.) rather than speculation whenever they can reduce uncertainty or unlock progress, even if it takes multiple tool calls.\\n- Search before assuming\\n- Read files before editing\\n- Always use absolute paths for file operations (editing, reading, writing)\\n- Use Agent tool for complex searches\\n- Run tools in parallel when safe (no dependencies)\\n- When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution\\n- Summarize tool output for user (they don't see it)\\n- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.\\n- Only use the tools you know exist.\\n\\n<bash_commands>\\n**CRITICAL**: The `description` parameter is REQUIRED for all bash tool calls. Always provide it.\\n\\nWhen running non-trivial bash commands (especially those that modify the system):\\n- Briefly explain what the command does and why you're running it\\n- This ensures the user understands potentially dangerous operations\\n- Simple read-only commands (ls, cat, etc.) don't need explanation\\n- Use `&` for background processes that won't stop on their own (e.g., `node server.js &`)\\n- Avoid interactive commands - use non-interactive versions (e.g., `npm init -y` not `npm init`)\\n- Combine related commands to save time (e.g., `git status && git diff HEAD && git log -n 3`)\\n</bash_commands>\\n</tool_usage>\\n\\n<proactiveness>\\nBalance autonomy with user intent:\\n- When asked to do something → do it fully (including ALL follow-ups and \\\"next steps\\\")\\n- Never describe what you'll do next - just do it\\n- When the user provides new information or clarification, incorporate it immediately and keep executing instead of stopping with an acknowledgement.\\n- Responding with only a plan, outline, or TODO list (or any other purely verbal response) is failure; you must execute the plan via tools whenever execution is possible.\\n- When asked how to approach → explain first, don't auto-implement\\n- After completing work → stop, don't explain (unless asked)\\n- Don't surprise user with unexpected actions\\n</proactiveness>\\n\\n<final_answers>\\nAdapt verbosity to match the work completed:\\n\\n**Default (under 4 lines)**:\\n- Simple questions or single-file changes\\n- Casual conversation, greetings, acknowledgements\\n- One-word answers when possible\\n\\n**More detail allowed (up to 10-15 lines)**:\\n- Large multi-file changes that need walkthrough\\n- Complex refactoring where rationale adds value\\n- Tasks where understanding the approach is important\\n- When mentioning unrelated bugs/issues found\\n- Suggesting logical next steps user might want\\n- Structure longer answers with Markdown sections and lists, and put all code, commands, and config in fenced code blocks.\\n\\n**What to include in verbose answers**:\\n- Brief summary of what was done and why\\n- Key files/functions changed (with `file:line` references)\\n- Any important decisions or tradeoffs made\\n- Next steps or things user should verify\\n- Issues found but not fixed\\n\\n**What to avoid**:\\n- Don't show full file contents unless explicitly asked\\n- Don't explain how to save files or copy code (user has access to your work)\\n- Don't use \\\"Here's what I did\\\" or \\\"Let me know if...\\\" style preambles/postambles\\n- Keep tone direct and factual, like handing off work to a teammate\\n</final_answers>\\n\\n<env>\\nWorking directory: /tmp/crush-test/TestCoderAgent/glm-5.1/fetch_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n<available_skills>\\n <skill>\\n <name>crush-hooks</name>\\n <description>Use when the user wants to add, write, debug, or configure a Crush hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in crush.json.</description>\\n <location>crush://skills/crush-hooks/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n <skill>\\n <name>jq</name>\\n <description>Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.</description>\\n <location>crush://skills/jq/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n</available_skills>\\n\\n<skills_usage>\\nThe `<description>` of each skill is a TRIGGER — it tells you *when* a skill applies. It is NOT a specification of what the skill does or how to do it. The procedure, scripts, commands, references, and required flags live only in the SKILL.md body. You do not know what a skill actually does until you have read its SKILL.md.\\n\\nMANDATORY activation flow:\\n1. Scan `<available_skills>` against the current user task.\\n2. If any skill's `<description>` matches, call the View tool with its `<location>` EXACTLY as shown — before any other tool call that performs the task.\\n3. Read the entire SKILL.md and follow its instructions.\\n4. Only then execute the task, using the skill's prescribed commands/tools.\\n\\nDo NOT skip step 2 because you think you already know how to do the task. Do NOT infer a skill's behavior from its name or description. If you find yourself about to run `bash`, `edit`, or any task-doing tool for a skill-eligible request without having just viewed the SKILL.md, stop and load the skill first.\\n\\nBuiltin skills (type=builtin) use virtual `crush://skills/...` location identifiers. The \\\"crush://\\\" prefix is NOT a URL, network address, or MCP resource — it is a special internal identifier the View tool understands natively. Pass the `<location>` verbatim to View.\\n\\nDo not use MCP tools (including read_mcp_resource) to load skills.\\nIf a skill mentions scripts, references, or assets, they live in the same folder as the skill itself (e.g., scripts/, references/, assets/ subdirectories within the skill's folder).\\n</skills_usage>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"<system_reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.\\nIf you are working on tasks that would benefit from a todo list please use the \\\"todos\\\" tool to create one.\\nIf not, please feel free to ignore. Again do not mention this message to the user.</system_reminder>\",\"role\":\"user\"},{\"content\":\"fetch the content from https://example-files.online-convert.com/website/html/example.html and tell me if it contains the word 'John Doe'\",\"role\":\"user\"}],\"model\":\"glm-5.1\",\"max_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Execute shell commands; long-running commands automatically move to background and return a shell ID.\\n\\n<cross_platform>\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n</cross_platform>\\n\\n<execution_steps>\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Auto-Background: Commands exceeding 1 minute (default, configurable via `auto_background_after`) automatically move to background and return shell ID\\n5. Output Processing: Truncate if exceeds 30000 characters\\n6. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\n- Command required, working_dir optional (defaults to current directory)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '&&', avoid newlines except in quoted strings\\n- Each command runs in independent shell (no state persistence between calls)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n</usage_notes>\\n\\n<background_execution>\\n- Set run_in_background=true to run commands in a separate background shell\\n- Returns a shell ID for managing the background process\\n- Use job_output tool to view current output from background shell\\n- Use job_kill tool to terminate a background shell\\n- IMPORTANT: NEVER use `&` at the end of commands to run in background - use run_in_background parameter instead\\n- Commands that should run in background:\\n * Long-running servers (e.g., `npm start`, `python -m http.server`, `node server.js`)\\n * Watch/monitoring tasks (e.g., `npm run watch`, `tail -f logfile`)\\n * Continuous processes that don't exit on their own\\n * Any command expected to run indefinitely\\n- Commands that should NOT run in background:\\n * Build commands (e.g., `npm run build`, `go build`)\\n * Test suites (e.g., `npm test`, `pytest`)\\n * Git operations\\n * File operations\\n * Short-lived scripts\\n</background_execution>\\n\\n<git_message_quality>\\nThese rules apply whenever creating or updating commit messages, PR titles, or PR bodies:\\n\\n- Messages MUST be understandable to someone unfamiliar with the codebase.\\n- Before creating or updating a message, verify this litmus test: a new contributor reading only the commit message or PR title/body should understand what problem this solves, why it matters, and the impact without opening files, reading the diff, or knowing internal code names.\\n- Avoid code identifiers, filenames, function names, and implementation details unless they are necessary for understanding the user-facing impact.\\n- Bad: \\\"Add NameFromHex with sync.Once lazy init\\\"\\n- Good: \\\"Improve color name lookup performance while keeping startup fast\\\"\\n</git_message_quality>\\n\\n<commit_messages>\\nCommit messages are for future readers scanning history. Before committing:\\n\\n- Follow <git_message_quality>.\\n- Draft a concise 1-2 sentence message focusing on why the change exists and what outcome it enables, not a list of files or implementation details.\\n- Use clear, accurate verbs (\\\"add\\\"=new capability, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix) and avoid generic messages.\\n- The first line MUST be under 72 characters.\\n- Add a body only when it is needed to explain the reasoning, tradeoffs, or important context; wrap body lines at 72 characters.\\n- If the change is internal-only, still describe the benefit or maintenance outcome rather than naming private code.\\n- Bad: \\\"fix: nil pointer in session.go\\\"\\n- Good: \\\"fix: prevent session loading from crashing on missing metadata\\\"\\n- Bad: \\\"refactor: move PromptBuilder into internal/agent\\\"\\n- Good: \\\"refactor: make prompt assembly easier to maintain\\\"\\n</commit_messages>\\n\\n<git_commits>\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in <commit_analysis> tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond the context of git\\n\\n4. Draft a commit message:\\n - Follow <commit_messages>\\n - Review draft against the litmus test before committing\\n\\n5. Create commit with attribution using HEREDOC:\\n git commit -m \\\"$(cat &lt;&lt;'EOF'\\nCommit message here.\\n\\n\\n\U0001F498 Generated with Crush\\n\\n\\n\\nCo-Authored-By: Crush <crush@charm.land>\\n\\nEOF\\n)\\\"\\n\\n6. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n7. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response, when rebasing always use -m.\\n</git_commits>\\n\\n<pull_requests>\\n\\n\\nWhen user asks you to create or update a PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n\\n3. Commit changes if needed\\n\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in <pr_analysis> tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n\\n6. Draft a PR message:\\n - Follow <git_message_quality>\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Use clear, concise language\\n - Provide an accurate reflection of changes and purpose\\n - Avoid generic summaries; messages should be thoughtful\\n - Review draft against the litmus test before creating or updating the PR\\n\\n7. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat &lt;&lt;'EOF'\\n\\n<summary>\\n\\n\U0001F498 Generated with Crush\\n\\nEOF\\n)\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"properties\":{\"auto_background_after\":{\"description\":\"Seconds to wait before automatically moving the command to a background job (default: 60)\",\"type\":\"integer\"},\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does, try to keep it under 30 characters or so\",\"type\":\"string\"},\"run_in_background\":{\"description\":\"Set to true (boolean) to run this command in the background. Use job_output to read the output later.\",\"type\":\"boolean\"},\"working_dir\":{\"description\":\"The working directory to execute the command in (defaults to current directory)\",\"type\":\"string\"}},\"required\":[\"description\",\"command\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Download a URL directly to a local file (binary-safe, streaming, max 600s timeout); overwrites without warning. For reading content into context use fetch.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"edit\",\"strict\":false,\"description\":\"Edit a file by exact find-and-replace; can also create or delete content. For renames/moves use bash. For large edits use write.\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiedit\",\"strict\":false,\"description\":\"Apply multiple find-and-replace edits to a single file in one operation; edits run sequentially. Prefer over edit for multiple changes to the same file. Same exact-match rules as edit apply.\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"properties\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"required\":[\"old_string\",\"new_string\"],\"type\":\"object\"},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"fetch\",\"strict\":false,\"description\":\"Fetch raw content from a URL as text, markdown, or html (max 100KB); no AI processing. For analysis or extraction use agentic_fetch.\\n\",\"parameters\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"glob\",\"strict\":false,\"description\":\"Find files by name/pattern (glob syntax), sorted by modification time; max 100 results; skips hidden files. Use grep to search file contents.\\n\",\"parameters\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"grep\",\"strict\":false,\"description\":\"Search file contents by regex or literal text; returns matching file paths sorted by modification time (max 100); respects .gitignore. Use glob to filter by filename, not contents.\\n\",\"parameters\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"ls\",\"strict\":false,\"description\":\"List files and directories as a tree; skips hidden files and common system dirs; max 1000 files. Use glob to find files by pattern, grep to search contents.\\n\",\"parameters\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{\"type\":\"string\"},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public GitHub repositories via Sourcegraph; supports regex, language/repo/file filters, and symbol search (max 20 results). Only searches public repos.\\n\",\"parameters\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"view\",\"strict\":false,\"description\":\"Read a file by path with line numbers; supports offset and line limit (default 200, max 200KB returned file content section); renders images (PNG, JPEG, GIF, WebP); use ls for directories.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 200)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"write\",\"strict\":false,\"description\":\"Create or overwrite a file with given content; auto-creates parent dirs. Cannot append. Read the file first to avoid conflicts. For surgical changes use edit or multiedit.\",\"parameters\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}"
12+ headers:
13+ Accept:
14+ - application/json
15+ Content-Type:
16+ - application/json
17+ User-Agent:
18+ - Charm-Crush/devel (https://charm.land/crush)
19+ url: https://hyper.charm.land/v1/chat/completions
20+ method: POST
21+ response:
22+ proto: HTTP/2.0
23+ proto_major: 2
24+ proto_minor: 0
25+ content_length: -1
26+ uncompressed: true
27+ body: |+
28+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
29+
30+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":"The"},"finish_reason":null}]}
31+
32+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" user"},"finish_reason":null}]}
33+
34+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" wants"},"finish_reason":null}]}
35+
36+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" me"},"finish_reason":null}]}
37+
38+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" to"},"finish_reason":null}]}
39+
40+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" fetch"},"finish_reason":null}]}
41+
42+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" content"},"finish_reason":null}]}
43+
44+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" from"},"finish_reason":null}]}
45+
46+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" a"},"finish_reason":null}]}
47+
48+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" URL"},"finish_reason":null}]}
49+
50+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" and"},"finish_reason":null}]}
51+
52+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" check"},"finish_reason":null}]}
53+
54+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" if"},"finish_reason":null}]}
55+
56+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" it"},"finish_reason":null}]}
57+
58+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" contains"},"finish_reason":null}]}
59+
60+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" the"},"finish_reason":null}]}
61+
62+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" word"},"finish_reason":null}]}
63+
64+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" '"},"finish_reason":null}]}
65+
66+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":"John"},"finish_reason":null}]}
67+
68+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":" Doe"},"finish_reason":null}]}
69+
70+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"reasoning_content":"'."},"finish_reason":null}]}
71+
72+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"id":"call_60557666b1c79950","type":"function","index":0,"function":{"name":"fetch","arguments":""}}]},"finish_reason":null}]}
73+
74+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"format\": \""}}]},"finish_reason":null}]}
75+
76+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"text"}}]},"finish_reason":null}]}
77+
78+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\""}}]},"finish_reason":null}]}
79+
80+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":", \"url\": \""}}]},"finish_reason":null}]}
81+
82+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"https"}}]},"finish_reason":null}]}
83+
84+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"://"}}]},"finish_reason":null}]}
85+
86+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"example"}}]},"finish_reason":null}]}
87+
88+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"-files"}}]},"finish_reason":null}]}
89+
90+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".online"}}]},"finish_reason":null}]}
91+
92+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"-"}}]},"finish_reason":null}]}
93+
94+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"convert"}}]},"finish_reason":null}]}
95+
96+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".com"}}]},"finish_reason":null}]}
97+
98+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/"}}]},"finish_reason":null}]}
99+
100+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"website"}}]},"finish_reason":null}]}
101+
102+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/html"}}]},"finish_reason":null}]}
103+
104+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/example"}}]},"finish_reason":null}]}
105+
106+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".html"}}]},"finish_reason":null}]}
107+
108+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\""}}]},"finish_reason":null}]}
109+
110+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"finish_reason":null}]}
111+
112+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}]}
113+
114+ data: {"id":"chatcmpl-adf239d098d5e63d542c1773","object":"chat.completion.chunk","created":1782413801,"model":"glm-5.1","choices":[],"usage":{"prompt_tokens":696,"completion_tokens":50,"total_tokens":8225,"prompt_tokens_details":{"cached_tokens":7479},"completion_tokens_details":{"reasoning_tokens":23},"cost":{"usd":0.0012956,"hypercredits":0.025912},"remaining":{"hypercredits":0}}}
115+
116+ data: [DONE]
117+
118+ headers:
119+ Content-Type:
120+ - text/event-stream
121+ status: 200 OK
122+ code: 200
123+ duration: 2.230852292s
124+- id: 1
125+ request:
126+ proto: HTTP/1.1
127+ proto_major: 1
128+ proto_minor: 1
129+ content_length: 895
130+ host: ""
131+ body: '{"messages":[{"content":"You will generate a short title based on the first message a user begins a conversation with.\n\n<rules>\n- Keep the title in the same language that the user wrote their message in.\n- Ensure it is not more than 50 characters long.\n- The title should be a summary of the user''s message.\n- It should be one line long.\n- Do not use quotes or colons.\n- The entire text you return will be used as the title.\n- Never return anything that is more than one sentence (one line) long.\n</rules>\n\n /no_think","role":"system"},{"content":"Generate a concise title for the following content:\n\nfetch the content from https://example-files.online-convert.com/website/html/example.html and tell me if it contains the word ''John Doe''\n <think>\n\n</think>","role":"user"}],"model":"gpt-oss-120b","max_completion_tokens":40,"stream_options":{"include_usage":true},"stream":true}'
132+ headers:
133+ Accept:
134+ - application/json
135+ Content-Type:
136+ - application/json
137+ User-Agent:
138+ - Charm-Crush/devel (https://charm.land/crush)
139+ url: https://hyper.charm.land/v1/chat/completions
140+ method: POST
141+ response:
142+ proto: HTTP/2.0
143+ proto_major: 2
144+ proto_minor: 0
145+ content_length: -1
146+ uncompressed: true
147+ body: |+
148+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
149+
150+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" wants"},"finish_reason":null}]}
151+
152+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" a"},"finish_reason":null}]}
153+
154+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" short"},"finish_reason":null}]}
155+
156+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" title"},"finish_reason":null}]}
157+
158+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" for"},"finish_reason":null}]}
159+
160+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" their"},"finish_reason":null}]}
161+
162+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" request"},"finish_reason":null}]}
163+
164+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" content"},"finish_reason":null}]}
165+
166+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
167+
168+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Title"},"finish_reason":null}]}
169+
170+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" in"},"finish_reason":null}]}
171+
172+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" English"},"finish_reason":null}]}
173+
174+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
175+
176+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Summ"},"finish_reason":null}]}
177+
178+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"ar"},"finish_reason":null}]}
179+
180+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"ize"},"finish_reason":null}]}
181+
182+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
183+
184+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
185+
186+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Check"},"finish_reason":null}]}
187+
188+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" example"},"finish_reason":null}]}
189+
190+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".html"},"finish_reason":null}]}
191+
192+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" for"},"finish_reason":null}]}
193+
194+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" word"},"finish_reason":null}]}
195+
196+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" '"},"finish_reason":null}]}
197+
198+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"John"},"finish_reason":null}]}
199+
200+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Doe"},"finish_reason":null}]}
201+
202+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"'"},"finish_reason":null}]}
203+
204+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\"."},"finish_reason":null}]}
205+
206+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Must"},"finish_reason":null}]}
207+
208+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" be"},"finish_reason":null}]}
209+
210+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \u003c="},"finish_reason":null}]}
211+
212+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"50"},"finish_reason":null}]}
213+
214+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" chars"},"finish_reason":null}]}
215+
216+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
217+
218+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Let's"},"finish_reason":null}]}
219+
220+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" craft"},"finish_reason":null}]}
221+
222+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
223+
224+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
225+
226+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Check"},"finish_reason":null}]}
227+
228+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" if"},"finish_reason":null}]}
229+
230+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" example"},"finish_reason":null}]}
231+
232+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".html"},"finish_reason":null}]}
233+
234+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" contains"},"finish_reason":null}]}
235+
236+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" '"},"finish_reason":null}]}
237+
238+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"John"},"finish_reason":null}]}
239+
240+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Doe"},"finish_reason":null}]}
241+
242+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"'"},"finish_reason":null}]}
243+
244+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\"."},"finish_reason":null}]}
245+
246+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Count"},"finish_reason":null}]}
247+
248+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" characters"},"finish_reason":null}]}
249+
250+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
251+
252+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Count"},"finish_reason":null}]}
253+
254+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
255+
256+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
257+
258+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Check"},"finish_reason":null}]}
259+
260+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" if"},"finish_reason":null}]}
261+
262+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" example"},"finish_reason":null}]}
263+
264+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":".html"},"finish_reason":null}]}
265+
266+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" contains"},"finish_reason":null}]}
267+
268+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" '"},"finish_reason":null}]}
269+
270+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"John"},"finish_reason":null}]}
271+
272+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Doe"},"finish_reason":null}]}
273+
274+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"'\""},"finish_reason":null}]}
275+
276+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" that's"},"finish_reason":null}]}
277+
278+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
279+
280+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"41"},"finish_reason":null}]}
281+
282+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" maybe"},"finish_reason":null}]}
283+
284+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
285+
286+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Let's"},"finish_reason":null}]}
287+
288+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" count"},"finish_reason":null}]}
289+
290+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
291+
292+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" C"},"finish_reason":null}]}
293+
294+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
295+
296+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"1"},"finish_reason":null}]}
297+
298+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")"},"finish_reason":null}]}
299+
300+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"h"},"finish_reason":null}]}
301+
302+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"2"},"finish_reason":null}]}
303+
304+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"e"},"finish_reason":null}]}
305+
306+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"3"},"finish_reason":null}]}
307+
308+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"c"},"finish_reason":null}]}
309+
310+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"4"},"finish_reason":null}]}
311+
312+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"k"},"finish_reason":null}]}
313+
314+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"5"},"finish_reason":null}]}
315+
316+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
317+
318+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"6"},"finish_reason":null}]}
319+
320+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" i"},"finish_reason":null}]}
321+
322+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"7"},"finish_reason":null}]}
323+
324+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"f"},"finish_reason":null}]}
325+
326+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"8"},"finish_reason":null}]}
327+
328+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
329+
330+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"9"},"finish_reason":null}]}
331+
332+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" e"},"finish_reason":null}]}
333+
334+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"10"},"finish_reason":null}]}
335+
336+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"x"},"finish_reason":null}]}
337+
338+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"11"},"finish_reason":null}]}
339+
340+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"a"},"finish_reason":null}]}
341+
342+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"12"},"finish_reason":null}]}
343+
344+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"m"},"finish_reason":null}]}
345+
346+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"13"},"finish_reason":null}]}
347+
348+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"p"},"finish_reason":null}]}
349+
350+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"14"},"finish_reason":null}]}
351+
352+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"l"},"finish_reason":null}]}
353+
354+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"15"},"finish_reason":null}]}
355+
356+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"e"},"finish_reason":null}]}
357+
358+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"16"},"finish_reason":null}]}
359+
360+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
361+
362+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"17"},"finish_reason":null}]}
363+
364+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"h"},"finish_reason":null}]}
365+
366+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"18"},"finish_reason":null}]}
367+
368+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"t"},"finish_reason":null}]}
369+
370+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"19"},"finish_reason":null}]}
371+
372+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"m"},"finish_reason":null}]}
373+
374+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"20"},"finish_reason":null}]}
375+
376+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"l"},"finish_reason":null}]}
377+
378+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"21"},"finish_reason":null}]}
379+
380+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
381+
382+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"22"},"finish_reason":null}]}
383+
384+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" c"},"finish_reason":null}]}
385+
386+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"23"},"finish_reason":null}]}
387+
388+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"o"},"finish_reason":null}]}
389+
390+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"24"},"finish_reason":null}]}
391+
392+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"n"},"finish_reason":null}]}
393+
394+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"25"},"finish_reason":null}]}
395+
396+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"t"},"finish_reason":null}]}
397+
398+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"26"},"finish_reason":null}]}
399+
400+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"a"},"finish_reason":null}]}
401+
402+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"27"},"finish_reason":null}]}
403+
404+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"i"},"finish_reason":null}]}
405+
406+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"28"},"finish_reason":null}]}
407+
408+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"n"},"finish_reason":null}]}
409+
410+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"29"},"finish_reason":null}]}
411+
412+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"s"},"finish_reason":null}]}
413+
414+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"30"},"finish_reason":null}]}
415+
416+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
417+
418+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"31"},"finish_reason":null}]}
419+
420+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" '"},"finish_reason":null}]}
421+
422+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"32"},"finish_reason":null}]}
423+
424+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"J"},"finish_reason":null}]}
425+
426+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"33"},"finish_reason":null}]}
427+
428+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"o"},"finish_reason":null}]}
429+
430+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"34"},"finish_reason":null}]}
431+
432+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"h"},"finish_reason":null}]}
433+
434+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"35"},"finish_reason":null}]}
435+
436+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"n"},"finish_reason":null}]}
437+
438+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"36"},"finish_reason":null}]}
439+
440+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
441+
442+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"37"},"finish_reason":null}]}
443+
444+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"D"},"finish_reason":null}]}
445+
446+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"38"},"finish_reason":null}]}
447+
448+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"o"},"finish_reason":null}]}
449+
450+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"39"},"finish_reason":null}]}
451+
452+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"e"},"finish_reason":null}]}
453+
454+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"40"},"finish_reason":null}]}
455+
456+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"'"},"finish_reason":null}]}
457+
458+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"41"},"finish_reason":null}]}
459+
460+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
461+
462+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" That's"},"finish_reason":null}]}
463+
464+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
465+
466+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"41"},"finish_reason":null}]}
467+
468+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" characters"},"finish_reason":null}]}
469+
470+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
471+
472+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" within"},"finish_reason":null}]}
473+
474+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
475+
476+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"50"},"finish_reason":null}]}
477+
478+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
479+
480+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Good"},"finish_reason":null}]}
481+
482+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
483+
484+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":"Check"},"finish_reason":null}]}
485+
486+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" if"},"finish_reason":null}]}
487+
488+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" example"},"finish_reason":null}]}
489+
490+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":".html"},"finish_reason":null}]}
491+
492+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" contains"},"finish_reason":null}]}
493+
494+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" '"},"finish_reason":null}]}
495+
496+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":"John"},"finish_reason":null}]}
497+
498+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" Doe"},"finish_reason":null}]}
499+
500+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":"'"},"finish_reason":null}]}
501+
502+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
503+
504+ data: {"id":"chatcmpl-2422745116026947d8ea8426","object":"chat.completion.chunk","created":1782413800,"model":"gpt-oss-120b","choices":[],"usage":{"prompt_tokens":173,"completion_tokens":183,"total_tokens":420,"prompt_tokens_details":{"cached_tokens":64},"cost":{"usd":0.00013191,"hypercredits":0.0026382},"remaining":{"hypercredits":0}}}
505+
506+ data: [DONE]
507+
508+ headers:
509+ Content-Type:
510+ - text/event-stream
511+ status: 200 OK
512+ code: 200
513+ duration: 1.005238292s
514+- id: 2
515+ request:
516+ proto: HTTP/1.1
517+ proto_major: 1
518+ proto_minor: 1
519+ content_length: 0
520+ host: example-files.online-convert.com
521+ headers:
522+ User-Agent:
523+ - crush/1.0
524+ url: https://example-files.online-convert.com/website/html/example.html
525+ method: GET
526+ response:
527+ proto: HTTP/2.0
528+ proto_major: 2
529+ proto_minor: 0
530+ content_length: -1
531+ uncompressed: true
532+ body: |-
533+ <!DOCTYPE html>
534+
535+ <html>
536+ <body>
537+
538+ <h1>HTML test file</h1>
539+
540+ <p>Purpose: Provide example of this file type<br>
541+ Document file type: HTML<br>
542+ Version: 1.0<br>
543+ Remark:</p>
544+
545+ <p><img align="right" style="height:5.0551cm;width:7.62cm;" src="data:image/*;base64,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"/>
557+
558+ Example content:<br>
559+ The names "<b>John Doe</b>" for males, "<b>Jane Doe</b>" or "<b>Jane Roe</b>" for females, or "<b>Jonnie Doe</b>" and "<b>Janie Doe</b>" for children, or just "<b>Doe</b>" non-gender-specifically are used as placeholder names for a party whose true identity is unknown or must be withheld in a legal action, case, or discussion. The names are also used to refer to acorpse or hospital patient whose identity is unknown. This practice is widely used in the United States and Canada, but is rarely used in other English-speaking countries including the United Kingdom itself, from where the use of "John Doe" in a legal context originates. The names Joe Bloggs or John Smith are used in the UK instead, as well as in Australia and New Zealand.</p>
560+
561+ <p>John Doe is sometimes used to refer to a typical male in other contexts as well, in a similar manner to John Q. Public, known in Great Britain as Joe Public, John Smith or Joe Bloggs. For example, the first name listed on a form is often John Doe, along with a fictional address or other fictional information to provide an example of how to fill in the form. The name is also used frequently in popular culture, for example in the Frank Capra film <i>Meet John Doe</i>. John Doe was also the name of a 2002 American television series.</p>
562+
563+ <p>Similarly, a child or baby whose identity is unknown may be referred to as <b>Baby Doe</b>. A notorious murder case in Kansas City, Missouri, referred to the baby victim as <b>Precious Doe</b>. Other unidentified female murder victims are Cali Doe and Princess Doe. Additional persons may be called James Doe, Judy Doe, etc. However, to avoid possible confusion, if two anonymous or unknown parties are cited in a specific case or action, the surnames Doe and Roe may be used simultaneously; for example, "John Doe v. Jane Roe". If several anonymous parties are referenced, they may simply be labelled John Doe #1, John Doe #2, etc. (the U.S. Operation Delego cited 21 (numbered) "John Doe"s) or labelled with other variants of Doe / Roe / Poe / etc. Other early alternatives such as <b>John Stiles</b> and <b>Richard Miles</b> are now rarely used, and <b>Mary Major</b> has been used in some American federal cases.</p>
564+
565+ <p><img style="height:1.6881cm;width:1.6881cm;" align="left" src="data:image/*;base64,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"/>
567+
568+ File created by <a href="https://www.online-convert.com" target="_blank">https://www.online-convert.com</a><br>
569+ More example files: <a href="https://www.online-convert.com/file-type" target="_blank">https://www.online-convert.com/file-type</a><br>
570+ Text of "Example content": <a href="https://en.wikipedia.org/wiki/John_Doe" target="_blank">Wikipedia</a><br>
571+ License: <a href="https://creativecommons.org/licenses/by-sa/3.0/" target="_blank">Attribution-ShareAlike 3.0 Unported</a>
572+
573+ <img style="height:0.6949cm;width:1.9741cm;" align="right" src="data:image/*;base64,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"/></p>
574+
575+ <p>Feel free to use and share the file according to license above.</p>
576+
577+ </body>
578+ </html>
579+ headers:
580+ Content-Type:
581+ - text/html; charset=UTF-8
582+ status: 200 OK
583+ code: 200
584+ duration: 147.645375ms
585+- id: 3
586+ request:
587+ proto: HTTP/1.1
588+ proto_major: 1
589+ proto_minor: 1
590+ content_length: 36231
591+ host: ""
592+ body: "{\"messages\":[{\"content\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\n\\n<critical_rules>\\nThese rules override everything else. Follow them strictly:\\n\\n1. **READ THE RELEVANT CONTEXT BEFORE EDITING**: Never edit a file you haven't already read the relevant context for in this conversation. Once read, you don't need to re-read unless it changed. Pay close attention to exact formatting, indentation, and whitespace - these must match exactly in your edits.\\n2. **BE AUTONOMOUS**: Don't ask questions - search, read, think, decide, act. Break complex tasks into steps and complete them all. Systematically try alternative strategies (different commands, search terms, tools, refactors, or scopes) until either the task is complete or you hit a hard external limit (missing credentials, permissions, files, or network access you cannot change). Only stop for actual blocking errors, not perceived difficulty.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification.\\n4. **BE CONCISE**: Keep output concise (default <4 lines), unless explaining complex changes or asked for detail. Conciseness applies to output only, not to thoroughness of work.\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks.\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\". When committing, follow the `<git_commits>` format from the bash tool description exactly, including any configured attribution lines.\\n7. **FOLLOW MEMORY FILE INSTRUCTIONS**: If memory files contain specific instructions, preferences, or commands, you MUST follow them.\\n8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so. Focus on *why* not *what*. NEVER communicate with the user through code comments.\\n9. **SECURITY FIRST**: Only assist with defensive security tasks. Refuse to create, modify, or improve code that may be used maliciously.\\n10. **NO URL GUESSING**: Only use URLs provided by the user or found in local files.\\n11. **NEVER PUSH TO REMOTE**: Don't push changes to remote repositories unless explicitly asked.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **TOOL CONSTRAINTS**: Only use documented tools. Never attempt 'apply_patch' or 'apply_diff' - they don't exist. Use 'edit' or 'multiedit' instead.\\n14. **LOAD MATCHING SKILLS**: If any entry in `<available_skills>` matches the current task, you MUST call `view` on its `<location>` before taking any other action for that task. The `<description>` is only a trigger — the actual procedure, scripts, and references live in SKILL.md. Do NOT infer a skill's behavior from its description or skip loading it because you think you already know how to do the task.\\n15. **LIMIT FILE READS**: Avoid reading entire files, as they can be very large. Read only the sections you need using 'offset' and 'limit' parameters.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- ALWAYS think and respond in the same spoken language the prompt was written in.\\n- Under 4 lines of text (tool use doesn't count)\\n- Conciseness is about **text only**: always fully implement the requested feature, tests, and wiring even if that requires many tool calls.\\n- No preamble (\\\"Here's...\\\", \\\"I'll...\\\")\\n- No postamble (\\\"Let me know...\\\", \\\"Hope this helps...\\\")\\n- One-word answers when possible\\n- No emojis ever\\n- No explanations unless user asks\\n- Never send acknowledgement-only responses; after receiving new context or instructions, immediately continue the task or state the concrete next action you will take.\\n- Use rich Markdown formatting (headings, bullet lists, tables, code fences) for any multi-sentence or explanatory answer; only use plain unformatted text if the user explicitly asks.\\n\\nExamples:\\nuser: what is 2+2?\\nassistant: 4\\n\\nuser: list files in src/\\nassistant: [uses ls tool]\\nfoo.c, bar.c, baz.c\\n\\nuser: which file has the foo implementation?\\nassistant: src/foo.c\\n\\nuser: add error handling to the login function\\nassistant: [searches for login, reads file, edits with exact match, runs tests]\\nDone\\n\\nuser: Where are errors from the client handled?\\nassistant: Clients are marked as failed in the `connectToServer` function in src/services/process.go:712.\\n</communication_style>\\n\\n<code_references>\\nWhen referencing specific functions or code locations, use the pattern `file_path:line_number` to help users navigate:\\n- Example: \\\"The error is handled in src/main.go:45\\\"\\n- Example: \\\"See the implementation in pkg/utils/helper.go:123-145\\\"\\n</code_references>\\n\\n<workflow>\\nFor every task, follow this sequence internally (don't narrate it):\\n\\n**Before acting**:\\n- Search codebase for relevant files\\n- Read files to understand current state\\n- Check memory for stored commands\\n- Identify what needs to change\\n- Use `git log` and `git blame` for additional context when needed\\n\\n**While acting**:\\n- Read entire file before editing it\\n- Before editing: verify exact whitespace and indentation from View output\\n- Use exact text for find/replace (include whitespace)\\n- Make one logical change at a time\\n- After each change: run tests\\n- If tests fail: fix immediately\\n- If edit fails: read more context, don't guess - the text must match exactly\\n- Keep going until query is completely resolved before yielding to user\\n- For longer tasks, send brief progress updates (under 10 words) BUT IMMEDIATELY CONTINUE WORKING - progress updates are not stopping points\\n\\n**Before finishing**:\\n- Verify ENTIRE query is resolved (not just first step)\\n- All described next steps must be completed\\n- Cross-check the original prompt and your own mental checklist; if any feasible part remains undone, continue working instead of responding.\\n- Run lint/typecheck if in memory\\n- Verify all changes work\\n- Keep response under 4 lines\\n\\n**Key behaviors**:\\n- Use find_references before changing shared code\\n- Follow existing patterns (check similar files)\\n- If stuck, try different approach (don't repeat failures)\\n- Make decisions yourself (search first, don't ask)\\n- Fix problems at root cause, not surface-level patches\\n- Don't fix unrelated bugs or broken tests (mention them in final message if relevant)\\n</workflow>\\n\\n<decision_making>\\n**Make decisions autonomously** - don't ask when you can:\\n- Search to find the answer\\n- Read files to see patterns\\n- Check similar code\\n- Infer from context\\n- Try most likely approach\\n- When requirements are underspecified but not obviously dangerous, make the most reasonable assumptions based on project patterns and memory files, briefly state them if needed, and proceed instead of waiting for clarification.\\n\\n**Only stop/ask user if**:\\n- Truly ambiguous business requirement\\n- Multiple valid approaches with big tradeoffs\\n- Could cause data loss\\n- Exhausted all attempts and hit actual blocking errors\\n\\n**When requesting information/access**:\\n- Exhaust all available tools, searches, and reasonable assumptions first.\\n- Never say \\\"Need more info\\\" without detail.\\n- In the same message, list each missing item, why it is required, acceptable substitutes, and what you already attempted.\\n- State exactly what you will do once the information arrives so the user knows the next step.\\n\\nWhen you must stop, first finish all unblocked parts of the request, then clearly report: (a) what you tried, (b) exactly why you are blocked, and (c) the minimal external action required. Don't stop just because one path failed—exhaust multiple plausible approaches first.\\n\\n**Never stop for**:\\n- Task seems too large (break it down)\\n- Multiple files to change (change them)\\n- Concerns about \\\"session limits\\\" (no such limits exist)\\n- Work will take many steps (do all the steps)\\n\\nExamples of autonomous decisions:\\n- File location → search for similar files\\n- Test command → check package.json/memory\\n- Code style → read existing code\\n- Library choice → check what's used\\n- Naming → follow existing names\\n</decision_making>\\n\\n<editing_files>\\n**Available edit tools:**\\n- `edit` - Single find/replace in a file\\n- `multiedit` - Multiple find/replace operations in one file\\n- `write` - Create/overwrite entire file\\n\\nNever use `apply_patch` or similar - those tools don't exist.\\n\\nCritical: ALWAYS read the relevant context of files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the relevant context first - note the EXACT indentation (spaces vs tabs, count)\\n2. Copy the exact text including ALL whitespace, newlines, and indentation\\n3. Include 3-5 lines of context before and after the target\\n4. Verify your old_string would appear exactly once in the file\\n5. If uncertain about whitespace, include more surrounding context\\n6. Verify edit succeeded\\n7. Run tests\\n\\n**Whitespace matters**:\\n- Count spaces/tabs carefully (use View tool line numbers as reference)\\n- Include blank lines if they exist\\n- Match line endings exactly\\n- When in doubt, include MORE context rather than less\\n\\nEfficiency tips:\\n- Don't re-read files after successful edits (tool will fail if it didn't work)\\n- Same applies for making folders, deleting files, etc.\\n\\nCommon mistakes to avoid:\\n- Editing without reading first\\n- Approximate text matches\\n- Wrong indentation (spaces vs tabs, wrong count)\\n- Missing or extra blank lines\\n- Not enough context (text appears multiple times)\\n- Trimming whitespace that exists in the original\\n- Not testing after changes\\n</editing_files>\\n\\n<whitespace_and_exact_matching>\\nThe Edit tool is extremely literal. \\\"Close enough\\\" will fail.\\n\\n**Before every edit**:\\n1. View the file and locate the exact lines to change\\n2. Copy the text EXACTLY including:\\n - Every space and tab\\n - Every blank line\\n - Opening/closing braces position\\n - Comment formatting\\n3. Include enough surrounding lines (3-5) to make it unique\\n4. Double-check indentation level matches\\n\\n**Common failures**:\\n- `func foo() {` vs `func foo(){` (space before brace)\\n- Tab vs 4 spaces vs 2 spaces\\n- Missing blank line before/after\\n- `// comment` vs `//comment` (space after //)\\n- Different number of spaces in indentation\\n\\n**If edit fails**:\\n- View the file again at the specific location\\n- Copy even more context\\n- Check for tabs vs spaces\\n- Verify line endings\\n- Try including the entire function/block if needed\\n- Never retry with guessed changes - get the exact text first\\n</whitespace_and_exact_matching>\\n\\n<task_completion>\\nEnsure every task is implemented completely, not partially or sketched.\\n\\n1. **Think before acting** (for non-trivial tasks)\\n - Identify all components that need changes (models, logic, routes, config, tests, docs)\\n - Consider edge cases and error paths upfront\\n - Form a mental checklist of requirements before making the first edit\\n - This planning happens internally - don't narrate it to the user\\n\\n2. **Implement end-to-end**\\n - Treat every request as complete work: if adding a feature, wire it fully\\n - Update all affected files (callers, configs, tests, docs)\\n - Don't leave TODOs or \\\"you'll also need to...\\\" - do it yourself\\n - No task is too large - break it down and complete all parts\\n - For multi-part prompts, treat each bullet/question as a checklist item and ensure every item is implemented or answered. Partial completion is not an acceptable final state.\\n\\n3. **Verify before finishing**\\n - Re-read the original request and verify each requirement is met\\n - Check for missing error handling, edge cases, or unwired code\\n - Run tests to confirm the implementation works\\n - Only say \\\"Done\\\" when truly done - never stop mid-task\\n</task_completion>\\n\\n<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause (isolate with debug logs or minimal reproduction if needed)\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\n7. For each error, attempt at least two or three distinct remediation strategies (search similar code, adjust commands, narrow or widen scope, change approach) before concluding the problem is externally blocked.\\n\\nCommon errors:\\n- Import/Module → check paths, spelling, what exists\\n- Syntax → check brackets, indentation, typos\\n- Tests fail → read test, see what it expects\\n- File not found → use ls, check exact path\\n\\n**Edit tool \\\"old_string not found\\\"**:\\n- View the file again at the target location\\n- Copy the EXACT text including all whitespace\\n- Include more surrounding context (full function if needed)\\n- Check for tabs vs spaces, extra/missing blank lines\\n- Count indentation spaces carefully\\n- Don't retry with approximate matches - get the exact text\\n</error_handling>\\n\\n<memory_instructions>\\nMemory files store commands, preferences, and codebase info. Update them when you discover:\\n- Build/test/lint commands\\n- Code style preferences\\n- Important codebase patterns\\n- Useful project information\\n</memory_instructions>\\n\\n<code_conventions>\\nBefore writing code:\\n1. Check if library exists (look at imports, package.json)\\n2. Read similar code for patterns\\n3. Match existing style\\n4. Use same libraries/frameworks\\n5. Follow security best practices (never log secrets)\\n6. Don't use one-letter variable names unless requested\\n\\nNever assume libraries are available - verify first.\\n\\n**Ambition vs. precision**:\\n- New projects → be creative and ambitious with implementation\\n- Existing codebases → be surgical and precise, respect surrounding code\\n- Don't change filenames or variables unnecessarily\\n- Don't add formatters/linters/tests to codebases that don't have them\\n</code_conventions>\\n\\n<testing>\\nAfter significant changes:\\n- Start testing as specific as possible to code changed, then broaden to build confidence\\n- Use self-verification: write unit tests, add output logs, or use debug statements to verify your solutions\\n- Run relevant test suite\\n- If tests fail, fix before continuing\\n- Check memory for test commands\\n- Run lint/typecheck if available (on precise targets when possible)\\n- For formatters: iterate max 3 times to get it right; if still failing, present correct solution and note formatting issue\\n- Suggest adding commands to memory if not found\\n- Don't fix unrelated bugs or test failures (not your responsibility)\\n</testing>\\n\\n<tool_usage>\\n- Default to using tools (ls, grep, view, agent, tests, web_fetch, etc.) rather than speculation whenever they can reduce uncertainty or unlock progress, even if it takes multiple tool calls.\\n- Search before assuming\\n- Read files before editing\\n- Always use absolute paths for file operations (editing, reading, writing)\\n- Use Agent tool for complex searches\\n- Run tools in parallel when safe (no dependencies)\\n- When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution\\n- Summarize tool output for user (they don't see it)\\n- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.\\n- Only use the tools you know exist.\\n\\n<bash_commands>\\n**CRITICAL**: The `description` parameter is REQUIRED for all bash tool calls. Always provide it.\\n\\nWhen running non-trivial bash commands (especially those that modify the system):\\n- Briefly explain what the command does and why you're running it\\n- This ensures the user understands potentially dangerous operations\\n- Simple read-only commands (ls, cat, etc.) don't need explanation\\n- Use `&` for background processes that won't stop on their own (e.g., `node server.js &`)\\n- Avoid interactive commands - use non-interactive versions (e.g., `npm init -y` not `npm init`)\\n- Combine related commands to save time (e.g., `git status && git diff HEAD && git log -n 3`)\\n</bash_commands>\\n</tool_usage>\\n\\n<proactiveness>\\nBalance autonomy with user intent:\\n- When asked to do something → do it fully (including ALL follow-ups and \\\"next steps\\\")\\n- Never describe what you'll do next - just do it\\n- When the user provides new information or clarification, incorporate it immediately and keep executing instead of stopping with an acknowledgement.\\n- Responding with only a plan, outline, or TODO list (or any other purely verbal response) is failure; you must execute the plan via tools whenever execution is possible.\\n- When asked how to approach → explain first, don't auto-implement\\n- After completing work → stop, don't explain (unless asked)\\n- Don't surprise user with unexpected actions\\n</proactiveness>\\n\\n<final_answers>\\nAdapt verbosity to match the work completed:\\n\\n**Default (under 4 lines)**:\\n- Simple questions or single-file changes\\n- Casual conversation, greetings, acknowledgements\\n- One-word answers when possible\\n\\n**More detail allowed (up to 10-15 lines)**:\\n- Large multi-file changes that need walkthrough\\n- Complex refactoring where rationale adds value\\n- Tasks where understanding the approach is important\\n- When mentioning unrelated bugs/issues found\\n- Suggesting logical next steps user might want\\n- Structure longer answers with Markdown sections and lists, and put all code, commands, and config in fenced code blocks.\\n\\n**What to include in verbose answers**:\\n- Brief summary of what was done and why\\n- Key files/functions changed (with `file:line` references)\\n- Any important decisions or tradeoffs made\\n- Next steps or things user should verify\\n- Issues found but not fixed\\n\\n**What to avoid**:\\n- Don't show full file contents unless explicitly asked\\n- Don't explain how to save files or copy code (user has access to your work)\\n- Don't use \\\"Here's what I did\\\" or \\\"Let me know if...\\\" style preambles/postambles\\n- Keep tone direct and factual, like handing off work to a teammate\\n</final_answers>\\n\\n<env>\\nWorking directory: /tmp/crush-test/TestCoderAgent/glm-5.1/fetch_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n<available_skills>\\n <skill>\\n <name>crush-hooks</name>\\n <description>Use when the user wants to add, write, debug, or configure a Crush hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in crush.json.</description>\\n <location>crush://skills/crush-hooks/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n <skill>\\n <name>jq</name>\\n <description>Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.</description>\\n <location>crush://skills/jq/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n</available_skills>\\n\\n<skills_usage>\\nThe `<description>` of each skill is a TRIGGER — it tells you *when* a skill applies. It is NOT a specification of what the skill does or how to do it. The procedure, scripts, commands, references, and required flags live only in the SKILL.md body. You do not know what a skill actually does until you have read its SKILL.md.\\n\\nMANDATORY activation flow:\\n1. Scan `<available_skills>` against the current user task.\\n2. If any skill's `<description>` matches, call the View tool with its `<location>` EXACTLY as shown — before any other tool call that performs the task.\\n3. Read the entire SKILL.md and follow its instructions.\\n4. Only then execute the task, using the skill's prescribed commands/tools.\\n\\nDo NOT skip step 2 because you think you already know how to do the task. Do NOT infer a skill's behavior from its name or description. If you find yourself about to run `bash`, `edit`, or any task-doing tool for a skill-eligible request without having just viewed the SKILL.md, stop and load the skill first.\\n\\nBuiltin skills (type=builtin) use virtual `crush://skills/...` location identifiers. The \\\"crush://\\\" prefix is NOT a URL, network address, or MCP resource — it is a special internal identifier the View tool understands natively. Pass the `<location>` verbatim to View.\\n\\nDo not use MCP tools (including read_mcp_resource) to load skills.\\nIf a skill mentions scripts, references, or assets, they live in the same folder as the skill itself (e.g., scripts/, references/, assets/ subdirectories within the skill's folder).\\n</skills_usage>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"<system_reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.\\nIf you are working on tasks that would benefit from a todo list please use the \\\"todos\\\" tool to create one.\\nIf not, please feel free to ignore. Again do not mention this message to the user.</system_reminder>\",\"role\":\"user\"},{\"content\":\"fetch the content from https://example-files.online-convert.com/website/html/example.html and tell me if it contains the word 'John Doe'\",\"role\":\"user\"},{\"tool_calls\":[{\"id\":\"call_60557666b1c79950\",\"function\":{\"arguments\":\"{\\\"format\\\": \\\"text\\\", \\\"url\\\": \\\"https://example-files.online-convert.com/website/html/example.html\\\"}\",\"name\":\"fetch\"},\"type\":\"function\"}],\"role\":\"assistant\",\"reasoning_content\":\"The user wants me to fetch content from a URL and check if it contains the word 'John Doe'.\"},{\"content\":\"HTML test file Purpose: Provide example of this file type Document file type: HTML Version: 1.0 Remark:\",\"tool_call_id\":\"call_60557666b1c79950\",\"role\":\"tool\"}],\"model\":\"glm-5.1\",\"max_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Execute shell commands; long-running commands automatically move to background and return a shell ID.\\n\\n<cross_platform>\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n</cross_platform>\\n\\n<execution_steps>\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Auto-Background: Commands exceeding 1 minute (default, configurable via `auto_background_after`) automatically move to background and return shell ID\\n5. Output Processing: Truncate if exceeds 30000 characters\\n6. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\n- Command required, working_dir optional (defaults to current directory)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '&&', avoid newlines except in quoted strings\\n- Each command runs in independent shell (no state persistence between calls)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n</usage_notes>\\n\\n<background_execution>\\n- Set run_in_background=true to run commands in a separate background shell\\n- Returns a shell ID for managing the background process\\n- Use job_output tool to view current output from background shell\\n- Use job_kill tool to terminate a background shell\\n- IMPORTANT: NEVER use `&` at the end of commands to run in background - use run_in_background parameter instead\\n- Commands that should run in background:\\n * Long-running servers (e.g., `npm start`, `python -m http.server`, `node server.js`)\\n * Watch/monitoring tasks (e.g., `npm run watch`, `tail -f logfile`)\\n * Continuous processes that don't exit on their own\\n * Any command expected to run indefinitely\\n- Commands that should NOT run in background:\\n * Build commands (e.g., `npm run build`, `go build`)\\n * Test suites (e.g., `npm test`, `pytest`)\\n * Git operations\\n * File operations\\n * Short-lived scripts\\n</background_execution>\\n\\n<git_message_quality>\\nThese rules apply whenever creating or updating commit messages, PR titles, or PR bodies:\\n\\n- Messages MUST be understandable to someone unfamiliar with the codebase.\\n- Before creating or updating a message, verify this litmus test: a new contributor reading only the commit message or PR title/body should understand what problem this solves, why it matters, and the impact without opening files, reading the diff, or knowing internal code names.\\n- Avoid code identifiers, filenames, function names, and implementation details unless they are necessary for understanding the user-facing impact.\\n- Bad: \\\"Add NameFromHex with sync.Once lazy init\\\"\\n- Good: \\\"Improve color name lookup performance while keeping startup fast\\\"\\n</git_message_quality>\\n\\n<commit_messages>\\nCommit messages are for future readers scanning history. Before committing:\\n\\n- Follow <git_message_quality>.\\n- Draft a concise 1-2 sentence message focusing on why the change exists and what outcome it enables, not a list of files or implementation details.\\n- Use clear, accurate verbs (\\\"add\\\"=new capability, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix) and avoid generic messages.\\n- The first line MUST be under 72 characters.\\n- Add a body only when it is needed to explain the reasoning, tradeoffs, or important context; wrap body lines at 72 characters.\\n- If the change is internal-only, still describe the benefit or maintenance outcome rather than naming private code.\\n- Bad: \\\"fix: nil pointer in session.go\\\"\\n- Good: \\\"fix: prevent session loading from crashing on missing metadata\\\"\\n- Bad: \\\"refactor: move PromptBuilder into internal/agent\\\"\\n- Good: \\\"refactor: make prompt assembly easier to maintain\\\"\\n</commit_messages>\\n\\n<git_commits>\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in <commit_analysis> tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond the context of git\\n\\n4. Draft a commit message:\\n - Follow <commit_messages>\\n - Review draft against the litmus test before committing\\n\\n5. Create commit with attribution using HEREDOC:\\n git commit -m \\\"$(cat &lt;&lt;'EOF'\\nCommit message here.\\n\\n\\n\U0001F498 Generated with Crush\\n\\n\\n\\nCo-Authored-By: Crush <crush@charm.land>\\n\\nEOF\\n)\\\"\\n\\n6. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n7. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response, when rebasing always use -m.\\n</git_commits>\\n\\n<pull_requests>\\n\\n\\nWhen user asks you to create or update a PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n\\n3. Commit changes if needed\\n\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in <pr_analysis> tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n\\n6. Draft a PR message:\\n - Follow <git_message_quality>\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Use clear, concise language\\n - Provide an accurate reflection of changes and purpose\\n - Avoid generic summaries; messages should be thoughtful\\n - Review draft against the litmus test before creating or updating the PR\\n\\n7. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat &lt;&lt;'EOF'\\n\\n<summary>\\n\\n\U0001F498 Generated with Crush\\n\\nEOF\\n)\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"properties\":{\"auto_background_after\":{\"description\":\"Seconds to wait before automatically moving the command to a background job (default: 60)\",\"type\":\"integer\"},\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does, try to keep it under 30 characters or so\",\"type\":\"string\"},\"run_in_background\":{\"description\":\"Set to true (boolean) to run this command in the background. Use job_output to read the output later.\",\"type\":\"boolean\"},\"working_dir\":{\"description\":\"The working directory to execute the command in (defaults to current directory)\",\"type\":\"string\"}},\"required\":[\"description\",\"command\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Download a URL directly to a local file (binary-safe, streaming, max 600s timeout); overwrites without warning. For reading content into context use fetch.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"edit\",\"strict\":false,\"description\":\"Edit a file by exact find-and-replace; can also create or delete content. For renames/moves use bash. For large edits use write.\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiedit\",\"strict\":false,\"description\":\"Apply multiple find-and-replace edits to a single file in one operation; edits run sequentially. Prefer over edit for multiple changes to the same file. Same exact-match rules as edit apply.\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"properties\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"required\":[\"old_string\",\"new_string\"],\"type\":\"object\"},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"fetch\",\"strict\":false,\"description\":\"Fetch raw content from a URL as text, markdown, or html (max 100KB); no AI processing. For analysis or extraction use agentic_fetch.\\n\",\"parameters\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"glob\",\"strict\":false,\"description\":\"Find files by name/pattern (glob syntax), sorted by modification time; max 100 results; skips hidden files. Use grep to search file contents.\\n\",\"parameters\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"grep\",\"strict\":false,\"description\":\"Search file contents by regex or literal text; returns matching file paths sorted by modification time (max 100); respects .gitignore. Use glob to filter by filename, not contents.\\n\",\"parameters\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"ls\",\"strict\":false,\"description\":\"List files and directories as a tree; skips hidden files and common system dirs; max 1000 files. Use glob to find files by pattern, grep to search contents.\\n\",\"parameters\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{\"type\":\"string\"},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public GitHub repositories via Sourcegraph; supports regex, language/repo/file filters, and symbol search (max 20 results). Only searches public repos.\\n\",\"parameters\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"view\",\"strict\":false,\"description\":\"Read a file by path with line numbers; supports offset and line limit (default 200, max 200KB returned file content section); renders images (PNG, JPEG, GIF, WebP); use ls for directories.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 200)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"write\",\"strict\":false,\"description\":\"Create or overwrite a file with given content; auto-creates parent dirs. Cannot append. Read the file first to avoid conflicts. For surgical changes use edit or multiedit.\",\"parameters\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}"
593+ headers:
594+ Accept:
595+ - application/json
596+ Content-Type:
597+ - application/json
598+ User-Agent:
599+ - Charm-Crush/devel (https://charm.land/crush)
600+ url: https://hyper.charm.land/v1/chat/completions
601+ method: POST
602+ response:
603+ proto: HTTP/2.0
604+ proto_major: 2
605+ proto_minor: 0
606+ content_length: -1
607+ uncompressed: true
608+ body: |+
609+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
610+
611+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"No"},"finish_reason":null}]}
612+
613+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":","},"finish_reason":null}]}
614+
615+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" the"},"finish_reason":null}]}
616+
617+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" fetched"},"finish_reason":null}]}
618+
619+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" content"},"finish_reason":null}]}
620+
621+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" does"},"finish_reason":null}]}
622+
623+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" not"},"finish_reason":null}]}
624+
625+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" contain"},"finish_reason":null}]}
626+
627+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" the"},"finish_reason":null}]}
628+
629+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" word"},"finish_reason":null}]}
630+
631+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" \""},"finish_reason":null}]}
632+
633+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"John"},"finish_reason":null}]}
634+
635+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" Doe"},"finish_reason":null}]}
636+
637+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"\"."},"finish_reason":null}]}
638+
639+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
640+
641+ data: {"id":"chatcmpl-cd7a3a1eb813288fd5e12324","object":"chat.completion.chunk","created":1782413803,"model":"glm-5.1","choices":[],"usage":{"prompt_tokens":753,"completion_tokens":16,"total_tokens":8248,"prompt_tokens_details":{"cached_tokens":7479},"cost":{"usd":0.0011246000000000001,"hypercredits":0.022492},"remaining":{"hypercredits":0}}}
642+
643+ data: [DONE]
644+
645+ headers:
646+ Content-Type:
647+ - text/event-stream
648+ status: 200 OK
649+ code: 200
650+ duration: 977.248916ms
internal/agent/testdata/TestCoderAgent/glm-5.1/glob_tool.yamlnew file+737
@@ -0,0 +1,737 @@
1+---
2+version: 2
3+interactions:
4+- id: 0
5+ request:
6+ proto: HTTP/1.1
7+ proto_major: 1
8+ proto_minor: 1
9+ content_length: 35633
10+ host: ""
11+ body: "{\"messages\":[{\"content\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\n\\n<critical_rules>\\nThese rules override everything else. Follow them strictly:\\n\\n1. **READ THE RELEVANT CONTEXT BEFORE EDITING**: Never edit a file you haven't already read the relevant context for in this conversation. Once read, you don't need to re-read unless it changed. Pay close attention to exact formatting, indentation, and whitespace - these must match exactly in your edits.\\n2. **BE AUTONOMOUS**: Don't ask questions - search, read, think, decide, act. Break complex tasks into steps and complete them all. Systematically try alternative strategies (different commands, search terms, tools, refactors, or scopes) until either the task is complete or you hit a hard external limit (missing credentials, permissions, files, or network access you cannot change). Only stop for actual blocking errors, not perceived difficulty.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification.\\n4. **BE CONCISE**: Keep output concise (default <4 lines), unless explaining complex changes or asked for detail. Conciseness applies to output only, not to thoroughness of work.\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks.\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\". When committing, follow the `<git_commits>` format from the bash tool description exactly, including any configured attribution lines.\\n7. **FOLLOW MEMORY FILE INSTRUCTIONS**: If memory files contain specific instructions, preferences, or commands, you MUST follow them.\\n8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so. Focus on *why* not *what*. NEVER communicate with the user through code comments.\\n9. **SECURITY FIRST**: Only assist with defensive security tasks. Refuse to create, modify, or improve code that may be used maliciously.\\n10. **NO URL GUESSING**: Only use URLs provided by the user or found in local files.\\n11. **NEVER PUSH TO REMOTE**: Don't push changes to remote repositories unless explicitly asked.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **TOOL CONSTRAINTS**: Only use documented tools. Never attempt 'apply_patch' or 'apply_diff' - they don't exist. Use 'edit' or 'multiedit' instead.\\n14. **LOAD MATCHING SKILLS**: If any entry in `<available_skills>` matches the current task, you MUST call `view` on its `<location>` before taking any other action for that task. The `<description>` is only a trigger — the actual procedure, scripts, and references live in SKILL.md. Do NOT infer a skill's behavior from its description or skip loading it because you think you already know how to do the task.\\n15. **LIMIT FILE READS**: Avoid reading entire files, as they can be very large. Read only the sections you need using 'offset' and 'limit' parameters.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- ALWAYS think and respond in the same spoken language the prompt was written in.\\n- Under 4 lines of text (tool use doesn't count)\\n- Conciseness is about **text only**: always fully implement the requested feature, tests, and wiring even if that requires many tool calls.\\n- No preamble (\\\"Here's...\\\", \\\"I'll...\\\")\\n- No postamble (\\\"Let me know...\\\", \\\"Hope this helps...\\\")\\n- One-word answers when possible\\n- No emojis ever\\n- No explanations unless user asks\\n- Never send acknowledgement-only responses; after receiving new context or instructions, immediately continue the task or state the concrete next action you will take.\\n- Use rich Markdown formatting (headings, bullet lists, tables, code fences) for any multi-sentence or explanatory answer; only use plain unformatted text if the user explicitly asks.\\n\\nExamples:\\nuser: what is 2+2?\\nassistant: 4\\n\\nuser: list files in src/\\nassistant: [uses ls tool]\\nfoo.c, bar.c, baz.c\\n\\nuser: which file has the foo implementation?\\nassistant: src/foo.c\\n\\nuser: add error handling to the login function\\nassistant: [searches for login, reads file, edits with exact match, runs tests]\\nDone\\n\\nuser: Where are errors from the client handled?\\nassistant: Clients are marked as failed in the `connectToServer` function in src/services/process.go:712.\\n</communication_style>\\n\\n<code_references>\\nWhen referencing specific functions or code locations, use the pattern `file_path:line_number` to help users navigate:\\n- Example: \\\"The error is handled in src/main.go:45\\\"\\n- Example: \\\"See the implementation in pkg/utils/helper.go:123-145\\\"\\n</code_references>\\n\\n<workflow>\\nFor every task, follow this sequence internally (don't narrate it):\\n\\n**Before acting**:\\n- Search codebase for relevant files\\n- Read files to understand current state\\n- Check memory for stored commands\\n- Identify what needs to change\\n- Use `git log` and `git blame` for additional context when needed\\n\\n**While acting**:\\n- Read entire file before editing it\\n- Before editing: verify exact whitespace and indentation from View output\\n- Use exact text for find/replace (include whitespace)\\n- Make one logical change at a time\\n- After each change: run tests\\n- If tests fail: fix immediately\\n- If edit fails: read more context, don't guess - the text must match exactly\\n- Keep going until query is completely resolved before yielding to user\\n- For longer tasks, send brief progress updates (under 10 words) BUT IMMEDIATELY CONTINUE WORKING - progress updates are not stopping points\\n\\n**Before finishing**:\\n- Verify ENTIRE query is resolved (not just first step)\\n- All described next steps must be completed\\n- Cross-check the original prompt and your own mental checklist; if any feasible part remains undone, continue working instead of responding.\\n- Run lint/typecheck if in memory\\n- Verify all changes work\\n- Keep response under 4 lines\\n\\n**Key behaviors**:\\n- Use find_references before changing shared code\\n- Follow existing patterns (check similar files)\\n- If stuck, try different approach (don't repeat failures)\\n- Make decisions yourself (search first, don't ask)\\n- Fix problems at root cause, not surface-level patches\\n- Don't fix unrelated bugs or broken tests (mention them in final message if relevant)\\n</workflow>\\n\\n<decision_making>\\n**Make decisions autonomously** - don't ask when you can:\\n- Search to find the answer\\n- Read files to see patterns\\n- Check similar code\\n- Infer from context\\n- Try most likely approach\\n- When requirements are underspecified but not obviously dangerous, make the most reasonable assumptions based on project patterns and memory files, briefly state them if needed, and proceed instead of waiting for clarification.\\n\\n**Only stop/ask user if**:\\n- Truly ambiguous business requirement\\n- Multiple valid approaches with big tradeoffs\\n- Could cause data loss\\n- Exhausted all attempts and hit actual blocking errors\\n\\n**When requesting information/access**:\\n- Exhaust all available tools, searches, and reasonable assumptions first.\\n- Never say \\\"Need more info\\\" without detail.\\n- In the same message, list each missing item, why it is required, acceptable substitutes, and what you already attempted.\\n- State exactly what you will do once the information arrives so the user knows the next step.\\n\\nWhen you must stop, first finish all unblocked parts of the request, then clearly report: (a) what you tried, (b) exactly why you are blocked, and (c) the minimal external action required. Don't stop just because one path failed—exhaust multiple plausible approaches first.\\n\\n**Never stop for**:\\n- Task seems too large (break it down)\\n- Multiple files to change (change them)\\n- Concerns about \\\"session limits\\\" (no such limits exist)\\n- Work will take many steps (do all the steps)\\n\\nExamples of autonomous decisions:\\n- File location → search for similar files\\n- Test command → check package.json/memory\\n- Code style → read existing code\\n- Library choice → check what's used\\n- Naming → follow existing names\\n</decision_making>\\n\\n<editing_files>\\n**Available edit tools:**\\n- `edit` - Single find/replace in a file\\n- `multiedit` - Multiple find/replace operations in one file\\n- `write` - Create/overwrite entire file\\n\\nNever use `apply_patch` or similar - those tools don't exist.\\n\\nCritical: ALWAYS read the relevant context of files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the relevant context first - note the EXACT indentation (spaces vs tabs, count)\\n2. Copy the exact text including ALL whitespace, newlines, and indentation\\n3. Include 3-5 lines of context before and after the target\\n4. Verify your old_string would appear exactly once in the file\\n5. If uncertain about whitespace, include more surrounding context\\n6. Verify edit succeeded\\n7. Run tests\\n\\n**Whitespace matters**:\\n- Count spaces/tabs carefully (use View tool line numbers as reference)\\n- Include blank lines if they exist\\n- Match line endings exactly\\n- When in doubt, include MORE context rather than less\\n\\nEfficiency tips:\\n- Don't re-read files after successful edits (tool will fail if it didn't work)\\n- Same applies for making folders, deleting files, etc.\\n\\nCommon mistakes to avoid:\\n- Editing without reading first\\n- Approximate text matches\\n- Wrong indentation (spaces vs tabs, wrong count)\\n- Missing or extra blank lines\\n- Not enough context (text appears multiple times)\\n- Trimming whitespace that exists in the original\\n- Not testing after changes\\n</editing_files>\\n\\n<whitespace_and_exact_matching>\\nThe Edit tool is extremely literal. \\\"Close enough\\\" will fail.\\n\\n**Before every edit**:\\n1. View the file and locate the exact lines to change\\n2. Copy the text EXACTLY including:\\n - Every space and tab\\n - Every blank line\\n - Opening/closing braces position\\n - Comment formatting\\n3. Include enough surrounding lines (3-5) to make it unique\\n4. Double-check indentation level matches\\n\\n**Common failures**:\\n- `func foo() {` vs `func foo(){` (space before brace)\\n- Tab vs 4 spaces vs 2 spaces\\n- Missing blank line before/after\\n- `// comment` vs `//comment` (space after //)\\n- Different number of spaces in indentation\\n\\n**If edit fails**:\\n- View the file again at the specific location\\n- Copy even more context\\n- Check for tabs vs spaces\\n- Verify line endings\\n- Try including the entire function/block if needed\\n- Never retry with guessed changes - get the exact text first\\n</whitespace_and_exact_matching>\\n\\n<task_completion>\\nEnsure every task is implemented completely, not partially or sketched.\\n\\n1. **Think before acting** (for non-trivial tasks)\\n - Identify all components that need changes (models, logic, routes, config, tests, docs)\\n - Consider edge cases and error paths upfront\\n - Form a mental checklist of requirements before making the first edit\\n - This planning happens internally - don't narrate it to the user\\n\\n2. **Implement end-to-end**\\n - Treat every request as complete work: if adding a feature, wire it fully\\n - Update all affected files (callers, configs, tests, docs)\\n - Don't leave TODOs or \\\"you'll also need to...\\\" - do it yourself\\n - No task is too large - break it down and complete all parts\\n - For multi-part prompts, treat each bullet/question as a checklist item and ensure every item is implemented or answered. Partial completion is not an acceptable final state.\\n\\n3. **Verify before finishing**\\n - Re-read the original request and verify each requirement is met\\n - Check for missing error handling, edge cases, or unwired code\\n - Run tests to confirm the implementation works\\n - Only say \\\"Done\\\" when truly done - never stop mid-task\\n</task_completion>\\n\\n<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause (isolate with debug logs or minimal reproduction if needed)\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\n7. For each error, attempt at least two or three distinct remediation strategies (search similar code, adjust commands, narrow or widen scope, change approach) before concluding the problem is externally blocked.\\n\\nCommon errors:\\n- Import/Module → check paths, spelling, what exists\\n- Syntax → check brackets, indentation, typos\\n- Tests fail → read test, see what it expects\\n- File not found → use ls, check exact path\\n\\n**Edit tool \\\"old_string not found\\\"**:\\n- View the file again at the target location\\n- Copy the EXACT text including all whitespace\\n- Include more surrounding context (full function if needed)\\n- Check for tabs vs spaces, extra/missing blank lines\\n- Count indentation spaces carefully\\n- Don't retry with approximate matches - get the exact text\\n</error_handling>\\n\\n<memory_instructions>\\nMemory files store commands, preferences, and codebase info. Update them when you discover:\\n- Build/test/lint commands\\n- Code style preferences\\n- Important codebase patterns\\n- Useful project information\\n</memory_instructions>\\n\\n<code_conventions>\\nBefore writing code:\\n1. Check if library exists (look at imports, package.json)\\n2. Read similar code for patterns\\n3. Match existing style\\n4. Use same libraries/frameworks\\n5. Follow security best practices (never log secrets)\\n6. Don't use one-letter variable names unless requested\\n\\nNever assume libraries are available - verify first.\\n\\n**Ambition vs. precision**:\\n- New projects → be creative and ambitious with implementation\\n- Existing codebases → be surgical and precise, respect surrounding code\\n- Don't change filenames or variables unnecessarily\\n- Don't add formatters/linters/tests to codebases that don't have them\\n</code_conventions>\\n\\n<testing>\\nAfter significant changes:\\n- Start testing as specific as possible to code changed, then broaden to build confidence\\n- Use self-verification: write unit tests, add output logs, or use debug statements to verify your solutions\\n- Run relevant test suite\\n- If tests fail, fix before continuing\\n- Check memory for test commands\\n- Run lint/typecheck if available (on precise targets when possible)\\n- For formatters: iterate max 3 times to get it right; if still failing, present correct solution and note formatting issue\\n- Suggest adding commands to memory if not found\\n- Don't fix unrelated bugs or test failures (not your responsibility)\\n</testing>\\n\\n<tool_usage>\\n- Default to using tools (ls, grep, view, agent, tests, web_fetch, etc.) rather than speculation whenever they can reduce uncertainty or unlock progress, even if it takes multiple tool calls.\\n- Search before assuming\\n- Read files before editing\\n- Always use absolute paths for file operations (editing, reading, writing)\\n- Use Agent tool for complex searches\\n- Run tools in parallel when safe (no dependencies)\\n- When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution\\n- Summarize tool output for user (they don't see it)\\n- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.\\n- Only use the tools you know exist.\\n\\n<bash_commands>\\n**CRITICAL**: The `description` parameter is REQUIRED for all bash tool calls. Always provide it.\\n\\nWhen running non-trivial bash commands (especially those that modify the system):\\n- Briefly explain what the command does and why you're running it\\n- This ensures the user understands potentially dangerous operations\\n- Simple read-only commands (ls, cat, etc.) don't need explanation\\n- Use `&` for background processes that won't stop on their own (e.g., `node server.js &`)\\n- Avoid interactive commands - use non-interactive versions (e.g., `npm init -y` not `npm init`)\\n- Combine related commands to save time (e.g., `git status && git diff HEAD && git log -n 3`)\\n</bash_commands>\\n</tool_usage>\\n\\n<proactiveness>\\nBalance autonomy with user intent:\\n- When asked to do something → do it fully (including ALL follow-ups and \\\"next steps\\\")\\n- Never describe what you'll do next - just do it\\n- When the user provides new information or clarification, incorporate it immediately and keep executing instead of stopping with an acknowledgement.\\n- Responding with only a plan, outline, or TODO list (or any other purely verbal response) is failure; you must execute the plan via tools whenever execution is possible.\\n- When asked how to approach → explain first, don't auto-implement\\n- After completing work → stop, don't explain (unless asked)\\n- Don't surprise user with unexpected actions\\n</proactiveness>\\n\\n<final_answers>\\nAdapt verbosity to match the work completed:\\n\\n**Default (under 4 lines)**:\\n- Simple questions or single-file changes\\n- Casual conversation, greetings, acknowledgements\\n- One-word answers when possible\\n\\n**More detail allowed (up to 10-15 lines)**:\\n- Large multi-file changes that need walkthrough\\n- Complex refactoring where rationale adds value\\n- Tasks where understanding the approach is important\\n- When mentioning unrelated bugs/issues found\\n- Suggesting logical next steps user might want\\n- Structure longer answers with Markdown sections and lists, and put all code, commands, and config in fenced code blocks.\\n\\n**What to include in verbose answers**:\\n- Brief summary of what was done and why\\n- Key files/functions changed (with `file:line` references)\\n- Any important decisions or tradeoffs made\\n- Next steps or things user should verify\\n- Issues found but not fixed\\n\\n**What to avoid**:\\n- Don't show full file contents unless explicitly asked\\n- Don't explain how to save files or copy code (user has access to your work)\\n- Don't use \\\"Here's what I did\\\" or \\\"Let me know if...\\\" style preambles/postambles\\n- Keep tone direct and factual, like handing off work to a teammate\\n</final_answers>\\n\\n<env>\\nWorking directory: /tmp/crush-test/TestCoderAgent/glm-5.1/glob_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n<available_skills>\\n <skill>\\n <name>crush-hooks</name>\\n <description>Use when the user wants to add, write, debug, or configure a Crush hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in crush.json.</description>\\n <location>crush://skills/crush-hooks/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n <skill>\\n <name>jq</name>\\n <description>Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.</description>\\n <location>crush://skills/jq/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n</available_skills>\\n\\n<skills_usage>\\nThe `<description>` of each skill is a TRIGGER — it tells you *when* a skill applies. It is NOT a specification of what the skill does or how to do it. The procedure, scripts, commands, references, and required flags live only in the SKILL.md body. You do not know what a skill actually does until you have read its SKILL.md.\\n\\nMANDATORY activation flow:\\n1. Scan `<available_skills>` against the current user task.\\n2. If any skill's `<description>` matches, call the View tool with its `<location>` EXACTLY as shown — before any other tool call that performs the task.\\n3. Read the entire SKILL.md and follow its instructions.\\n4. Only then execute the task, using the skill's prescribed commands/tools.\\n\\nDo NOT skip step 2 because you think you already know how to do the task. Do NOT infer a skill's behavior from its name or description. If you find yourself about to run `bash`, `edit`, or any task-doing tool for a skill-eligible request without having just viewed the SKILL.md, stop and load the skill first.\\n\\nBuiltin skills (type=builtin) use virtual `crush://skills/...` location identifiers. The \\\"crush://\\\" prefix is NOT a URL, network address, or MCP resource — it is a special internal identifier the View tool understands natively. Pass the `<location>` verbatim to View.\\n\\nDo not use MCP tools (including read_mcp_resource) to load skills.\\nIf a skill mentions scripts, references, or assets, they live in the same folder as the skill itself (e.g., scripts/, references/, assets/ subdirectories within the skill's folder).\\n</skills_usage>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"<system_reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.\\nIf you are working on tasks that would benefit from a todo list please use the \\\"todos\\\" tool to create one.\\nIf not, please feel free to ignore. Again do not mention this message to the user.</system_reminder>\",\"role\":\"user\"},{\"content\":\"use glob to find all .go files in the current directory\",\"role\":\"user\"}],\"model\":\"glm-5.1\",\"max_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Execute shell commands; long-running commands automatically move to background and return a shell ID.\\n\\n<cross_platform>\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n</cross_platform>\\n\\n<execution_steps>\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Auto-Background: Commands exceeding 1 minute (default, configurable via `auto_background_after`) automatically move to background and return shell ID\\n5. Output Processing: Truncate if exceeds 30000 characters\\n6. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\n- Command required, working_dir optional (defaults to current directory)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '&&', avoid newlines except in quoted strings\\n- Each command runs in independent shell (no state persistence between calls)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n</usage_notes>\\n\\n<background_execution>\\n- Set run_in_background=true to run commands in a separate background shell\\n- Returns a shell ID for managing the background process\\n- Use job_output tool to view current output from background shell\\n- Use job_kill tool to terminate a background shell\\n- IMPORTANT: NEVER use `&` at the end of commands to run in background - use run_in_background parameter instead\\n- Commands that should run in background:\\n * Long-running servers (e.g., `npm start`, `python -m http.server`, `node server.js`)\\n * Watch/monitoring tasks (e.g., `npm run watch`, `tail -f logfile`)\\n * Continuous processes that don't exit on their own\\n * Any command expected to run indefinitely\\n- Commands that should NOT run in background:\\n * Build commands (e.g., `npm run build`, `go build`)\\n * Test suites (e.g., `npm test`, `pytest`)\\n * Git operations\\n * File operations\\n * Short-lived scripts\\n</background_execution>\\n\\n<git_message_quality>\\nThese rules apply whenever creating or updating commit messages, PR titles, or PR bodies:\\n\\n- Messages MUST be understandable to someone unfamiliar with the codebase.\\n- Before creating or updating a message, verify this litmus test: a new contributor reading only the commit message or PR title/body should understand what problem this solves, why it matters, and the impact without opening files, reading the diff, or knowing internal code names.\\n- Avoid code identifiers, filenames, function names, and implementation details unless they are necessary for understanding the user-facing impact.\\n- Bad: \\\"Add NameFromHex with sync.Once lazy init\\\"\\n- Good: \\\"Improve color name lookup performance while keeping startup fast\\\"\\n</git_message_quality>\\n\\n<commit_messages>\\nCommit messages are for future readers scanning history. Before committing:\\n\\n- Follow <git_message_quality>.\\n- Draft a concise 1-2 sentence message focusing on why the change exists and what outcome it enables, not a list of files or implementation details.\\n- Use clear, accurate verbs (\\\"add\\\"=new capability, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix) and avoid generic messages.\\n- The first line MUST be under 72 characters.\\n- Add a body only when it is needed to explain the reasoning, tradeoffs, or important context; wrap body lines at 72 characters.\\n- If the change is internal-only, still describe the benefit or maintenance outcome rather than naming private code.\\n- Bad: \\\"fix: nil pointer in session.go\\\"\\n- Good: \\\"fix: prevent session loading from crashing on missing metadata\\\"\\n- Bad: \\\"refactor: move PromptBuilder into internal/agent\\\"\\n- Good: \\\"refactor: make prompt assembly easier to maintain\\\"\\n</commit_messages>\\n\\n<git_commits>\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in <commit_analysis> tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond the context of git\\n\\n4. Draft a commit message:\\n - Follow <commit_messages>\\n - Review draft against the litmus test before committing\\n\\n5. Create commit with attribution using HEREDOC:\\n git commit -m \\\"$(cat &lt;&lt;'EOF'\\nCommit message here.\\n\\n\\n\U0001F498 Generated with Crush\\n\\n\\n\\nCo-Authored-By: Crush <crush@charm.land>\\n\\nEOF\\n)\\\"\\n\\n6. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n7. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response, when rebasing always use -m.\\n</git_commits>\\n\\n<pull_requests>\\n\\n\\nWhen user asks you to create or update a PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n\\n3. Commit changes if needed\\n\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in <pr_analysis> tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n\\n6. Draft a PR message:\\n - Follow <git_message_quality>\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Use clear, concise language\\n - Provide an accurate reflection of changes and purpose\\n - Avoid generic summaries; messages should be thoughtful\\n - Review draft against the litmus test before creating or updating the PR\\n\\n7. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat &lt;&lt;'EOF'\\n\\n<summary>\\n\\n\U0001F498 Generated with Crush\\n\\nEOF\\n)\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"properties\":{\"auto_background_after\":{\"description\":\"Seconds to wait before automatically moving the command to a background job (default: 60)\",\"type\":\"integer\"},\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does, try to keep it under 30 characters or so\",\"type\":\"string\"},\"run_in_background\":{\"description\":\"Set to true (boolean) to run this command in the background. Use job_output to read the output later.\",\"type\":\"boolean\"},\"working_dir\":{\"description\":\"The working directory to execute the command in (defaults to current directory)\",\"type\":\"string\"}},\"required\":[\"description\",\"command\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Download a URL directly to a local file (binary-safe, streaming, max 600s timeout); overwrites without warning. For reading content into context use fetch.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"edit\",\"strict\":false,\"description\":\"Edit a file by exact find-and-replace; can also create or delete content. For renames/moves use bash. For large edits use write.\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiedit\",\"strict\":false,\"description\":\"Apply multiple find-and-replace edits to a single file in one operation; edits run sequentially. Prefer over edit for multiple changes to the same file. Same exact-match rules as edit apply.\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"properties\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"required\":[\"old_string\",\"new_string\"],\"type\":\"object\"},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"fetch\",\"strict\":false,\"description\":\"Fetch raw content from a URL as text, markdown, or html (max 100KB); no AI processing. For analysis or extraction use agentic_fetch.\\n\",\"parameters\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"glob\",\"strict\":false,\"description\":\"Find files by name/pattern (glob syntax), sorted by modification time; max 100 results; skips hidden files. Use grep to search file contents.\\n\",\"parameters\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"grep\",\"strict\":false,\"description\":\"Search file contents by regex or literal text; returns matching file paths sorted by modification time (max 100); respects .gitignore. Use glob to filter by filename, not contents.\\n\",\"parameters\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"ls\",\"strict\":false,\"description\":\"List files and directories as a tree; skips hidden files and common system dirs; max 1000 files. Use glob to find files by pattern, grep to search contents.\\n\",\"parameters\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{\"type\":\"string\"},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public GitHub repositories via Sourcegraph; supports regex, language/repo/file filters, and symbol search (max 20 results). Only searches public repos.\\n\",\"parameters\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"view\",\"strict\":false,\"description\":\"Read a file by path with line numbers; supports offset and line limit (default 200, max 200KB returned file content section); renders images (PNG, JPEG, GIF, WebP); use ls for directories.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 200)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"write\",\"strict\":false,\"description\":\"Create or overwrite a file with given content; auto-creates parent dirs. Cannot append. Read the file first to avoid conflicts. For surgical changes use edit or multiedit.\",\"parameters\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}"
12+ headers:
13+ Accept:
14+ - application/json
15+ Content-Type:
16+ - application/json
17+ User-Agent:
18+ - Charm-Crush/devel (https://charm.land/crush)
19+ url: https://hyper.charm.land/v1/chat/completions
20+ method: POST
21+ response:
22+ proto: HTTP/2.0
23+ proto_major: 2
24+ proto_minor: 0
25+ content_length: -1
26+ uncompressed: true
27+ body: |+
28+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
29+
30+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"id":"call_ad74b69d4b477328","type":"function","index":0,"function":{"name":"glob","arguments":""}}]},"finish_reason":null}]}
31+
32+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"pattern\": \""}}]},"finish_reason":null}]}
33+
34+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"**"}}]},"finish_reason":null}]}
35+
36+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/*."}}]},"finish_reason":null}]}
37+
38+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"go"}}]},"finish_reason":null}]}
39+
40+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\""}}]},"finish_reason":null}]}
41+
42+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"finish_reason":null}]}
43+
44+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}]}
45+
46+ data: {"id":"chatcmpl-680977ab8e48dc961b5a65b4","object":"chat.completion.chunk","created":1782413805,"model":"glm-5.1","choices":[],"usage":{"prompt_tokens":679,"completion_tokens":13,"total_tokens":8171,"prompt_tokens_details":{"cached_tokens":7479},"cost":{"usd":0.0010077999999999999,"hypercredits":0.020155999999999997},"remaining":{"hypercredits":0}}}
47+
48+ data: [DONE]
49+
50+ headers:
51+ Content-Type:
52+ - text/event-stream
53+ status: 200 OK
54+ code: 200
55+ duration: 2.191829958s
56+- id: 1
57+ request:
58+ proto: HTTP/1.1
59+ proto_major: 1
60+ proto_minor: 1
61+ content_length: 35910
62+ host: ""
63+ body: "{\"messages\":[{\"content\":\"You are Crush, a powerful AI Assistant that runs in the CLI.\\n\\n<critical_rules>\\nThese rules override everything else. Follow them strictly:\\n\\n1. **READ THE RELEVANT CONTEXT BEFORE EDITING**: Never edit a file you haven't already read the relevant context for in this conversation. Once read, you don't need to re-read unless it changed. Pay close attention to exact formatting, indentation, and whitespace - these must match exactly in your edits.\\n2. **BE AUTONOMOUS**: Don't ask questions - search, read, think, decide, act. Break complex tasks into steps and complete them all. Systematically try alternative strategies (different commands, search terms, tools, refactors, or scopes) until either the task is complete or you hit a hard external limit (missing credentials, permissions, files, or network access you cannot change). Only stop for actual blocking errors, not perceived difficulty.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification.\\n4. **BE CONCISE**: Keep output concise (default <4 lines), unless explaining complex changes or asked for detail. Conciseness applies to output only, not to thoroughness of work.\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks.\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\". When committing, follow the `<git_commits>` format from the bash tool description exactly, including any configured attribution lines.\\n7. **FOLLOW MEMORY FILE INSTRUCTIONS**: If memory files contain specific instructions, preferences, or commands, you MUST follow them.\\n8. **NEVER ADD COMMENTS**: Only add comments if the user asked you to do so. Focus on *why* not *what*. NEVER communicate with the user through code comments.\\n9. **SECURITY FIRST**: Only assist with defensive security tasks. Refuse to create, modify, or improve code that may be used maliciously.\\n10. **NO URL GUESSING**: Only use URLs provided by the user or found in local files.\\n11. **NEVER PUSH TO REMOTE**: Don't push changes to remote repositories unless explicitly asked.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **TOOL CONSTRAINTS**: Only use documented tools. Never attempt 'apply_patch' or 'apply_diff' - they don't exist. Use 'edit' or 'multiedit' instead.\\n14. **LOAD MATCHING SKILLS**: If any entry in `<available_skills>` matches the current task, you MUST call `view` on its `<location>` before taking any other action for that task. The `<description>` is only a trigger — the actual procedure, scripts, and references live in SKILL.md. Do NOT infer a skill's behavior from its description or skip loading it because you think you already know how to do the task.\\n15. **LIMIT FILE READS**: Avoid reading entire files, as they can be very large. Read only the sections you need using 'offset' and 'limit' parameters.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- ALWAYS think and respond in the same spoken language the prompt was written in.\\n- Under 4 lines of text (tool use doesn't count)\\n- Conciseness is about **text only**: always fully implement the requested feature, tests, and wiring even if that requires many tool calls.\\n- No preamble (\\\"Here's...\\\", \\\"I'll...\\\")\\n- No postamble (\\\"Let me know...\\\", \\\"Hope this helps...\\\")\\n- One-word answers when possible\\n- No emojis ever\\n- No explanations unless user asks\\n- Never send acknowledgement-only responses; after receiving new context or instructions, immediately continue the task or state the concrete next action you will take.\\n- Use rich Markdown formatting (headings, bullet lists, tables, code fences) for any multi-sentence or explanatory answer; only use plain unformatted text if the user explicitly asks.\\n\\nExamples:\\nuser: what is 2+2?\\nassistant: 4\\n\\nuser: list files in src/\\nassistant: [uses ls tool]\\nfoo.c, bar.c, baz.c\\n\\nuser: which file has the foo implementation?\\nassistant: src/foo.c\\n\\nuser: add error handling to the login function\\nassistant: [searches for login, reads file, edits with exact match, runs tests]\\nDone\\n\\nuser: Where are errors from the client handled?\\nassistant: Clients are marked as failed in the `connectToServer` function in src/services/process.go:712.\\n</communication_style>\\n\\n<code_references>\\nWhen referencing specific functions or code locations, use the pattern `file_path:line_number` to help users navigate:\\n- Example: \\\"The error is handled in src/main.go:45\\\"\\n- Example: \\\"See the implementation in pkg/utils/helper.go:123-145\\\"\\n</code_references>\\n\\n<workflow>\\nFor every task, follow this sequence internally (don't narrate it):\\n\\n**Before acting**:\\n- Search codebase for relevant files\\n- Read files to understand current state\\n- Check memory for stored commands\\n- Identify what needs to change\\n- Use `git log` and `git blame` for additional context when needed\\n\\n**While acting**:\\n- Read entire file before editing it\\n- Before editing: verify exact whitespace and indentation from View output\\n- Use exact text for find/replace (include whitespace)\\n- Make one logical change at a time\\n- After each change: run tests\\n- If tests fail: fix immediately\\n- If edit fails: read more context, don't guess - the text must match exactly\\n- Keep going until query is completely resolved before yielding to user\\n- For longer tasks, send brief progress updates (under 10 words) BUT IMMEDIATELY CONTINUE WORKING - progress updates are not stopping points\\n\\n**Before finishing**:\\n- Verify ENTIRE query is resolved (not just first step)\\n- All described next steps must be completed\\n- Cross-check the original prompt and your own mental checklist; if any feasible part remains undone, continue working instead of responding.\\n- Run lint/typecheck if in memory\\n- Verify all changes work\\n- Keep response under 4 lines\\n\\n**Key behaviors**:\\n- Use find_references before changing shared code\\n- Follow existing patterns (check similar files)\\n- If stuck, try different approach (don't repeat failures)\\n- Make decisions yourself (search first, don't ask)\\n- Fix problems at root cause, not surface-level patches\\n- Don't fix unrelated bugs or broken tests (mention them in final message if relevant)\\n</workflow>\\n\\n<decision_making>\\n**Make decisions autonomously** - don't ask when you can:\\n- Search to find the answer\\n- Read files to see patterns\\n- Check similar code\\n- Infer from context\\n- Try most likely approach\\n- When requirements are underspecified but not obviously dangerous, make the most reasonable assumptions based on project patterns and memory files, briefly state them if needed, and proceed instead of waiting for clarification.\\n\\n**Only stop/ask user if**:\\n- Truly ambiguous business requirement\\n- Multiple valid approaches with big tradeoffs\\n- Could cause data loss\\n- Exhausted all attempts and hit actual blocking errors\\n\\n**When requesting information/access**:\\n- Exhaust all available tools, searches, and reasonable assumptions first.\\n- Never say \\\"Need more info\\\" without detail.\\n- In the same message, list each missing item, why it is required, acceptable substitutes, and what you already attempted.\\n- State exactly what you will do once the information arrives so the user knows the next step.\\n\\nWhen you must stop, first finish all unblocked parts of the request, then clearly report: (a) what you tried, (b) exactly why you are blocked, and (c) the minimal external action required. Don't stop just because one path failed—exhaust multiple plausible approaches first.\\n\\n**Never stop for**:\\n- Task seems too large (break it down)\\n- Multiple files to change (change them)\\n- Concerns about \\\"session limits\\\" (no such limits exist)\\n- Work will take many steps (do all the steps)\\n\\nExamples of autonomous decisions:\\n- File location → search for similar files\\n- Test command → check package.json/memory\\n- Code style → read existing code\\n- Library choice → check what's used\\n- Naming → follow existing names\\n</decision_making>\\n\\n<editing_files>\\n**Available edit tools:**\\n- `edit` - Single find/replace in a file\\n- `multiedit` - Multiple find/replace operations in one file\\n- `write` - Create/overwrite entire file\\n\\nNever use `apply_patch` or similar - those tools don't exist.\\n\\nCritical: ALWAYS read the relevant context of files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the relevant context first - note the EXACT indentation (spaces vs tabs, count)\\n2. Copy the exact text including ALL whitespace, newlines, and indentation\\n3. Include 3-5 lines of context before and after the target\\n4. Verify your old_string would appear exactly once in the file\\n5. If uncertain about whitespace, include more surrounding context\\n6. Verify edit succeeded\\n7. Run tests\\n\\n**Whitespace matters**:\\n- Count spaces/tabs carefully (use View tool line numbers as reference)\\n- Include blank lines if they exist\\n- Match line endings exactly\\n- When in doubt, include MORE context rather than less\\n\\nEfficiency tips:\\n- Don't re-read files after successful edits (tool will fail if it didn't work)\\n- Same applies for making folders, deleting files, etc.\\n\\nCommon mistakes to avoid:\\n- Editing without reading first\\n- Approximate text matches\\n- Wrong indentation (spaces vs tabs, wrong count)\\n- Missing or extra blank lines\\n- Not enough context (text appears multiple times)\\n- Trimming whitespace that exists in the original\\n- Not testing after changes\\n</editing_files>\\n\\n<whitespace_and_exact_matching>\\nThe Edit tool is extremely literal. \\\"Close enough\\\" will fail.\\n\\n**Before every edit**:\\n1. View the file and locate the exact lines to change\\n2. Copy the text EXACTLY including:\\n - Every space and tab\\n - Every blank line\\n - Opening/closing braces position\\n - Comment formatting\\n3. Include enough surrounding lines (3-5) to make it unique\\n4. Double-check indentation level matches\\n\\n**Common failures**:\\n- `func foo() {` vs `func foo(){` (space before brace)\\n- Tab vs 4 spaces vs 2 spaces\\n- Missing blank line before/after\\n- `// comment` vs `//comment` (space after //)\\n- Different number of spaces in indentation\\n\\n**If edit fails**:\\n- View the file again at the specific location\\n- Copy even more context\\n- Check for tabs vs spaces\\n- Verify line endings\\n- Try including the entire function/block if needed\\n- Never retry with guessed changes - get the exact text first\\n</whitespace_and_exact_matching>\\n\\n<task_completion>\\nEnsure every task is implemented completely, not partially or sketched.\\n\\n1. **Think before acting** (for non-trivial tasks)\\n - Identify all components that need changes (models, logic, routes, config, tests, docs)\\n - Consider edge cases and error paths upfront\\n - Form a mental checklist of requirements before making the first edit\\n - This planning happens internally - don't narrate it to the user\\n\\n2. **Implement end-to-end**\\n - Treat every request as complete work: if adding a feature, wire it fully\\n - Update all affected files (callers, configs, tests, docs)\\n - Don't leave TODOs or \\\"you'll also need to...\\\" - do it yourself\\n - No task is too large - break it down and complete all parts\\n - For multi-part prompts, treat each bullet/question as a checklist item and ensure every item is implemented or answered. Partial completion is not an acceptable final state.\\n\\n3. **Verify before finishing**\\n - Re-read the original request and verify each requirement is met\\n - Check for missing error handling, edge cases, or unwired code\\n - Run tests to confirm the implementation works\\n - Only say \\\"Done\\\" when truly done - never stop mid-task\\n</task_completion>\\n\\n<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause (isolate with debug logs or minimal reproduction if needed)\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\n7. For each error, attempt at least two or three distinct remediation strategies (search similar code, adjust commands, narrow or widen scope, change approach) before concluding the problem is externally blocked.\\n\\nCommon errors:\\n- Import/Module → check paths, spelling, what exists\\n- Syntax → check brackets, indentation, typos\\n- Tests fail → read test, see what it expects\\n- File not found → use ls, check exact path\\n\\n**Edit tool \\\"old_string not found\\\"**:\\n- View the file again at the target location\\n- Copy the EXACT text including all whitespace\\n- Include more surrounding context (full function if needed)\\n- Check for tabs vs spaces, extra/missing blank lines\\n- Count indentation spaces carefully\\n- Don't retry with approximate matches - get the exact text\\n</error_handling>\\n\\n<memory_instructions>\\nMemory files store commands, preferences, and codebase info. Update them when you discover:\\n- Build/test/lint commands\\n- Code style preferences\\n- Important codebase patterns\\n- Useful project information\\n</memory_instructions>\\n\\n<code_conventions>\\nBefore writing code:\\n1. Check if library exists (look at imports, package.json)\\n2. Read similar code for patterns\\n3. Match existing style\\n4. Use same libraries/frameworks\\n5. Follow security best practices (never log secrets)\\n6. Don't use one-letter variable names unless requested\\n\\nNever assume libraries are available - verify first.\\n\\n**Ambition vs. precision**:\\n- New projects → be creative and ambitious with implementation\\n- Existing codebases → be surgical and precise, respect surrounding code\\n- Don't change filenames or variables unnecessarily\\n- Don't add formatters/linters/tests to codebases that don't have them\\n</code_conventions>\\n\\n<testing>\\nAfter significant changes:\\n- Start testing as specific as possible to code changed, then broaden to build confidence\\n- Use self-verification: write unit tests, add output logs, or use debug statements to verify your solutions\\n- Run relevant test suite\\n- If tests fail, fix before continuing\\n- Check memory for test commands\\n- Run lint/typecheck if available (on precise targets when possible)\\n- For formatters: iterate max 3 times to get it right; if still failing, present correct solution and note formatting issue\\n- Suggest adding commands to memory if not found\\n- Don't fix unrelated bugs or test failures (not your responsibility)\\n</testing>\\n\\n<tool_usage>\\n- Default to using tools (ls, grep, view, agent, tests, web_fetch, etc.) rather than speculation whenever they can reduce uncertainty or unlock progress, even if it takes multiple tool calls.\\n- Search before assuming\\n- Read files before editing\\n- Always use absolute paths for file operations (editing, reading, writing)\\n- Use Agent tool for complex searches\\n- Run tools in parallel when safe (no dependencies)\\n- When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution\\n- Summarize tool output for user (they don't see it)\\n- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.\\n- Only use the tools you know exist.\\n\\n<bash_commands>\\n**CRITICAL**: The `description` parameter is REQUIRED for all bash tool calls. Always provide it.\\n\\nWhen running non-trivial bash commands (especially those that modify the system):\\n- Briefly explain what the command does and why you're running it\\n- This ensures the user understands potentially dangerous operations\\n- Simple read-only commands (ls, cat, etc.) don't need explanation\\n- Use `&` for background processes that won't stop on their own (e.g., `node server.js &`)\\n- Avoid interactive commands - use non-interactive versions (e.g., `npm init -y` not `npm init`)\\n- Combine related commands to save time (e.g., `git status && git diff HEAD && git log -n 3`)\\n</bash_commands>\\n</tool_usage>\\n\\n<proactiveness>\\nBalance autonomy with user intent:\\n- When asked to do something → do it fully (including ALL follow-ups and \\\"next steps\\\")\\n- Never describe what you'll do next - just do it\\n- When the user provides new information or clarification, incorporate it immediately and keep executing instead of stopping with an acknowledgement.\\n- Responding with only a plan, outline, or TODO list (or any other purely verbal response) is failure; you must execute the plan via tools whenever execution is possible.\\n- When asked how to approach → explain first, don't auto-implement\\n- After completing work → stop, don't explain (unless asked)\\n- Don't surprise user with unexpected actions\\n</proactiveness>\\n\\n<final_answers>\\nAdapt verbosity to match the work completed:\\n\\n**Default (under 4 lines)**:\\n- Simple questions or single-file changes\\n- Casual conversation, greetings, acknowledgements\\n- One-word answers when possible\\n\\n**More detail allowed (up to 10-15 lines)**:\\n- Large multi-file changes that need walkthrough\\n- Complex refactoring where rationale adds value\\n- Tasks where understanding the approach is important\\n- When mentioning unrelated bugs/issues found\\n- Suggesting logical next steps user might want\\n- Structure longer answers with Markdown sections and lists, and put all code, commands, and config in fenced code blocks.\\n\\n**What to include in verbose answers**:\\n- Brief summary of what was done and why\\n- Key files/functions changed (with `file:line` references)\\n- Any important decisions or tradeoffs made\\n- Next steps or things user should verify\\n- Issues found but not fixed\\n\\n**What to avoid**:\\n- Don't show full file contents unless explicitly asked\\n- Don't explain how to save files or copy code (user has access to your work)\\n- Don't use \\\"Here's what I did\\\" or \\\"Let me know if...\\\" style preambles/postambles\\n- Keep tone direct and factual, like handing off work to a teammate\\n</final_answers>\\n\\n<env>\\nWorking directory: /tmp/crush-test/TestCoderAgent/glm-5.1/glob_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n<available_skills>\\n <skill>\\n <name>crush-hooks</name>\\n <description>Use when the user wants to add, write, debug, or configure a Crush hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in crush.json.</description>\\n <location>crush://skills/crush-hooks/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n <skill>\\n <name>jq</name>\\n <description>Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.</description>\\n <location>crush://skills/jq/SKILL.md</location>\\n <type>builtin</type>\\n </skill>\\n</available_skills>\\n\\n<skills_usage>\\nThe `<description>` of each skill is a TRIGGER — it tells you *when* a skill applies. It is NOT a specification of what the skill does or how to do it. The procedure, scripts, commands, references, and required flags live only in the SKILL.md body. You do not know what a skill actually does until you have read its SKILL.md.\\n\\nMANDATORY activation flow:\\n1. Scan `<available_skills>` against the current user task.\\n2. If any skill's `<description>` matches, call the View tool with its `<location>` EXACTLY as shown — before any other tool call that performs the task.\\n3. Read the entire SKILL.md and follow its instructions.\\n4. Only then execute the task, using the skill's prescribed commands/tools.\\n\\nDo NOT skip step 2 because you think you already know how to do the task. Do NOT infer a skill's behavior from its name or description. If you find yourself about to run `bash`, `edit`, or any task-doing tool for a skill-eligible request without having just viewed the SKILL.md, stop and load the skill first.\\n\\nBuiltin skills (type=builtin) use virtual `crush://skills/...` location identifiers. The \\\"crush://\\\" prefix is NOT a URL, network address, or MCP resource — it is a special internal identifier the View tool understands natively. Pass the `<location>` verbatim to View.\\n\\nDo not use MCP tools (including read_mcp_resource) to load skills.\\nIf a skill mentions scripts, references, or assets, they live in the same folder as the skill itself (e.g., scripts/, references/, assets/ subdirectories within the skill's folder).\\n</skills_usage>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"<system_reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware.\\nIf you are working on tasks that would benefit from a todo list please use the \\\"todos\\\" tool to create one.\\nIf not, please feel free to ignore. Again do not mention this message to the user.</system_reminder>\",\"role\":\"user\"},{\"content\":\"use glob to find all .go files in the current directory\",\"role\":\"user\"},{\"tool_calls\":[{\"id\":\"call_ad74b69d4b477328\",\"function\":{\"arguments\":\"{\\\"pattern\\\": \\\"**/*.go\\\"}\",\"name\":\"glob\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"/tmp/crush-test/TestCoderAgent/glm-5.1/glob_tool/main.go\",\"tool_call_id\":\"call_ad74b69d4b477328\",\"role\":\"tool\"}],\"model\":\"glm-5.1\",\"max_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Execute shell commands; long-running commands automatically move to background and return a shell ID.\\n\\n<cross_platform>\\nUses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).\\nUse forward slashes for paths: \\\"ls C:/foo/bar\\\" not \\\"ls C:\\\\foo\\\\bar\\\".\\nCommon shell builtins and core utils available on Windows.\\n</cross_platform>\\n\\n<execution_steps>\\n1. Directory Verification: If creating directories/files, use LS tool to verify parent exists\\n2. Security Check: Banned commands (alias, aria2c, axel, chrome, curl, curlie, firefox, http-prompt, httpie, links, lynx, nc, safari, scp, ssh, telnet, w3m, wget, xh, doas, su, sudo, apk, apt, apt-cache, apt-get, dnf, dpkg, emerge, home-manager, makepkg, opkg, pacman, paru, pkg, pkg_add, pkg_delete, portage, rpm, yay, yum, zypper, at, batch, chkconfig, crontab, fdisk, mkfs, mount, parted, service, systemctl, umount, firewall-cmd, ifconfig, ip, iptables, netstat, pfctl, route, ufw) return error - explain to user. Safe read-only commands execute without prompts\\n3. Command Execution: Execute with proper quoting, capture output\\n4. Auto-Background: Commands exceeding 1 minute (default, configurable via `auto_background_after`) automatically move to background and return shell ID\\n5. Output Processing: Truncate if exceeds 30000 characters\\n6. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\n- Command required, working_dir optional (defaults to current directory)\\n- IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'\\n- Chain with ';' or '&&', avoid newlines except in quoted strings\\n- Each command runs in independent shell (no state persistence between calls)\\n- Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)\\n</usage_notes>\\n\\n<background_execution>\\n- Set run_in_background=true to run commands in a separate background shell\\n- Returns a shell ID for managing the background process\\n- Use job_output tool to view current output from background shell\\n- Use job_kill tool to terminate a background shell\\n- IMPORTANT: NEVER use `&` at the end of commands to run in background - use run_in_background parameter instead\\n- Commands that should run in background:\\n * Long-running servers (e.g., `npm start`, `python -m http.server`, `node server.js`)\\n * Watch/monitoring tasks (e.g., `npm run watch`, `tail -f logfile`)\\n * Continuous processes that don't exit on their own\\n * Any command expected to run indefinitely\\n- Commands that should NOT run in background:\\n * Build commands (e.g., `npm run build`, `go build`)\\n * Test suites (e.g., `npm test`, `pytest`)\\n * Git operations\\n * File operations\\n * Short-lived scripts\\n</background_execution>\\n\\n<git_message_quality>\\nThese rules apply whenever creating or updating commit messages, PR titles, or PR bodies:\\n\\n- Messages MUST be understandable to someone unfamiliar with the codebase.\\n- Before creating or updating a message, verify this litmus test: a new contributor reading only the commit message or PR title/body should understand what problem this solves, why it matters, and the impact without opening files, reading the diff, or knowing internal code names.\\n- Avoid code identifiers, filenames, function names, and implementation details unless they are necessary for understanding the user-facing impact.\\n- Bad: \\\"Add NameFromHex with sync.Once lazy init\\\"\\n- Good: \\\"Improve color name lookup performance while keeping startup fast\\\"\\n</git_message_quality>\\n\\n<commit_messages>\\nCommit messages are for future readers scanning history. Before committing:\\n\\n- Follow <git_message_quality>.\\n- Draft a concise 1-2 sentence message focusing on why the change exists and what outcome it enables, not a list of files or implementation details.\\n- Use clear, accurate verbs (\\\"add\\\"=new capability, \\\"update\\\"=enhancement, \\\"fix\\\"=bug fix) and avoid generic messages.\\n- The first line MUST be under 72 characters.\\n- Add a body only when it is needed to explain the reasoning, tradeoffs, or important context; wrap body lines at 72 characters.\\n- If the change is internal-only, still describe the benefit or maintenance outcome rather than naming private code.\\n- Bad: \\\"fix: nil pointer in session.go\\\"\\n- Good: \\\"fix: prevent session loading from crashing on missing metadata\\\"\\n- Bad: \\\"refactor: move PromptBuilder into internal/agent\\\"\\n- Good: \\\"refactor: make prompt assembly easier to maintain\\\"\\n</commit_messages>\\n\\n<git_commits>\\nWhen user asks to create git commit:\\n\\n1. Single message with three tool_use blocks (IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - git log (recent commit message style)\\n\\n2. Add relevant untracked files to staging. Don't commit files already modified at conversation start unless relevant.\\n\\n3. Analyze staged changes in <commit_analysis> tags:\\n - List changed/added files, summarize nature (feature/enhancement/bug fix/refactoring/test/docs)\\n - Brainstorm purpose/motivation, assess project impact, check for sensitive info\\n - Don't use tools beyond the context of git\\n\\n4. Draft a commit message:\\n - Follow <commit_messages>\\n - Review draft against the litmus test before committing\\n\\n5. Create commit with attribution using HEREDOC:\\n git commit -m \\\"$(cat &lt;&lt;'EOF'\\nCommit message here.\\n\\n\\n\U0001F498 Generated with Crush\\n\\n\\n\\nCo-Authored-By: Crush <crush@charm.land>\\n\\nEOF\\n)\\\"\\n\\n6. If pre-commit hook fails, retry ONCE. If fails again, hook preventing commit. If succeeds but files modified, MUST amend.\\n\\n7. Run git status to verify.\\n\\nNotes: Use \\\"git commit -am\\\" when possible, don't stage unrelated files, NEVER update config, don't push, no -i flags, no empty commits, return empty response, when rebasing always use -m.\\n</git_commits>\\n\\n<pull_requests>\\n\\n\\nWhen user asks you to create or update a PR:\\n\\n1. Single message with multiple tool_use blocks (VERY IMPORTANT for speed):\\n - git status (untracked files)\\n - git diff (staged/unstaged changes)\\n - Check if branch tracks remote and is up to date\\n - git log and 'git diff main...HEAD' (full commit history from main divergence)\\n\\n2. Create new branch if needed\\n\\n3. Commit changes if needed\\n\\n4. Push to remote with -u flag if needed\\n\\n5. Analyze changes in <pr_analysis> tags:\\n - List commits since diverging from main\\n - Summarize nature of changes\\n - Brainstorm purpose/motivation\\n - Assess project impact\\n - Don't use tools beyond git context\\n - Check for sensitive information\\n\\n6. Draft a PR message:\\n - Follow <git_message_quality>\\n - Draft concise (1-2 bullet points) PR summary focusing on \\\"why\\\"\\n - Ensure summary reflects ALL changes since main divergence\\n - Use clear, concise language\\n - Provide an accurate reflection of changes and purpose\\n - Avoid generic summaries; messages should be thoughtful\\n - Review draft against the litmus test before creating or updating the PR\\n\\n7. Create PR with gh pr create using HEREDOC:\\n gh pr create --title \\\"title\\\" --body \\\"$(cat &lt;&lt;'EOF'\\n\\n<summary>\\n\\n\U0001F498 Generated with Crush\\n\\nEOF\\n)\\\"\\n\\nImportant:\\n\\n- Return empty response - user sees gh output\\n- Never update git config\\n</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"properties\":{\"auto_background_after\":{\"description\":\"Seconds to wait before automatically moving the command to a background job (default: 60)\",\"type\":\"integer\"},\"command\":{\"description\":\"The command to execute\",\"type\":\"string\"},\"description\":{\"description\":\"A brief description of what the command does, try to keep it under 30 characters or so\",\"type\":\"string\"},\"run_in_background\":{\"description\":\"Set to true (boolean) to run this command in the background. Use job_output to read the output later.\",\"type\":\"boolean\"},\"working_dir\":{\"description\":\"The working directory to execute the command in (defaults to current directory)\",\"type\":\"string\"}},\"required\":[\"description\",\"command\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Download a URL directly to a local file (binary-safe, streaming, max 600s timeout); overwrites without warning. For reading content into context use fetch.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The local file path where the downloaded content should be saved\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 600)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to download from\",\"type\":\"string\"}},\"required\":[\"url\",\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"edit\",\"strict\":false,\"description\":\"Edit a file by exact find-and-replace; can also create or delete content. For renames/moves use bash. For large edits use write.\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"},\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false)\",\"type\":\"boolean\"}},\"required\":[\"file_path\",\"old_string\",\"new_string\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiedit\",\"strict\":false,\"description\":\"Apply multiple find-and-replace edits to a single file in one operation; edits run sequentially. Prefer over edit for multiple changes to the same file. Same exact-match rules as edit apply.\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{\"properties\":{\"new_string\":{\"description\":\"The text to replace it with\",\"type\":\"string\"},\"old_string\":{\"description\":\"The text to replace\",\"type\":\"string\"},\"replace_all\":{\"description\":\"Replace all occurrences of old_string (default false).\",\"type\":\"boolean\"}},\"required\":[\"old_string\",\"new_string\"],\"type\":\"object\"},\"type\":\"array\"},\"file_path\":{\"description\":\"The absolute path to the file to modify\",\"type\":\"string\"}},\"required\":[\"file_path\",\"edits\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"fetch\",\"strict\":false,\"description\":\"Fetch raw content from a URL as text, markdown, or html (max 100KB); no AI processing. For analysis or extraction use agentic_fetch.\\n\",\"parameters\":{\"properties\":{\"format\":{\"description\":\"The format to return the content in (text, markdown, or html)\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"},\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\"}},\"required\":[\"url\",\"format\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"glob\",\"strict\":false,\"description\":\"Find files by name/pattern (glob syntax), sorted by modification time; max 100 results; skips hidden files. Use grep to search file contents.\\n\",\"parameters\":{\"properties\":{\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The glob pattern to match files against\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"grep\",\"strict\":false,\"description\":\"Search file contents by regex or literal text; returns matching file paths sorted by modification time (max 100); respects .gitignore. Use glob to filter by filename, not contents.\\n\",\"parameters\":{\"properties\":{\"include\":{\"description\":\"File pattern to include in the search (e.g. \\\"*.js\\\", \\\"*.{ts,tsx}\\\")\",\"type\":\"string\"},\"literal_text\":{\"description\":\"If true, the pattern will be treated as literal text with special regex characters escaped. Default is false.\",\"type\":\"boolean\"},\"path\":{\"description\":\"The directory to search in. Defaults to the current working directory.\",\"type\":\"string\"},\"pattern\":{\"description\":\"The regex pattern to search for in file contents\",\"type\":\"string\"}},\"required\":[\"pattern\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"ls\",\"strict\":false,\"description\":\"List files and directories as a tree; skips hidden files and common system dirs; max 1000 files. Use glob to find files by pattern, grep to search contents.\\n\",\"parameters\":{\"properties\":{\"depth\":{\"description\":\"The maximum depth to traverse\",\"type\":\"integer\"},\"ignore\":{\"description\":\"List of glob patterns to ignore\",\"items\":{\"type\":\"string\"},\"type\":\"array\"},\"path\":{\"description\":\"The path to the directory to list (defaults to current working directory)\",\"type\":\"string\"}},\"required\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public GitHub repositories via Sourcegraph; supports regex, language/repo/file filters, and symbol search (max 20 results). Only searches public repos.\\n\",\"parameters\":{\"properties\":{\"context_window\":{\"description\":\"The context around the match to return (default: 10 lines)\",\"type\":\"integer\"},\"count\":{\"description\":\"Optional number of results to return (default: 10, max: 20)\",\"type\":\"integer\"},\"query\":{\"description\":\"The Sourcegraph search query\",\"type\":\"string\"},\"timeout\":{\"description\":\"Optional timeout in seconds (max 120)\",\"type\":\"integer\"}},\"required\":[\"query\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"view\",\"strict\":false,\"description\":\"Read a file by path with line numbers; supports offset and line limit (default 200, max 200KB returned file content section); renders images (PNG, JPEG, GIF, WebP); use ls for directories.\\n\",\"parameters\":{\"properties\":{\"file_path\":{\"description\":\"The path to the file to read\",\"type\":\"string\"},\"limit\":{\"description\":\"The number of lines to read (defaults to 200)\",\"type\":\"integer\"},\"offset\":{\"description\":\"The line number to start reading from (0-based)\",\"type\":\"integer\"}},\"required\":[\"file_path\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"write\",\"strict\":false,\"description\":\"Create or overwrite a file with given content; auto-creates parent dirs. Cannot append. Read the file first to avoid conflicts. For surgical changes use edit or multiedit.\",\"parameters\":{\"properties\":{\"content\":{\"description\":\"The content to write to the file\",\"type\":\"string\"},\"file_path\":{\"description\":\"The path to the file to write\",\"type\":\"string\"}},\"required\":[\"file_path\",\"content\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}"
64+ headers:
65+ Accept:
66+ - application/json
67+ Content-Type:
68+ - application/json
69+ User-Agent:
70+ - Charm-Crush/devel (https://charm.land/crush)
71+ url: https://hyper.charm.land/v1/chat/completions
72+ method: POST
73+ response:
74+ proto: HTTP/2.0
75+ proto_major: 2
76+ proto_minor: 0
77+ content_length: -1
78+ uncompressed: true
79+ body: |+
80+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
81+
82+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"Found"},"finish_reason":null}]}
83+
84+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" "},"finish_reason":null}]}
85+
86+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"1"},"finish_reason":null}]}
87+
88+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" `."},"finish_reason":null}]}
89+
90+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"go"},"finish_reason":null}]}
91+
92+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"`"},"finish_reason":null}]}
93+
94+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" file"},"finish_reason":null}]}
95+
96+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":":"},"finish_reason":null}]}
97+
98+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":" `"},"finish_reason":null}]}
99+
100+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"main"},"finish_reason":null}]}
101+
102+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":".go"},"finish_reason":null}]}
103+
104+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{"content":"`"},"finish_reason":null}]}
105+
106+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
107+
108+ data: {"id":"chatcmpl-85e120b7a3fdf21599aee1ba","object":"chat.completion.chunk","created":1782413807,"model":"glm-5.1","choices":[],"usage":{"prompt_tokens":36,"completion_tokens":14,"total_tokens":8207,"prompt_tokens_details":{"cached_tokens":8157},"cost":{"usd":0.00011200000000000001,"hypercredits":0.0022400000000000002},"remaining":{"hypercredits":0}}}
109+
110+ data: [DONE]
111+
112+ headers:
113+ Content-Type:
114+ - text/event-stream
115+ status: 200 OK
116+ code: 200
117+ duration: 1.449032542s
118+- id: 2
119+ request:
120+ proto: HTTP/1.1
121+ proto_major: 1
122+ proto_minor: 1
123+ content_length: 814
124+ host: ""
125+ body: '{"messages":[{"content":"You will generate a short title based on the first message a user begins a conversation with.\n\n<rules>\n- Keep the title in the same language that the user wrote their message in.\n- Ensure it is not more than 50 characters long.\n- The title should be a summary of the user''s message.\n- It should be one line long.\n- Do not use quotes or colons.\n- The entire text you return will be used as the title.\n- Never return anything that is more than one sentence (one line) long.\n</rules>\n\n /no_think","role":"system"},{"content":"Generate a concise title for the following content:\n\nuse glob to find all .go files in the current directory\n <think>\n\n</think>","role":"user"}],"model":"gpt-oss-120b","max_completion_tokens":40,"stream_options":{"include_usage":true},"stream":true}'
126+ headers:
127+ Accept:
128+ - application/json
129+ Content-Type:
130+ - application/json
131+ User-Agent:
132+ - Charm-Crush/devel (https://charm.land/crush)
133+ url: https://hyper.charm.land/v1/chat/completions
134+ method: POST
135+ response:
136+ proto: HTTP/2.0
137+ proto_major: 2
138+ proto_minor: 0
139+ content_length: -1
140+ uncompressed: true
141+ body: |+
142+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
143+
144+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" user"},"finish_reason":null}]}
145+
146+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" wants"},"finish_reason":null}]}
147+
148+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" a"},"finish_reason":null}]}
149+
150+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" concise"},"finish_reason":null}]}
151+
152+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" title"},"finish_reason":null}]}
153+
154+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" for"},"finish_reason":null}]}
155+
156+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" the"},"finish_reason":null}]}
157+
158+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" content"},"finish_reason":null}]}
159+
160+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
161+
162+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
163+
164+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"use"},"finish_reason":null}]}
165+
166+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" glob"},"finish_reason":null}]}
167+
168+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" to"},"finish_reason":null}]}
169+
170+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" find"},"finish_reason":null}]}
171+
172+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" all"},"finish_reason":null}]}
173+
174+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ."},"finish_reason":null}]}
175+
176+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"go"},"finish_reason":null}]}
177+
178+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" files"},"finish_reason":null}]}
179+
180+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" in"},"finish_reason":null}]}
181+
182+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" the"},"finish_reason":null}]}
183+
184+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" current"},"finish_reason":null}]}
185+
186+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" directory"},"finish_reason":null}]}
187+
188+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\"."},"finish_reason":null}]}
189+
190+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Title"},"finish_reason":null}]}
191+
192+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" in"},"finish_reason":null}]}
193+
194+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" English"},"finish_reason":null}]}
195+
196+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
197+
198+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \u003c="},"finish_reason":null}]}
199+
200+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"50"},"finish_reason":null}]}
201+
202+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" characters"},"finish_reason":null}]}
203+
204+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
205+
206+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" one"},"finish_reason":null}]}
207+
208+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" line"},"finish_reason":null}]}
209+
210+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
211+
212+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" no"},"finish_reason":null}]}
213+
214+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" quotes"},"finish_reason":null}]}
215+
216+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" or"},"finish_reason":null}]}
217+
218+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" col"},"finish_reason":null}]}
219+
220+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"ons"},"finish_reason":null}]}
221+
222+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
223+
224+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Something"},"finish_reason":null}]}
225+
226+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" like"},"finish_reason":null}]}
227+
228+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
229+
230+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Finding"},"finish_reason":null}]}
231+
232+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ."},"finish_reason":null}]}
233+
234+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"go"},"finish_reason":null}]}
235+
236+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Files"},"finish_reason":null}]}
237+
238+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" with"},"finish_reason":null}]}
239+
240+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Glob"},"finish_reason":null}]}
241+
242+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" in"},"finish_reason":null}]}
243+
244+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Current"},"finish_reason":null}]}
245+
246+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Directory"},"finish_reason":null}]}
247+
248+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\"."},"finish_reason":null}]}
249+
250+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" That's"},"finish_reason":null}]}
251+
252+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" under"},"finish_reason":null}]}
253+
254+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
255+
256+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"50"},"finish_reason":null}]}
257+
258+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" characters"},"finish_reason":null}]}
259+
260+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
261+
262+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Count"},"finish_reason":null}]}
263+
264+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
265+
266+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
267+
268+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Finding"},"finish_reason":null}]}
269+
270+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ."},"finish_reason":null}]}
271+
272+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"go"},"finish_reason":null}]}
273+
274+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Files"},"finish_reason":null}]}
275+
276+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" with"},"finish_reason":null}]}
277+
278+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Glob"},"finish_reason":null}]}
279+
280+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" in"},"finish_reason":null}]}
281+
282+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Current"},"finish_reason":null}]}
283+
284+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Directory"},"finish_reason":null}]}
285+
286+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\""},"finish_reason":null}]}
287+
288+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ="},"finish_reason":null}]}
289+
290+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" let's"},"finish_reason":null}]}
291+
292+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" count"},"finish_reason":null}]}
293+
294+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
295+
296+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Finding"},"finish_reason":null}]}
297+
298+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
299+
300+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"7"},"finish_reason":null}]}
301+
302+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")"},"finish_reason":null}]}
303+
304+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" +"},"finish_reason":null}]}
305+
306+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
307+
308+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ("},"finish_reason":null}]}
309+
310+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"1"},"finish_reason":null}]}
311+
312+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")"},"finish_reason":null}]}
313+
314+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ="},"finish_reason":null}]}
315+
316+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"8"},"finish_reason":null}]}
317+
318+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
319+
320+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ."},"finish_reason":null}]}
321+
322+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"go"},"finish_reason":null}]}
323+
324+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
325+
326+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"3"},"finish_reason":null}]}
327+
328+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")"},"finish_reason":null}]}
329+
330+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" =\u003e"},"finish_reason":null}]}
331+
332+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" total"},"finish_reason":null}]}
333+
334+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
335+
336+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"11"},"finish_reason":null}]}
337+
338+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
339+
340+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
341+
342+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
343+
344+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"12"},"finish_reason":null}]}
345+
346+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
347+
348+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Files"},"finish_reason":null}]}
349+
350+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
351+
352+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"5"},"finish_reason":null}]}
353+
354+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
355+
356+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"17"},"finish_reason":null}]}
357+
358+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
359+
360+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
361+
362+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
363+
364+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"18"},"finish_reason":null}]}
365+
366+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
367+
368+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" with"},"finish_reason":null}]}
369+
370+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
371+
372+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"4"},"finish_reason":null}]}
373+
374+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
375+
376+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"22"},"finish_reason":null}]}
377+
378+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
379+
380+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
381+
382+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
383+
384+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"23"},"finish_reason":null}]}
385+
386+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
387+
388+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Glob"},"finish_reason":null}]}
389+
390+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
391+
392+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"4"},"finish_reason":null}]}
393+
394+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
395+
396+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"27"},"finish_reason":null}]}
397+
398+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
399+
400+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
401+
402+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
403+
404+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"28"},"finish_reason":null}]}
405+
406+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
407+
408+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" in"},"finish_reason":null}]}
409+
410+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
411+
412+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"2"},"finish_reason":null}]}
413+
414+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
415+
416+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"30"},"finish_reason":null}]}
417+
418+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
419+
420+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
421+
422+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
423+
424+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"31"},"finish_reason":null}]}
425+
426+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
427+
428+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Current"},"finish_reason":null}]}
429+
430+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
431+
432+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"7"},"finish_reason":null}]}
433+
434+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
435+
436+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"38"},"finish_reason":null}]}
437+
438+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
439+
440+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
441+
442+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
443+
444+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"39"},"finish_reason":null}]}
445+
446+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
447+
448+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Directory"},"finish_reason":null}]}
449+
450+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
451+
452+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"9"},"finish_reason":null}]}
453+
454+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
455+
456+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"48"},"finish_reason":null}]}
457+
458+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
459+
460+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" So"},"finish_reason":null}]}
461+
462+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
463+
464+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"48"},"finish_reason":null}]}
465+
466+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" characters"},"finish_reason":null}]}
467+
468+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
469+
470+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" okay"},"finish_reason":null}]}
471+
472+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
473+
474+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Or"},"finish_reason":null}]}
475+
476+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" \""},"finish_reason":null}]}
477+
478+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"Use"},"finish_reason":null}]}
479+
480+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" glob"},"finish_reason":null}]}
481+
482+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" to"},"finish_reason":null}]}
483+
484+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" locate"},"finish_reason":null}]}
485+
486+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ."},"finish_reason":null}]}
487+
488+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"go"},"finish_reason":null}]}
489+
490+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" files"},"finish_reason":null}]}
491+
492+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" in"},"finish_reason":null}]}
493+
494+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" current"},"finish_reason":null}]}
495+
496+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" dir"},"finish_reason":null}]}
497+
498+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"\"."},"finish_reason":null}]}
499+
500+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Let's"},"finish_reason":null}]}
501+
502+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" count"},"finish_reason":null}]}
503+
504+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":":"},"finish_reason":null}]}
505+
506+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Use"},"finish_reason":null}]}
507+
508+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
509+
510+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"3"},"finish_reason":null}]}
511+
512+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")+"},"finish_reason":null}]}
513+
514+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"space"},"finish_reason":null}]}
515+
516+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
517+
518+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"4"},"finish_reason":null}]}
519+
520+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
521+
522+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" glob"},"finish_reason":null}]}
523+
524+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
525+
526+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"4"},"finish_reason":null}]}
527+
528+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
529+
530+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"8"},"finish_reason":null}]}
531+
532+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
533+
534+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
535+
536+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
537+
538+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"9"},"finish_reason":null}]}
539+
540+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
541+
542+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" to"},"finish_reason":null}]}
543+
544+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
545+
546+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"2"},"finish_reason":null}]}
547+
548+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
549+
550+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"11"},"finish_reason":null}]}
551+
552+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
553+
554+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
555+
556+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
557+
558+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"12"},"finish_reason":null}]}
559+
560+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
561+
562+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" locate"},"finish_reason":null}]}
563+
564+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
565+
566+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"6"},"finish_reason":null}]}
567+
568+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
569+
570+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"18"},"finish_reason":null}]}
571+
572+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
573+
574+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
575+
576+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
577+
578+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"19"},"finish_reason":null}]}
579+
580+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
581+
582+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" ."},"finish_reason":null}]}
583+
584+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"go"},"finish_reason":null}]}
585+
586+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
587+
588+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"3"},"finish_reason":null}]}
589+
590+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
591+
592+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"22"},"finish_reason":null}]}
593+
594+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
595+
596+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
597+
598+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
599+
600+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"23"},"finish_reason":null}]}
601+
602+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
603+
604+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" files"},"finish_reason":null}]}
605+
606+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
607+
608+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"5"},"finish_reason":null}]}
609+
610+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
611+
612+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"28"},"finish_reason":null}]}
613+
614+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
615+
616+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
617+
618+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
619+
620+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"29"},"finish_reason":null}]}
621+
622+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
623+
624+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" in"},"finish_reason":null}]}
625+
626+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
627+
628+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"2"},"finish_reason":null}]}
629+
630+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
631+
632+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"31"},"finish_reason":null}]}
633+
634+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
635+
636+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
637+
638+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
639+
640+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"32"},"finish_reason":null}]}
641+
642+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
643+
644+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" current"},"finish_reason":null}]}
645+
646+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
647+
648+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"7"},"finish_reason":null}]}
649+
650+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
651+
652+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"39"},"finish_reason":null}]}
653+
654+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
655+
656+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" space"},"finish_reason":null}]}
657+
658+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"="},"finish_reason":null}]}
659+
660+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"40"},"finish_reason":null}]}
661+
662+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
663+
664+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" dir"},"finish_reason":null}]}
665+
666+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"("},"finish_reason":null}]}
667+
668+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"3"},"finish_reason":null}]}
669+
670+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":")="},"finish_reason":null}]}
671+
672+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"43"},"finish_reason":null}]}
673+
674+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
675+
676+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" That's"},"finish_reason":null}]}
677+
678+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" "},"finish_reason":null}]}
679+
680+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"43"},"finish_reason":null}]}
681+
682+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
683+
684+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Both"},"finish_reason":null}]}
685+
686+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" fine"},"finish_reason":null}]}
687+
688+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
689+
690+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" Let's"},"finish_reason":null}]}
691+
692+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" output"},"finish_reason":null}]}
693+
694+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" one"},"finish_reason":null}]}
695+
696+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" line"},"finish_reason":null}]}
697+
698+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":","},"finish_reason":null}]}
699+
700+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" no"},"finish_reason":null}]}
701+
702+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":" quotes"},"finish_reason":null}]}
703+
704+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"reasoning_content":"."},"finish_reason":null}]}
705+
706+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":"Use"},"finish_reason":null}]}
707+
708+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" glob"},"finish_reason":null}]}
709+
710+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" to"},"finish_reason":null}]}
711+
712+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" locate"},"finish_reason":null}]}
713+
714+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" ."},"finish_reason":null}]}
715+
716+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":"go"},"finish_reason":null}]}
717+
718+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" files"},"finish_reason":null}]}
719+
720+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" in"},"finish_reason":null}]}
721+
722+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" current"},"finish_reason":null}]}
723+
724+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{"content":" directory"},"finish_reason":null}]}
725+
726+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
727+
728+ data: {"id":"chatcmpl-eb1b020a610e9fa7da88e894","object":"chat.completion.chunk","created":1782413804,"model":"gpt-oss-120b","choices":[],"usage":{"prompt_tokens":157,"completion_tokens":298,"total_tokens":519,"prompt_tokens_details":{"cached_tokens":64},"cost":{"usd":0.00019385200000000003,"hypercredits":0.0038770400000000004},"remaining":{"hypercredits":0}}}
729+
730+ data: [DONE]
731+
732+ headers:
733+ Content-Type:
734+ - text/event-stream
735+ status: 200 OK
736+ code: 200
737+ duration: 648.718041ms
internal/agent/testdata/TestCoderAgent/glm-5.1/grep_tool.yamlnew file+499

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/glm-5.1/ls_tool.yamlnew file+485

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/glm-5.1/multiedit_tool.yamlnew file+1439

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/glm-5.1/parallel_tool_calls.yamlnew file+685

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/glm-5.1/read_a_file.yamlnew file+413

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/glm-5.1/simple_test.yamlnew file+277

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/glm-5.1/sourcegraph_tool.yamlnew file+1479

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/glm-5.1/update_a_file.yamlnew file+747

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/glm-5.1/write_tool.yamlnew file+547

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/bash_tool.yamldeleted−174

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/download_tool.yamldeleted−198

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/fetch_tool.yamldeleted−218

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/glob_tool.yamldeleted−182

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/grep_tool.yamldeleted−212

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/ls_tool.yamldeleted−144

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/multiedit_tool.yamldeleted−553

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/parallel_tool_calls.yamldeleted−254

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/read_a_file.yamldeleted−293

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/simple_test.yamldeleted−83

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/sourcegraph_tool.yamldeleted−386

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/update_a_file.yamldeleted−509

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openai-gpt-5/write_tool.yamldeleted−220

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/bash_tool.yamldeleted−279

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/download_tool.yamldeleted−220

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/fetch_tool.yamldeleted−194

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/glob_tool.yamldeleted−136

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/grep_tool.yamldeleted−160

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/ls_tool.yamldeleted−176

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/multiedit_tool.yamldeleted−563

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/parallel_tool_calls.yamldeleted−210

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/read_a_file.yamldeleted−198

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/simple_test.yamldeleted−83

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/sourcegraph_tool.yamldeleted−186

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/update_a_file.yamldeleted−385

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/write_tool.yamldeleted−212

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/bash_tool.yamldeleted−310

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/download_tool.yamldeleted−162

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/fetch_tool.yamldeleted−228

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/glob_tool.yamldeleted−162

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/grep_tool.yamldeleted−196

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/ls_tool.yamldeleted−222

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/multiedit_tool.yamldeleted−269

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/parallel_tool_calls.yamldeleted−298

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/read_a_file.yamldeleted−142

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/simple_test.yamldeleted−189

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/sourcegraph_tool.yamldeleted−334

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/update_a_file.yamldeleted−189

This diff is too big to show here.

internal/agent/testdata/TestCoderAgent/zai-glm4.6/write_tool.yamldeleted−142

This diff is too big to show here.

internal/agent/tools/bash.go+214−92

This diff is too big to show here.

internal/agent/tools/bash.md.tplnew file+173

This diff is too big to show here.

internal/agent/tools/bash.tpldeleted−116

This diff is too big to show here.

internal/agent/tools/bash_test.gonew file+213

This diff is too big to show here.

internal/agent/tools/context_test.gonew file+233

This diff is too big to show here.

internal/agent/tools/crush_info.gonew file+487

This diff is too big to show here.

internal/agent/tools/crush_info.mdnew file+19

This diff is too big to show here.

internal/agent/tools/crush_info_test.gonew file+505

This diff is too big to show here.

internal/agent/tools/crush_logs.gonew file+514

This diff is too big to show here.

internal/agent/tools/crush_logs.md.tplnew file+13

This diff is too big to show here.

internal/agent/tools/crush_logs_test.gonew file+529

This diff is too big to show here.

internal/agent/tools/diagnostics.go+101−21

This diff is too big to show here.

internal/agent/tools/diagnostics.md+1−24

This diff is too big to show here.

internal/agent/tools/download.go+48−41

This diff is too big to show here.

internal/agent/tools/download.mddeleted−28

This diff is too big to show here.

internal/agent/tools/download.md.tplnew file+1

This diff is too big to show here.

internal/agent/tools/edit.go+108−75

This diff is too big to show here.

internal/agent/tools/edit.md+1−57

This diff is too big to show here.

internal/agent/tools/fetch.go+62−54

This diff is too big to show here.

internal/agent/tools/fetch.mddeleted−28

This diff is too big to show here.

internal/agent/tools/fetch.md.tplnew file+2

This diff is too big to show here.

internal/agent/tools/fetch_helpers.gonew file+175

This diff is too big to show here.

internal/agent/tools/fetch_types.gonew file+50

This diff is too big to show here.

internal/agent/tools/file.godeleted−53

This diff is too big to show here.

internal/agent/tools/glob.go+106−29

This diff is too big to show here.

internal/agent/tools/glob.mddeleted−40

This diff is too big to show here.

internal/agent/tools/glob.md.tplnew file+1

This diff is too big to show here.

internal/agent/tools/glob_test.gonew file+74

This diff is too big to show here.

internal/agent/tools/grep.go+73−46

This diff is too big to show here.

internal/agent/tools/grep.mddeleted−49

This diff is too big to show here.

internal/agent/tools/grep.md.tplnew file+1

This diff is too big to show here.

internal/agent/tools/job_kill.gonew file+60

This diff is too big to show here.

internal/agent/tools/job_kill.mdnew file+18

This diff is too big to show here.

internal/agent/tools/job_output.gonew file+92

This diff is too big to show here.

internal/agent/tools/job_output.mdnew file+1

This diff is too big to show here.

internal/agent/tools/job_test.gonew file+334

This diff is too big to show here.

internal/agent/tools/list_mcp_resources.gonew file+100

This diff is too big to show here.

internal/agent/tools/list_mcp_resources.mdnew file+1

This diff is too big to show here.

internal/agent/tools/ls.go+46−20

This diff is too big to show here.

internal/agent/tools/ls.mddeleted−34

This diff is too big to show here.

internal/agent/tools/ls.md.tplnew file+1

This diff is too big to show here.

internal/agent/tools/lsp_restart.gonew file+80

This diff is too big to show here.

internal/agent/tools/lsp_restart.mdnew file+1

This diff is too big to show here.

internal/agent/tools/mcp-tools.go+75−449

This diff is too big to show here.

internal/agent/tools/mcp/init.gonew file+554

This diff is too big to show here.

internal/agent/tools/mcp/init_test.gonew file+526

This diff is too big to show here.

internal/agent/tools/mcp/prompts.gonew file+88

This diff is too big to show here.

internal/agent/tools/mcp/resources.gonew file+109

This diff is too big to show here.

internal/agent/tools/mcp/tools.gonew file+248

This diff is too big to show here.

internal/agent/tools/mcp/tools_test.gonew file+117

This diff is too big to show here.

internal/agent/tools/multiedit.go+140−55

This diff is too big to show here.

internal/agent/tools/multiedit.md+1−47

This diff is too big to show here.

internal/agent/tools/multiedit_test.gonew file+214

This diff is too big to show here.

internal/agent/tools/read_mcp_resource.gonew file+103

This diff is too big to show here.

internal/agent/tools/read_mcp_resource.mdnew file+1

This diff is too big to show here.

internal/agent/tools/references.go+17−21

This diff is too big to show here.

internal/agent/tools/references.md+1−36

This diff is too big to show here.

internal/agent/tools/rg.go+10−1

This diff is too big to show here.

internal/agent/tools/safe.go+99−6

This diff is too big to show here.

internal/agent/tools/safe_test.gonew file+74

This diff is too big to show here.

internal/agent/tools/search.gonew file+219

This diff is too big to show here.

internal/agent/tools/sourcegraph.go+41−23

This diff is too big to show here.

internal/agent/tools/sourcegraph.mddeleted−55

This diff is too big to show here.

internal/agent/tools/sourcegraph.md.tplnew file+1

This diff is too big to show here.

internal/agent/tools/todos.gonew file+135

This diff is too big to show here.

internal/agent/tools/todos.mdnew file+1

This diff is too big to show here.

internal/agent/tools/tools.go+81−15

This diff is too big to show here.

internal/agent/tools/view.go+315−127

This diff is too big to show here.

internal/agent/tools/view.mddeleted−35

This diff is too big to show here.

internal/agent/tools/view.md.tplnew file+1

This diff is too big to show here.

internal/agent/tools/view_test.gonew file+356

This diff is too big to show here.

internal/agent/tools/web_fetch.gonew file+80

This diff is too big to show here.

internal/agent/tools/web_fetch.md.tplnew file+2

This diff is too big to show here.

internal/agent/tools/web_search.gonew file+62

This diff is too big to show here.

internal/agent/tools/web_search.md.tplnew file+2

This diff is too big to show here.

internal/agent/tools/write.go+54−49

This diff is too big to show here.

internal/agent/tools/write.md+1−30

This diff is too big to show here.

internal/agent/tools/write_test.gonew file+49

This diff is too big to show here.

internal/agent/usage_fallback.gonew file+167

This diff is too big to show here.

internal/agent/usage_fallback_test.gonew file+339

This diff is too big to show here.

internal/app/app.go+521−83

This diff is too big to show here.

internal/app/app_test.gonew file+183

This diff is too big to show here.

internal/app/lsp.godeleted−80

This diff is too big to show here.

internal/app/lsp_events.go+3−2

This diff is too big to show here.

internal/app/provider.gonew file+95

This diff is too big to show here.

internal/app/provider_test.gonew file+210

This diff is too big to show here.

internal/app/resolve_session_test.gonew file+174

This diff is too big to show here.

internal/app/testing.gonew file+72

This diff is too big to show here.

internal/backend/accepted_run_integration_test.gonew file+131

This diff is too big to show here.

internal/backend/agent.gonew file+273

This diff is too big to show here.

internal/backend/agent_runcomplete_test.gonew file+163

This diff is too big to show here.

internal/backend/agent_test.gonew file+164

This diff is too big to show here.

internal/backend/backend.gonew file+792

This diff is too big to show here.

internal/backend/backend_skills_test.gonew file+167

This diff is too big to show here.

internal/backend/backend_test.gonew file+1241

This diff is too big to show here.

internal/backend/config.gonew file+307

This diff is too big to show here.

internal/backend/config_test.gonew file+205

This diff is too big to show here.

internal/backend/events.gonew file+109

This diff is too big to show here.

internal/backend/filetracker.gonew file+37

This diff is too big to show here.

internal/backend/permission.gonew file+60

This diff is too big to show here.

internal/backend/race_off_test.gonew file+5

This diff is too big to show here.

internal/backend/race_on_test.gonew file+5

This diff is too big to show here.

internal/backend/session.gonew file+132

This diff is too big to show here.

internal/backend/shell_command_test.gonew file+54

This diff is too big to show here.

internal/backend/testing.gonew file+69

This diff is too big to show here.

internal/backend/util.gonew file+22

This diff is too big to show here.

internal/client/client.gonew file+213

This diff is too big to show here.

internal/client/config.gonew file+345

This diff is too big to show here.

internal/client/config_test.gonew file+101

This diff is too big to show here.

internal/client/dial_other.gonew file+13

This diff is too big to show here.

internal/client/dial_windows.gonew file+15

This diff is too big to show here.

internal/client/proto.gonew file+861

This diff is too big to show here.

internal/client/proto_test.gonew file+178

This diff is too big to show here.

internal/clipboard/clipboard.gonew file+44

This diff is too big to show here.

internal/clipboard/clipboard_not_supported.gonew file+13

This diff is too big to show here.

internal/clipboard/clipboard_supported.gonew file+30

This diff is too big to show here.

internal/cmd/clientserverrace/race_test.gonew file+361

This diff is too big to show here.

internal/cmd/dirs.go+63−38

This diff is too big to show here.

internal/cmd/dirs_test.godeleted−46

This diff is too big to show here.

internal/cmd/gitignore/defaultnew file+4

This diff is too big to show here.

internal/cmd/gitignore/oldnew file+1

This diff is too big to show here.

internal/cmd/login.gonew file+229

This diff is too big to show here.

internal/cmd/login_test.gonew file+21

This diff is too big to show here.

internal/cmd/logout.gonew file+182

This diff is too big to show here.

internal/cmd/logout_test.gonew file+41

This diff is too big to show here.

internal/cmd/logs.go+12−7

This diff is too big to show here.

internal/cmd/models.gonew file+155

This diff is too big to show here.

internal/cmd/projects.gonew file+77

This diff is too big to show here.

internal/cmd/projects_test.gonew file+56

This diff is too big to show here.

internal/cmd/root.go+653−67

This diff is too big to show here.

internal/cmd/root_other.gonew file+15

This diff is too big to show here.

internal/cmd/root_windows.gonew file+18

This diff is too big to show here.

internal/cmd/run.go+624−18

This diff is too big to show here.

internal/cmd/run_stream_test.go+417

This diff is too big to show here.

internal/cmd/schema.go+35−1

This diff is too big to show here.

internal/cmd/schema_test.go+59

This diff is too big to show here.

internal/cmd/server.go+99

This diff is too big to show here.

internal/cmd/server_other.go+12

This diff is too big to show here.

internal/cmd/server_windows.go+10

This diff is too big to show here.

internal/cmd/session.go+728

This diff is too big to show here.

internal/cmd/stats.go+390

This diff is too big to show here.

internal/cmd/stats/AGENTS.md+3

This diff is too big to show here.

internal/cmd/stats/footer.svg+838

This diff is too big to show here.

internal/cmd/stats/header.svg+673

This diff is too big to show here.

internal/cmd/stats/heartbit.svg+43

This diff is too big to show here.

internal/cmd/stats/index.css+270

This diff is too big to show here.

internal/cmd/stats/index.html+136

This diff is too big to show here.

internal/cmd/stats/index.js+356

This diff is too big to show here.

internal/cmd/update_providers.go+33−11

This diff is too big to show here.

internal/commands/commands.go+239

This diff is too big to show here.

internal/commands/commands_test.go+114

This diff is too big to show here.

internal/config/agent_id_test.go+29

This diff is too big to show here.

internal/config/atomicwrite.go+38

This diff is too big to show here.

internal/config/atomicwrite_test.go+43

This diff is too big to show here.

internal/config/attribution_migration_test.go+93

This diff is too big to show here.

internal/config/catwalk.go+82

This diff is too big to show here.

internal/config/catwalk_test.go+221

This diff is too big to show here.

internal/config/clone_test.go+46

This diff is too big to show here.

internal/config/config.go+507−185

This diff is too big to show here.

internal/config/copilot.go+1

This diff is too big to show here.

internal/config/docker_mcp.go+141

This diff is too big to show here.

internal/config/docker_mcp_test.go+195

This diff is too big to show here.

internal/config/hyper.go+124

This diff is too big to show here.

internal/config/hyper_test.go+205

This diff is too big to show here.

internal/config/init.go+35−23

This diff is too big to show here.

internal/config/load.go+750−147

This diff is too big to show here.

internal/config/load_bench_test.go+103

This diff is too big to show here.

internal/config/load_test.go+1162−117

This diff is too big to show here.

internal/config/mcp_resolved_url_test.go+105

This diff is too big to show here.

internal/config/merge.go−16

This diff is too big to show here.

internal/config/merge_test.go−27

This diff is too big to show here.

internal/config/provider.go+150−93

This diff is too big to show here.

internal/config/provider_empty_test.go+20−28

This diff is too big to show here.

internal/config/provider_test.go+277−42

This diff is too big to show here.

internal/config/recent_models_test.go+158

This diff is too big to show here.

internal/config/refresh_singleflight_test.go+175

This diff is too big to show here.

internal/config/reload_hooks_test.go+102

This diff is too big to show here.

internal/config/resolve.go+140−131

This diff is too big to show here.

internal/config/resolve_real_test.go+512

This diff is too big to show here.

internal/config/resolve_test.go+185−288

This diff is too big to show here.

internal/config/scope.go+29

This diff is too big to show here.

internal/config/scopeb_race_test.go+74

This diff is too big to show here.

internal/config/store.go+1078

This diff is too big to show here.

internal/config/store_test.go+784

This diff is too big to show here.

internal/config/update_model_bench_test.go+108

This diff is too big to show here.

internal/csync/maps.go+32−10

This diff is too big to show here.

internal/csync/maps_test.go+4−3

This diff is too big to show here.

internal/csync/slices.go+10−34

This diff is too big to show here.

internal/csync/slices_test.go−57

This diff is too big to show here.

internal/csync/value.go+44

This diff is too big to show here.

internal/csync/value_test.go+97

This diff is too big to show here.

internal/csync/versionedmap.go+5

This diff is too big to show here.

internal/db/connect.go+195−33

This diff is too big to show here.

internal/db/connect_modernc.go+31

This diff is too big to show here.

internal/db/connect_ncruces.go+33

This diff is too big to show here.

internal/db/connect_test.go+210

This diff is too big to show here.

internal/db/datadirlock.go+131

This diff is too big to show here.

internal/db/db.go+235−45

This diff is too big to show here.

internal/db/embed.go−6

This diff is too big to show here.

internal/db/files.sql.go+21−5

This diff is too big to show here.

internal/db/messages.sql.go+132−2

This diff is too big to show here.

internal/db/migrations/20250812000000_add_todos_to_sessions.sql+9

This diff is too big to show here.

internal/db/migrations/20260127000000_add_read_files_table.sql+20

This diff is too big to show here.

internal/db/migrations/20260701000000_add_composite_indexes.sql+12

This diff is too big to show here.

internal/db/migrations/20260702000000_add_hot_path_indexes.sql+14

This diff is too big to show here.

internal/db/models.go+8−1

This diff is too big to show here.

internal/db/querier.go+20−1

This diff is too big to show here.

internal/db/read_files.sql.go+79

This diff is too big to show here.

internal/db/sessions.sql.go+117−7

This diff is too big to show here.

internal/db/sql/files.sql+12−4

This diff is too big to show here.

internal/db/sql/messages.sql+19

This diff is too big to show here.

internal/db/sql/read_files.sql+20

This diff is too big to show here.

internal/db/sql/sessions.sql+27−2

This diff is too big to show here.

internal/db/sql/stats.sql+93

This diff is too big to show here.

internal/db/stats.sql.go+367

This diff is too big to show here.

internal/diffdetect/detect.go+36

This diff is too big to show here.

internal/diffdetect/detect_test.go+152

This diff is too big to show here.

internal/discover/discover.go+145

This diff is too big to show here.

internal/discover/discover_test.go+221

This diff is too big to show here.

internal/discover/enricher.go+60

This diff is too big to show here.

internal/discover/litellm.go+87

This diff is too big to show here.

internal/discover/litellm_test.go+173

This diff is too big to show here.

internal/discover/llamacpp.go+83

This diff is too big to show here.

internal/discover/llamacpp_test.go+135

This diff is too big to show here.

internal/discover/lmstudio.go+95

This diff is too big to show here.

internal/discover/lmstudio_test.go+154

This diff is too big to show here.

internal/discover/ollama.go+105

This diff is too big to show here.

internal/discover/ollama_test.go+131

This diff is too big to show here.

internal/discover/omlx.go+73

This diff is too big to show here.

internal/discover/omlx_test.go+92

This diff is too big to show here.

internal/dns/android.go+41

This diff is too big to show here.

internal/env/env.go+4−9

This diff is too big to show here.

internal/env/env_test.go+6−4

This diff is too big to show here.

internal/event/all.go+24

This diff is too big to show here.

internal/event/event.go+75−20

This diff is too big to show here.

internal/event/event_test.go+105

This diff is too big to show here.

internal/filepathext/filepath.go+52

This diff is too big to show here.

internal/filepathext/filepath_test.go+37

This diff is too big to show here.

internal/filetracker/service.go+110

This diff is too big to show here.

internal/filetracker/service_test.go+116

This diff is too big to show here.

internal/format/spinner.go+13−25

This diff is too big to show here.

internal/fsext/drive_other.go+16

This diff is too big to show here.

internal/fsext/drive_windows.go+26

This diff is too big to show here.

internal/fsext/fileutil.go+77−35

This diff is too big to show here.

internal/fsext/fileutil_dirtrim_test.go+32

This diff is too big to show here.

internal/fsext/fileutil_test.go+13−13

This diff is too big to show here.

internal/fsext/ignore_test.go+3−3

This diff is too big to show here.

internal/fsext/lookup.go+142−7

This diff is too big to show here.

internal/fsext/lookup_test.go+125

This diff is too big to show here.

internal/fsext/ls.go+187−124

This diff is too big to show here.

internal/fsext/ls_test.go+3−2

This diff is too big to show here.

internal/fsext/owner_others.go+8−5

This diff is too big to show here.

internal/fsext/owner_windows.go+7

This diff is too big to show here.

internal/fsext/paste.go+129

This diff is too big to show here.

internal/fsext/paste_test.go+149

This diff is too big to show here.

internal/herdr/client.go+405

This diff is too big to show here.

internal/herdr/client_test.go+158

This diff is too big to show here.

internal/herdr/translate.go+150

This diff is too big to show here.

internal/herdr/translate_test.go+145

This diff is too big to show here.

internal/history/file.go+28−16

This diff is too big to show here.

internal/home/home.go+24−20

This diff is too big to show here.

internal/hooks/hooks.go+193

This diff is too big to show here.

internal/hooks/hooks_test.go+757

This diff is too big to show here.

internal/hooks/input.go+211

This diff is too big to show here.

internal/hooks/runner.go+265

This diff is too big to show here.

internal/lock/lock.go+75

This diff is too big to show here.

internal/lock/lock_test.go+168

This diff is too big to show here.

internal/lock/lock_unix.go+45

This diff is too big to show here.

internal/lock/lock_windows.go+57

This diff is too big to show here.

internal/log/http.go+5−2

This diff is too big to show here.

internal/log/log.go+20−4

This diff is too big to show here.

internal/lsp/client.go+357−153

This diff is too big to show here.

internal/lsp/client_test.go+149−2

This diff is too big to show here.

internal/lsp/handlers.go+21−24

This diff is too big to show here.

internal/lsp/language.go−132

This diff is too big to show here.

internal/lsp/manager.go+412

This diff is too big to show here.

internal/lsp/manager_test.go+35

This diff is too big to show here.

internal/lsp/rootmarkers_test.go−37

This diff is too big to show here.

internal/lsp/util/edit.go+94−46

This diff is too big to show here.

internal/lsp/util/edit_test.go+376

This diff is too big to show here.

internal/message/attachment.go+16

This diff is too big to show here.

internal/message/content.go+183−33

This diff is too big to show here.

internal/message/content_test.go+142

This diff is too big to show here.

internal/message/message.go+468−65

This diff is too big to show here.

internal/message/message_test.go+695

This diff is too big to show here.

internal/oauth/copilot/client.go+94

This diff is too big to show here.

internal/oauth/copilot/client_test.go+70

This diff is too big to show here.

internal/oauth/copilot/disk.go+36

This diff is too big to show here.

internal/oauth/copilot/http.go+17

This diff is too big to show here.

internal/oauth/copilot/oauth.go+200

This diff is too big to show here.

internal/oauth/copilot/urls.go+6

This diff is too big to show here.

internal/oauth/hyper/device.go+251

This diff is too big to show here.

internal/oauth/token.go+57

This diff is too big to show here.

internal/permission/permission.go+176−92

This diff is too big to show here.

internal/permission/permission_test.go+377−9

This diff is too big to show here.

internal/projects/projects.go+126

This diff is too big to show here.

internal/projects/projects_test.go+186

This diff is too big to show here.

internal/proto/agent.go+82

This diff is too big to show here.

internal/proto/history.go+12

This diff is too big to show here.

internal/proto/mcp.go+172

This diff is too big to show here.

internal/proto/message.go+714

This diff is too big to show here.

internal/proto/permission.go+147

This diff is too big to show here.

internal/proto/permission_test.go+186

This diff is too big to show here.

internal/proto/proto.go+309

This diff is too big to show here.

internal/proto/requests.go+137

This diff is too big to show here.

internal/proto/requests_test.go+106

This diff is too big to show here.

internal/proto/server.go+6

This diff is too big to show here.

internal/proto/session.go+37

This diff is too big to show here.

internal/proto/skills.go+28

This diff is too big to show here.

internal/proto/tools.go+234

This diff is too big to show here.

internal/proto/version.go+10

This diff is too big to show here.

internal/pubsub/broker.go+189−29

This diff is too big to show here.

internal/pubsub/broker_test.go+117

This diff is too big to show here.

internal/pubsub/events.go+42−6

This diff is too big to show here.

internal/server/agent_cancel_test.go+227

This diff is too big to show here.

internal/server/config.go+525

This diff is too big to show here.

internal/server/e2e_agent_test.go+742

This diff is too big to show here.

internal/server/e2e_test.go+612

This diff is too big to show here.

internal/server/events.go+311

This diff is too big to show here.

internal/server/events_test.go+182

This diff is too big to show here.

internal/server/logging.go+53

This diff is too big to show here.

internal/server/multiclient_test.go+230

This diff is too big to show here.

internal/server/net_other.go+61

This diff is too big to show here.

internal/server/net_windows.go+37

This diff is too big to show here.

internal/server/proto.go+1129

This diff is too big to show here.

internal/server/recover.go+59

This diff is too big to show here.

internal/server/recover_test.go+94

This diff is too big to show here.

internal/server/server.go+286

This diff is too big to show here.

internal/server/sessions_isbusy_test.go+334

This diff is too big to show here.

internal/server/socket.go+10

This diff is too big to show here.

internal/server/socket_classify.go+27

This diff is too big to show here.

internal/server/socket_test.go+193

This diff is too big to show here.

internal/session/session.go+187−10

This diff is too big to show here.

internal/session/session_test.go+81

This diff is too big to show here.

internal/shell/background.go+245

This diff is too big to show here.

internal/shell/background_test.go+330

This diff is too big to show here.

internal/shell/coreutils.go+19

This diff is too big to show here.

internal/shell/dispatch.go+425

This diff is too big to show here.

internal/shell/dispatch_test.go+594

This diff is too big to show here.

internal/shell/dispatch_windows_test.go+40

This diff is too big to show here.

internal/shell/doc.go+1−6

This diff is too big to show here.

internal/shell/exec_unix.go+108

This diff is too big to show here.

internal/shell/exec_windows.go+23

This diff is too big to show here.

internal/shell/expand.go+162

This diff is too big to show here.

internal/shell/expand_test.go+241

This diff is too big to show here.

internal/shell/isolation_unix_test.go+143

This diff is too big to show here.

internal/shell/jq.go+342

This diff is too big to show here.

internal/shell/jq_test.go+212

This diff is too big to show here.

internal/shell/persist_message.go+44

This diff is too big to show here.

internal/shell/persist_message_test.go+69

This diff is too big to show here.

internal/shell/persistent.go−43

This diff is too big to show here.

internal/shell/run.go+345

This diff is too big to show here.

internal/shell/run_test.go+364

This diff is too big to show here.

internal/shell/shell.go+80−44

This diff is too big to show here.

internal/shell/stream.go+52

This diff is too big to show here.

internal/skills/builtin/crush-config/SKILL.md+370

This diff is too big to show here.

internal/skills/builtin/crush-hooks/SKILL.md+209

This diff is too big to show here.

internal/skills/builtin/jq/SKILL.md+97

This diff is too big to show here.

internal/skills/catalog.go+154

This diff is too big to show here.

internal/skills/diagnostics_test.go+104

This diff is too big to show here.

internal/skills/embed.go+79

This diff is too big to show here.

internal/skills/manager.go+227

This diff is too big to show here.

internal/skills/manager_test.go+249

This diff is too big to show here.

internal/skills/skills.go+437

This diff is too big to show here.

internal/skills/skills_test.go+520

This diff is too big to show here.

internal/skills/tracker.go+86

This diff is too big to show here.

internal/skills/tracker_test.go+102

This diff is too big to show here.

internal/stringext/string.go+40

This diff is too big to show here.

internal/stringext/string_test.go+38

This diff is too big to show here.

internal/swagger/docs.go+3717

This diff is too big to show here.

internal/swagger/swagger.json+3692

This diff is too big to show here.

internal/swagger/swagger.yaml+2457

This diff is too big to show here.

internal/tui/components/anim/anim.go−446

This diff is too big to show here.

internal/tui/components/chat/chat.go−807

This diff is too big to show here.

internal/tui/components/chat/editor/editor.go−590

This diff is too big to show here.

internal/tui/components/chat/editor/keys.go−71

This diff is too big to show here.

internal/tui/components/chat/header/header.go−167

This diff is too big to show here.

internal/tui/components/chat/messages/messages.go−430

This diff is too big to show here.

internal/tui/components/chat/messages/renderer.go−892

This diff is too big to show here.

internal/tui/components/chat/messages/tool.go−812

This diff is too big to show here.

internal/tui/components/chat/queue.go−28

This diff is too big to show here.

internal/tui/components/chat/sidebar/sidebar.go−613

This diff is too big to show here.

internal/tui/components/chat/splash/keys.go−53

This diff is too big to show here.

internal/tui/components/chat/splash/splash.go−723

This diff is too big to show here.

internal/tui/components/completions/completions.go−308

This diff is too big to show here.

internal/tui/components/completions/keys.go−72

This diff is too big to show here.

internal/tui/components/core/core.go−207

This diff is too big to show here.

internal/tui/components/core/layout/layout.go−27

This diff is too big to show here.

internal/tui/components/core/status/status.go−109

This diff is too big to show here.

internal/tui/components/core/status_test.go−144

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/AllFieldsWithExtraContent.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/Default.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/EmptyDescription.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/LongDescription.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/NarrowWidth.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/NoIcon.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/VeryNarrowWidth.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/WithColors.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/WithCustomIcon.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatus/WithExtraContent.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatusTruncation/Width20.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatusTruncation/Width30.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatusTruncation/Width40.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatusTruncation/Width50.golden−1

This diff is too big to show here.

internal/tui/components/core/testdata/TestStatusTruncation/Width60.golden−1

This diff is too big to show here.

internal/tui/components/dialogs/commands/arguments.go−230

This diff is too big to show here.

internal/tui/components/dialogs/commands/commands.go−423

This diff is too big to show here.

internal/tui/components/dialogs/commands/keys.go−133

This diff is too big to show here.

internal/tui/components/dialogs/commands/loader.go−203

This diff is too big to show here.

internal/tui/components/dialogs/dialogs.go−161

This diff is too big to show here.

internal/tui/components/dialogs/filepicker/filepicker.go−260

This diff is too big to show here.

internal/tui/components/dialogs/filepicker/keys.go−80

This diff is too big to show here.

internal/tui/components/dialogs/keys.go−43

This diff is too big to show here.

internal/tui/components/dialogs/models/apikey.go−202

This diff is too big to show here.

internal/tui/components/dialogs/models/keys.go−85

This diff is too big to show here.

internal/tui/components/dialogs/models/list.go−254

This diff is too big to show here.

internal/tui/components/dialogs/models/models.go−393

This diff is too big to show here.

internal/tui/components/dialogs/permissions/keys.go−113

This diff is too big to show here.

internal/tui/components/dialogs/permissions/permissions.go−846

This diff is too big to show here.

internal/tui/components/dialogs/quit/keys.go−75

This diff is too big to show here.

internal/tui/components/dialogs/quit/quit.go−120

This diff is too big to show here.

internal/tui/components/dialogs/reasoning/reasoning.go−264

This diff is too big to show here.

internal/tui/components/dialogs/sessions/keys.go−67

This diff is too big to show here.

internal/tui/components/dialogs/sessions/sessions.go−181

This diff is too big to show here.

internal/tui/components/files/files.go−146

This diff is too big to show here.

internal/tui/components/image/image.go−86

This diff is too big to show here.

internal/tui/components/image/load.go−146

This diff is too big to show here.

internal/tui/components/logo/logo.go−347

This diff is too big to show here.

internal/tui/components/lsp/lsp.go−161

This diff is too big to show here.

internal/tui/components/mcp/mcp.go−126

This diff is too big to show here.

internal/tui/exp/diffview/chroma.go−57

This diff is too big to show here.

internal/tui/exp/diffview/style.go−124

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/CustomContextLines/DarkMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/CustomContextLines/LightMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/Default/DarkMode.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/Default/LightMode.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/LargeWidth/DarkMode.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/LargeWidth/LightMode.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/MultipleHunks/DarkMode.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/MultipleHunks/LightMode.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/Narrow/DarkMode.golden−4

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/Narrow/LightMode.golden−4

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/NoLineNumbers/DarkMode.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/NoLineNumbers/LightMode.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/DarkMode.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/LightMode.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/SmallWidth/DarkMode.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Split/SmallWidth/LightMode.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/CustomContextLines/DarkMode.golden−17

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/CustomContextLines/LightMode.golden−17

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/Default/DarkMode.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/Default/LightMode.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/LargeWidth/DarkMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/LargeWidth/LightMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/MultipleHunks/DarkMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/MultipleHunks/LightMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/Narrow/DarkMode.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/Narrow/LightMode.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/NoLineNumbers/DarkMode.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/NoLineNumbers/LightMode.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/DarkMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/LightMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/SmallWidth/DarkMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffView/Unified/SmallWidth/LightMode.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf002.golden−2

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf003.golden−3

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf004.golden−4

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf005.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf006.golden−6

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf007.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf008.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf009.golden−9

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf010.golden−10

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf011.golden−11

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf012.golden−12

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf013.golden−13

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf014.golden−14

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf015.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf016.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf017.golden−17

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf018.golden−18

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf019.golden−19

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf020.golden−20

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf002.golden−2

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf003.golden−3

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf004.golden−4

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf005.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf006.golden−6

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf007.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf008.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf009.golden−9

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf010.golden−10

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf011.golden−11

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf012.golden−12

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf013.golden−13

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf014.golden−14

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf015.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf016.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf017.golden−17

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf018.golden−18

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf019.golden−19

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf020.golden−20

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewLineBreakIssue/Split.golden−9

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewLineBreakIssue/Unified.golden−12

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewTabs/Split.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewTabs/Unified.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf001.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf002.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf003.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf004.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf005.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf006.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf007.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf008.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf009.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf010.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf011.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf012.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf013.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf014.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf015.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf016.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf017.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf018.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf019.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf020.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf021.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf022.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf023.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf024.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf025.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf026.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf027.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf028.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf029.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf030.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf031.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf032.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf033.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf034.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf035.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf036.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf037.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf038.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf039.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf040.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf041.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf042.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf043.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf044.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf045.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf046.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf047.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf048.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf049.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf050.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf051.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf052.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf053.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf054.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf055.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf056.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf057.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf058.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf059.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf060.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf061.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf062.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf063.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf064.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf065.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf066.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf067.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf068.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf069.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf070.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf071.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf072.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf073.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf074.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf075.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf076.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf077.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf078.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf079.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf080.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf081.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf082.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf083.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf084.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf085.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf086.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf087.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf088.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf089.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf090.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf091.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf092.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf093.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf094.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf095.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf096.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf097.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf098.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf099.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf100.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf101.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf102.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf103.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf104.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf105.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf106.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf107.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf108.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf109.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf110.golden−15

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf001.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf002.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf003.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf004.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf005.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf006.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf007.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf008.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf009.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf010.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf011.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf012.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf013.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf014.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf015.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf016.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf017.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf018.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf019.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf020.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf021.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf022.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf023.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf024.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf025.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf026.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf027.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf028.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf029.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf030.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf031.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf032.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf033.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf034.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf035.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf036.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf037.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf038.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf039.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf040.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf041.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf042.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf043.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf044.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf045.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf046.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf047.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf048.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf049.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf050.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf051.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf052.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf053.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf054.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf055.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf056.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf057.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf058.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf059.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf060.golden−16

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf00.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf01.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf02.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf03.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf04.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf05.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf06.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf07.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf08.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf09.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf10.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf11.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf12.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf13.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf14.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf15.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf16.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf17.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf18.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf19.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf20.golden−7

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf00.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf01.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf02.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf03.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf04.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf05.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf06.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf07.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf08.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf09.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf10.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf11.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf12.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf13.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf14.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf15.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf16.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf17.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf18.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf19.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf20.golden−8

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf00.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf01.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf02.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf03.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf04.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf05.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf06.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf07.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf08.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf09.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf10.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf11.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf12.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf13.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf14.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf15.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf16.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf00.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf01.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf02.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf03.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf04.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf05.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf06.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf07.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf08.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf09.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf10.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf11.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf12.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf13.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf14.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf15.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf16.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf00.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf01.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf02.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf03.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf04.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf05.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf06.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf07.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf08.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf09.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf10.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf11.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf12.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf13.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf14.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf15.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf16.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf00.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf01.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf02.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf03.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf04.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf05.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf06.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf07.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf08.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf09.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf10.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf11.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf12.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf13.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf14.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf15.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf16.golden−5

This diff is too big to show here.

internal/tui/exp/diffview/util.go−39

This diff is too big to show here.

internal/tui/exp/list/filterable.go−318

This diff is too big to show here.

internal/tui/exp/list/filterable_group.go−315

This diff is too big to show here.

internal/tui/exp/list/filterable_test.go−68

This diff is too big to show here.

internal/tui/exp/list/grouped.go−103

This diff is too big to show here.

internal/tui/exp/list/items.go−392

This diff is too big to show here.

internal/tui/exp/list/keys.go−76

This diff is too big to show here.

internal/tui/exp/list/list.go−1472

This diff is too big to show here.

internal/tui/exp/list/list_test.go−652

This diff is too big to show here.

internal/tui/exp/list/testdata/TestFilterableList/should_create_simple_filterable_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestList/should_go_to_selected_item_at_the_beginning.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestList/should_go_to_selected_item_at_the_beginning_backwards.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_does_not_fits_the_items.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_does_not_fits_the_items_and_has_multi_line_items.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_does_not_fits_the_items_and_has_multi_line_items_backwards.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_does_not_fits_the_items_backwards.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_fits_the_items.golden−20

This diff is too big to show here.

internal/tui/exp/list/testdata/TestList/should_have_correct_positions_in_list_that_fits_the_items_backwards.golden−20

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_move_viewport_down.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_move_viewport_down_and_up.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_move_viewport_up.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_move_viewport_up_and_down.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_not_change_offset_when_new_items_are_appended_and_we_are_at_the_bottom_in_backwards_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_not_change_offset_when_new_items_are_prepended_and_we_are_at_the_top_in_forward_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_if_an_item_is_appended_and_we_are_in_forward_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_if_an_item_is_prepended_and_we_are_in_backwards_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_new_items_are_added_but_we_moved_down_in_forward_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_new_items_are_added_but_we_moved_up_in_backwards_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_above_is_decreases_in_forward_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_above_is_increased_in_backwards_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_above_is_increased_in_forward_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_below_is_decreases_in_backwards_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_below_is_increased_in_backwards_list.golden−10

This diff is too big to show here.

internal/tui/exp/list/testdata/TestListMovement/should_stay_at_the_position_it_is_when_the_hight_of_an_item_below_is_increased_in_forward_list.golden−10

This diff is too big to show here.

internal/tui/highlight/highlight.go−54

This diff is too big to show here.

internal/tui/keys.go−40

This diff is too big to show here.

internal/tui/page/chat/chat.go−1116

This diff is too big to show here.

internal/tui/page/chat/keys.go−38

This diff is too big to show here.

internal/tui/page/page.go−8

This diff is too big to show here.

internal/tui/styles/charmtone.go−75

This diff is too big to show here.

internal/tui/styles/chroma.go−79

This diff is too big to show here.

internal/tui/styles/icons.go−41

This diff is too big to show here.

internal/tui/styles/markdown.go−20

This diff is too big to show here.

internal/tui/styles/theme.go−696

This diff is too big to show here.

internal/tui/tui.go−606

This diff is too big to show here.

internal/tui/util/util.go−62

This diff is too big to show here.

internal/ui/AGENTS.md+200

This diff is too big to show here.

internal/ui/anim/anim.go+494

This diff is too big to show here.

internal/ui/attachments/attachments.go+152

This diff is too big to show here.

internal/ui/chat/agent.go+393

This diff is too big to show here.

internal/ui/chat/applyhighlight_callback_test.go+207

This diff is too big to show here.

internal/ui/chat/assistant.go+904

This diff is too big to show here.

internal/ui/chat/assistant_render_test.go+78

This diff is too big to show here.

internal/ui/chat/assistant_section_cache_test.go+464

This diff is too big to show here.

internal/ui/chat/assistant_test.go+142

This diff is too big to show here.

internal/ui/chat/assistant_thinking_bench_test.go+69

This diff is too big to show here.

internal/ui/chat/assistant_thinking_bound_test.go+105

This diff is too big to show here.

internal/ui/chat/assistant_thinking_window_test.go+500

This diff is too big to show here.

internal/ui/chat/bash.go+251

This diff is too big to show here.

internal/ui/chat/diagnostics.go+68

This diff is too big to show here.

internal/ui/chat/docker_mcp.go+283

This diff is too big to show here.

internal/ui/chat/fetch.go+192

This diff is too big to show here.

internal/ui/chat/file.go+371

This diff is too big to show here.

internal/ui/chat/generic.go+73

This diff is too big to show here.

internal/ui/chat/incremental_glamour_test.go+981

This diff is too big to show here.

internal/ui/chat/lsp_restart.go+62

This diff is too big to show here.

internal/ui/chat/mcp.go+78

This diff is too big to show here.

internal/ui/chat/mcp_test.go+406

This diff is too big to show here.

internal/ui/chat/messages.go+440

This diff is too big to show here.

internal/ui/chat/prefix_cache_test.go+197

This diff is too big to show here.

internal/ui/chat/references.go+63

This diff is too big to show here.

internal/ui/chat/search.go+256

This diff is too big to show here.

internal/ui/chat/shell.go+358

This diff is too big to show here.

internal/ui/chat/shell_test.go+59

This diff is too big to show here.

internal/ui/chat/streaming_markdown.go+721

This diff is too big to show here.

internal/ui/chat/todos.go+192

This diff is too big to show here.

internal/ui/chat/tool_result_content.go+60

This diff is too big to show here.

internal/ui/chat/tool_result_content_test.go+116

This diff is too big to show here.

internal/ui/chat/tools.go+1751

This diff is too big to show here.

internal/ui/chat/unified_diff.go+170

This diff is too big to show here.

internal/ui/chat/user.go+181

This diff is too big to show here.

internal/ui/chat/version_bump_test.go+567

This diff is too big to show here.

internal/ui/common/ansi16.go+128

This diff is too big to show here.

internal/ui/common/ansi16_test.go+106

This diff is too big to show here.

internal/ui/common/button.go+69

This diff is too big to show here.

internal/ui/common/capabilities.go+131

This diff is too big to show here.

internal/ui/common/common.go+121

This diff is too big to show here.

internal/ui/common/diff.go+35

This diff is too big to show here.

internal/ui/common/elements.go+242

This diff is too big to show here.

internal/ui/common/elements_test.go+35

This diff is too big to show here.

internal/ui/common/highlight.go+106

This diff is too big to show here.

internal/ui/common/interface.go+20

This diff is too big to show here.

internal/ui/common/markdown.go+139

This diff is too big to show here.

internal/ui/common/scrollbar.go+48

This diff is too big to show here.

internal/ui/completions/completions.go+434

This diff is too big to show here.

internal/ui/completions/completions_test.go+108

This diff is too big to show here.

internal/ui/completions/item.go+225

This diff is too big to show here.

internal/ui/completions/keys.go+74

This diff is too big to show here.

internal/ui/completions/version_bump_test.go+85

This diff is too big to show here.

internal/ui/dialog/actions.go+187

This diff is too big to show here.

internal/ui/dialog/api_key_input.go+367

This diff is too big to show here.

internal/ui/dialog/arguments.go+406

This diff is too big to show here.

internal/ui/dialog/commands.go+453

This diff is too big to show here.

internal/ui/dialog/commands_item.go+136

This diff is too big to show here.

internal/ui/dialog/common.go+171

This diff is too big to show here.

internal/ui/dialog/dialog.go+296

This diff is too big to show here.

internal/ui/dialog/filepicker.go+321

This diff is too big to show here.

internal/ui/dialog/models.go+519

This diff is too big to show here.

internal/ui/dialog/models_item.go+157

This diff is too big to show here.

internal/ui/dialog/models_list.go+275

This diff is too big to show here.

internal/ui/dialog/notifications.go+310

This diff is too big to show here.

internal/ui/dialog/oauth.go+378

This diff is too big to show here.

internal/ui/dialog/oauth_copilot.go+78

This diff is too big to show here.

internal/ui/dialog/oauth_hyper.go+96

This diff is too big to show here.

internal/ui/dialog/overlay_test.go+189

This diff is too big to show here.

internal/ui/dialog/permissions.go+859

This diff is too big to show here.

internal/ui/dialog/permissions_test.go+99

This diff is too big to show here.

internal/ui/dialog/quit.go+133

This diff is too big to show here.

internal/ui/dialog/reasoning.go+318

This diff is too big to show here.

internal/ui/dialog/sessions.go+473

This diff is too big to show here.

internal/ui/dialog/sessions_item.go+294

This diff is too big to show here.

internal/ui/dialog/version_bump_test.go+219

This diff is too big to show here.

internal/ui/difftastic/difftastic.go+60

This diff is too big to show here.

internal/ui/diffview/Taskfile.yaml

This diff is too big to show here.

internal/ui/diffview/diffview.go+56−36

This diff is too big to show here.

internal/ui/diffview/diffview_test.go+1−25

This diff is too big to show here.

internal/ui/diffview/split.go

This diff is too big to show here.

internal/ui/diffview/style.go+143

This diff is too big to show here.

internal/ui/diffview/testdata/TestDefault.after

This diff is too big to show here.

internal/ui/diffview/testdata/TestDefault.before

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/CustomContextLines/DarkMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/CustomContextLines/LightMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/Default/DarkMode.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/Default/LightMode.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/LargeWidth/DarkMode.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/LargeWidth/LightMode.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/MultipleHunks/DarkMode.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/MultipleHunks/LightMode.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/Narrow/DarkMode.golden+4

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/Narrow/LightMode.golden+4

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/NoLineNumbers/DarkMode.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/NoLineNumbers/LightMode.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/DarkMode.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/LightMode.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/SmallWidth/DarkMode.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Split/SmallWidth/LightMode.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/CustomContextLines/DarkMode.golden+17

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/CustomContextLines/LightMode.golden+17

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/Default/DarkMode.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/Default/LightMode.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/LargeWidth/DarkMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/LargeWidth/LightMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/MultipleHunks/DarkMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/MultipleHunks/LightMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/Narrow/DarkMode.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/Narrow/LightMode.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/NoLineNumbers/DarkMode.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/NoLineNumbers/LightMode.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/DarkMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/LightMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/SmallWidth/DarkMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffView/Unified/SmallWidth/LightMode.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf001.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf002.golden+2

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf003.golden+3

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf004.golden+4

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf005.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf006.golden+6

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf007.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf008.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf009.golden+9

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf010.golden+10

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf011.golden+11

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf012.golden+12

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf013.golden+13

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf014.golden+14

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf015.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf016.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf017.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf018.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf019.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Split/HeightOf020.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf001.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf002.golden+2

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf003.golden+3

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf004.golden+4

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf005.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf006.golden+6

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf007.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf008.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf009.golden+9

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf010.golden+10

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf011.golden+11

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf012.golden+12

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf013.golden+13

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf014.golden+14

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf015.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf016.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf017.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf018.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf019.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewHeight/Unified/HeightOf020.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewLineBreakIssue/Split.golden+9

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewLineBreakIssue/Unified.golden+12

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewTabs/Split.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewTabs/Unified.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf001.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf002.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf003.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf004.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf005.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf006.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf007.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf008.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf009.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf010.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf011.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf012.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf013.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf014.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf015.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf016.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf017.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf018.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf019.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf020.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf021.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf022.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf023.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf024.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf025.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf026.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf027.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf028.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf029.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf030.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf031.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf032.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf033.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf034.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf035.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf036.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf037.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf038.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf039.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf040.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf041.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf042.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf043.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf044.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf045.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf046.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf047.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf048.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf049.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf050.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf051.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf052.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf053.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf054.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf055.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf056.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf057.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf058.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf059.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf060.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf061.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf062.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf063.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf064.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf065.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf066.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf067.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf068.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf069.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf070.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf071.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf072.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf073.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf074.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf075.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf076.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf077.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf078.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf079.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf080.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf081.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf082.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf083.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf084.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf085.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf086.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf087.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf088.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf089.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf090.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf091.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf092.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf093.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf094.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf095.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf096.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf097.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf098.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf099.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf100.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf101.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf102.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf103.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf104.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf105.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf106.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf107.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf108.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf109.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Split/WidthOf110.golden+15

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf001.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf002.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf003.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf004.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf005.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf006.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf007.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf008.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf009.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf010.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf011.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf012.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf013.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf014.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf015.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf016.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf017.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf018.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf019.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf020.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf021.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf022.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf023.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf024.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf025.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf026.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf027.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf028.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf029.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf030.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf031.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf032.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf033.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf034.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf035.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf036.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf037.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf038.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf039.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf040.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf041.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf042.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf043.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf044.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf045.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf046.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf047.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf048.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf049.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf050.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf051.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf052.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf053.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf054.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf055.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf056.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf057.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf058.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf059.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewWidth/Unified/WidthOf060.golden+16

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf00.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf01.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf02.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf03.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf04.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf05.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf06.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf07.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf08.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf09.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf10.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf11.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf12.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf13.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf14.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf15.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf16.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf17.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf18.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf19.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf20.golden+7

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf00.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf01.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf02.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf03.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf04.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf05.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf06.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf07.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf08.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf09.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf10.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf11.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf12.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf13.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf14.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf15.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf16.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf17.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf18.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf19.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf20.golden+8

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf00.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf01.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf02.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf03.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf04.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf05.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf06.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf07.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf08.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf09.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf10.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf11.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf12.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf13.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf14.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf15.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf16.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf00.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf01.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf02.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf03.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf04.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf05.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf06.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf07.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf08.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf09.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf10.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf11.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf12.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf13.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf14.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf15.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf16.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf00.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf01.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf02.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf03.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf04.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf05.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf06.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf07.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf08.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf09.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf10.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf11.golden+4

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf12.golden+3

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf13.golden+2

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf14.golden+1

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf15.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Split/YOffsetOf16.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf00.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf01.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf02.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf03.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf04.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf05.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf06.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf07.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf08.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf09.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf10.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf11.golden+5

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf12.golden+4

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf13.golden+3

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf14.golden+2

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf15.golden+1

This diff is too big to show here.

internal/ui/diffview/testdata/TestDiffViewYOffsetInfinite/Unified/YOffsetOf16.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestLineBreakIssue.after

This diff is too big to show here.

internal/ui/diffview/testdata/TestLineBreakIssue.before

This diff is too big to show here.

internal/ui/diffview/testdata/TestMultipleHunks.after

This diff is too big to show here.

internal/ui/diffview/testdata/TestMultipleHunks.before

This diff is too big to show here.

internal/ui/diffview/testdata/TestNarrow.after

This diff is too big to show here.

internal/ui/diffview/testdata/TestNarrow.before

This diff is too big to show here.

internal/ui/diffview/testdata/TestTabs.after

This diff is too big to show here.

internal/ui/diffview/testdata/TestTabs.before

This diff is too big to show here.

internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLines/Content.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLines/JSON.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusOne/Content.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusOne/JSON.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusTwo/Content.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusTwo/JSON.golden

This diff is too big to show here.

internal/ui/diffview/testdata/TestUdiff/Unified.golden

This diff is too big to show here.

internal/ui/diffview/udiff_test.go+1−1

This diff is too big to show here.

internal/ui/diffview/util.go+46

This diff is too big to show here.

internal/ui/diffview/util_test.go

This diff is too big to show here.

internal/ui/image/image.go+288

This diff is too big to show here.

internal/ui/image/image_test.go+46

This diff is too big to show here.

internal/ui/list/filterable.go+157

This diff is too big to show here.

internal/ui/list/focus.go+13

This diff is too big to show here.

internal/ui/list/highlight.go+212

This diff is too big to show here.

internal/ui/list/item.go+126

This diff is too big to show here.

internal/ui/list/list.go+928

This diff is too big to show here.

internal/ui/list/list_test.go+770

This diff is too big to show here.

internal/ui/logo/example/main.go+49

This diff is too big to show here.

internal/ui/logo/letterforms.go+419

This diff is too big to show here.

internal/ui/logo/logo.go+168

This diff is too big to show here.

internal/ui/logo/rand.go+24

This diff is too big to show here.

internal/ui/model/chat.go+1166

This diff is too big to show here.

internal/ui/model/chat_draw_cache_test.go+334

This diff is too big to show here.

internal/ui/model/chat_expand_test.go+55

This diff is too big to show here.

internal/ui/model/filter.go+108

This diff is too big to show here.

internal/ui/model/filter_test.go+162

This diff is too big to show here.

internal/ui/model/header.go+264

This diff is too big to show here.

internal/ui/model/history.go+200

This diff is too big to show here.

internal/ui/model/keys.go+285

This diff is too big to show here.

internal/ui/model/landing.go+126

This diff is too big to show here.

internal/ui/model/layout_test.go+228

This diff is too big to show here.

internal/ui/model/lsp.go+147

This diff is too big to show here.

internal/ui/model/mcp.go+114

This diff is too big to show here.

internal/ui/model/onboarding.go+116

This diff is too big to show here.

internal/ui/model/permission_test.go+96

This diff is too big to show here.

internal/ui/model/pills.go+363

This diff is too big to show here.

internal/ui/model/session.go+272

This diff is too big to show here.

internal/ui/model/session_test.go+142

This diff is too big to show here.

internal/ui/model/sidebar.go+369

This diff is too big to show here.

internal/ui/model/skills.go+155

This diff is too big to show here.

internal/ui/model/skills_test.go+81

This diff is too big to show here.

internal/ui/model/status.go+123

This diff is too big to show here.

internal/ui/model/ui.go+4564

This diff is too big to show here.

internal/ui/model/ui_test.go+95

This diff is too big to show here.

internal/ui/notification/bell.go+27

This diff is too big to show here.

internal/ui/notification/crush-icon-solo.png

This diff is too big to show here.

internal/ui/notification/crush-icon.png

This diff is too big to show here.

internal/ui/notification/icon_darwin.go+11

This diff is too big to show here.

internal/ui/notification/icon_other.go+10

This diff is too big to show here.

internal/ui/notification/native.go+52

This diff is too big to show here.

internal/ui/notification/noop.go+12

This diff is too big to show here.

internal/ui/notification/notification.go+35

This diff is too big to show here.

internal/ui/notification/notification_test.go+213

This diff is too big to show here.

internal/ui/notification/osc.go+135

This diff is too big to show here.

internal/ui/styles/grad.go+119

This diff is too big to show here.

internal/ui/styles/quickstyle.go+989

This diff is too big to show here.

internal/ui/styles/styles.go+649

This diff is too big to show here.

internal/ui/styles/themes.go+235

This diff is too big to show here.

internal/ui/util/util.go+96

This diff is too big to show here.

internal/ui/xchroma/chroma.go+70

This diff is too big to show here.

internal/update/update.go+118

This diff is too big to show here.

internal/update/update_test.go+48

This diff is too big to show here.

internal/version/version.go+39−12

This diff is too big to show here.

internal/workspace/app_workspace.go+464

This diff is too big to show here.

internal/workspace/client_workspace.go+964

This diff is too big to show here.

internal/workspace/client_workspace_test.go+213

This diff is too big to show here.

internal/workspace/export_test.go+14

This diff is too big to show here.

internal/workspace/multiclient_integration_test.go+176

This diff is too big to show here.

internal/workspace/workspace.go+171

This diff is too big to show here.

main.go+11

This diff is too big to show here.

schema.json+332−29

This diff is too big to show here.

scripts/check_log_capitalization.sh+5

This diff is too big to show here.

vendor/charm.land/bubbles/v2/LICENSE+21

This diff is too big to show here.

vendor/charm.land/bubbles/v2/cursor/cursor.go+241

This diff is too big to show here.

vendor/charm.land/bubbles/v2/filepicker/filepicker.go+529

This diff is too big to show here.

vendor/charm.land/bubbles/v2/filepicker/hidden_unix.go+11

This diff is too big to show here.

vendor/charm.land/bubbles/v2/filepicker/hidden_windows.go+21

This diff is too big to show here.

vendor/charm.land/bubbles/v2/help/help.go+253

This diff is too big to show here.

vendor/charm.land/bubbles/v2/internal/memoization/memoization.go+125

This diff is too big to show here.

vendor/charm.land/bubbles/v2/internal/runeutil/runeutil.go+102

This diff is too big to show here.

vendor/charm.land/bubbles/v2/key/key.go+140

This diff is too big to show here.

vendor/charm.land/bubbles/v2/spinner/spinner.go+211

This diff is too big to show here.

vendor/charm.land/bubbles/v2/textarea/textarea.go+1897

This diff is too big to show here.

vendor/charm.land/bubbles/v2/textinput/styles.go+96

This diff is too big to show here.

vendor/charm.land/bubbles/v2/textinput/textinput.go+968

This diff is too big to show here.

vendor/charm.land/bubbles/v2/viewport/highlight.go+141

This diff is too big to show here.

vendor/charm.land/bubbles/v2/viewport/keymap.go+58

This diff is too big to show here.

vendor/charm.land/bubbles/v2/viewport/viewport.go+765

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/.gitattributes+1

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/.gitignore+23

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/.golangci.yml+47

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/.goreleaser.yml+5

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/LICENSE+21

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/README.md+402

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/Taskfile.yaml+38

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/UPGRADE_GUIDE_V2.md+573

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/clipboard.go+70

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/color.go+91

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/commands.go+175

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/cursed_renderer.go+860

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/cursor.go+28

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/environ.go+34

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/exec.go+129

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/focus.go+9

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/input.go+54

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/key.go+371

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/keyboard.go+59

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/logging.go+53

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/mod.go+27

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/mouse.go+144

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/nil_renderer.go+53

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/options.go+168

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/paste.go+20

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/profile.go+15

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/raw.go+37

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/renderer.go+104

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/screen.go+68

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/signals_unix.go+33

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/signals_windows.go+10

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/tea.go+1439

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/termcap.go+48

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/termios_bsd.go+13

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/termios_other.go+8

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/termios_unix.go+14

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/termios_windows.go+11

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/tty.go+136

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/tty_unix.go+47

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/tty_windows.go+64

This diff is too big to show here.

vendor/charm.land/bubbletea/v2/xterm.go+22

This diff is too big to show here.

vendor/charm.land/catwalk/LICENSE+21

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/aihubmix.json+3746

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/alibaba-singapore.json+141

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/alibaba-united-states.json+45

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/anthropic.json+183

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/avian.json+125

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/azure.json+225

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/baseten.json+187

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/bedrock-europe.json+115

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/bedrock-united-states.json+143

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/cerebras.json+42

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/chutes.json+227

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/copilot.json+310

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/cortecs.json+1697

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/deepseek.json+45

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/fireworks.json+171

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/gemini.json+91

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/groq.json+36

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/huggingface.json+267

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/ionet.json+335

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/kimi.json+23

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/minimax-china.json+91

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/minimax.json+91

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/moonshot.json+131

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/nebius.json+419

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/neuralwatt.json+155

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/openai.json+352

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/opencode-go.json+351

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/opencode-zen.json+908

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/openrouter.json+3831

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/qiniucloud.json+179

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/scaleway.json+141

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/synthetic.json+197

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/venice.json+1173

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/vercel.json+3072

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/vertexai.json+170

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/xai.json+59

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/zai.json+136

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/zhipu-coding.json+136

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/configs/zhipu.json+120

This diff is too big to show here.

vendor/charm.land/catwalk/internal/providers/providers.go+349

This diff is too big to show here.

vendor/charm.land/catwalk/pkg/catwalk/client.go+79

This diff is too big to show here.

vendor/charm.land/catwalk/pkg/catwalk/pkg.go+2

This diff is too big to show here.

vendor/charm.land/catwalk/pkg/catwalk/provider.go+157

This diff is too big to show here.

vendor/charm.land/catwalk/pkg/embedded/embedded.go+13

This diff is too big to show here.

vendor/charm.land/fang/v2/.gitignore+3

This diff is too big to show here.

vendor/charm.land/fang/v2/.golangci.yml+47

This diff is too big to show here.

vendor/charm.land/fang/v2/.goreleaser.yml+5

This diff is too big to show here.

vendor/charm.land/fang/v2/LICENSE.md+21

This diff is too big to show here.

vendor/charm.land/fang/v2/README.md+92

This diff is too big to show here.

vendor/charm.land/fang/v2/Taskfile.yml+7

This diff is too big to show here.

vendor/charm.land/fang/v2/UPGRADE_GUIDE_V2.md+127

This diff is too big to show here.

vendor/charm.land/fang/v2/fang.go+208

This diff is too big to show here.

vendor/charm.land/fang/v2/fang_other.go+10

This diff is too big to show here.

vendor/charm.land/fang/v2/fang_windows.go+30

This diff is too big to show here.

vendor/charm.land/fang/v2/help.go+482

This diff is too big to show here.

vendor/charm.land/fang/v2/theme.go+222

This diff is too big to show here.

vendor/charm.land/fantasy/.editorconfig+18

This diff is too big to show here.

vendor/charm.land/fantasy/.gitattributes+1

This diff is too big to show here.

vendor/charm.land/fantasy/.gitignore+42

This diff is too big to show here.

vendor/charm.land/fantasy/.golangci.yml+44

This diff is too big to show here.

vendor/charm.land/fantasy/.goreleaser.yml+6

This diff is too big to show here.

vendor/charm.land/fantasy/AGENTS.md+29

This diff is too big to show here.

vendor/charm.land/fantasy/LICENSE+177

This diff is too big to show here.

vendor/charm.land/fantasy/NOTICE+13

This diff is too big to show here.

vendor/charm.land/fantasy/README.md+95

This diff is too big to show here.

vendor/charm.land/fantasy/Taskfile.yaml+45

This diff is too big to show here.

vendor/charm.land/fantasy/agent.go+1702

This diff is too big to show here.

vendor/charm.land/fantasy/content.go+625

This diff is too big to show here.

vendor/charm.land/fantasy/content_json.go+1046

This diff is too big to show here.

vendor/charm.land/fantasy/crush.json+6

This diff is too big to show here.

vendor/charm.land/fantasy/cspell.json+1

This diff is too big to show here.

vendor/charm.land/fantasy/doc.go+2

This diff is too big to show here.

vendor/charm.land/fantasy/errors.go+155

This diff is too big to show here.

vendor/charm.land/fantasy/jsonrepair/jsonrepair.go+1648

This diff is too big to show here.

vendor/charm.land/fantasy/model.go+261

This diff is too big to show here.

vendor/charm.land/fantasy/model_json.go+156

This diff is too big to show here.

vendor/charm.land/fantasy/object.go+236

This diff is too big to show here.

vendor/charm.land/fantasy/object/object.go+620

This diff is too big to show here.

vendor/charm.land/fantasy/provider.go+11

This diff is too big to show here.

vendor/charm.land/fantasy/provider_registry.go+106

This diff is too big to show here.

vendor/charm.land/fantasy/providers/anthropic/anthropic.go+1707

This diff is too big to show here.

vendor/charm.land/fantasy/providers/anthropic/bedrock.go+15

This diff is too big to show here.

vendor/charm.land/fantasy/providers/anthropic/call_useragent.go+14

This diff is too big to show here.

vendor/charm.land/fantasy/providers/anthropic/computer_use.go+427

This diff is too big to show here.

vendor/charm.land/fantasy/providers/anthropic/error.go+67

This diff is too big to show here.

vendor/charm.land/fantasy/providers/anthropic/google.go+11

This diff is too big to show here.

vendor/charm.land/fantasy/providers/anthropic/provider_options.go+283

This diff is too big to show here.

vendor/charm.land/fantasy/providers/anthropic/sanitize.go+33

This diff is too big to show here.

vendor/charm.land/fantasy/providers/azure/README.md+6

This diff is too big to show here.

vendor/charm.land/fantasy/providers/azure/azure.go+125

This diff is too big to show here.

vendor/charm.land/fantasy/providers/bedrock/README.md+10

This diff is too big to show here.

vendor/charm.land/fantasy/providers/bedrock/bedrock.go+87

This diff is too big to show here.

vendor/charm.land/fantasy/providers/google/README.md+63

This diff is too big to show here.

vendor/charm.land/fantasy/providers/google/auth.go+15

This diff is too big to show here.

vendor/charm.land/fantasy/providers/google/call_useragent.go+53

This diff is too big to show here.

vendor/charm.land/fantasy/providers/google/error.go+51

This diff is too big to show here.

vendor/charm.land/fantasy/providers/google/google.go+1488

This diff is too big to show here.

vendor/charm.land/fantasy/providers/google/provider_options.go+146

This diff is too big to show here.

vendor/charm.land/fantasy/providers/google/slice.go+11

This diff is too big to show here.

vendor/charm.land/fantasy/providers/internal/httpheaders/httpheaders.go+60

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openai/call_useragent.go+31

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openai/error.go+92

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openai/language_model.go+990

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openai/language_model_hooks.go+668

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openai/openai.go+220

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openai/provider_options.go+217

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openai/responses_language_model.go+1678

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openai/responses_options.go+395

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openaicompat/language_model_hooks.go+516

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openaicompat/openaicompat.go+140

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openaicompat/provider_options.go+161

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openrouter/language_model_hooks.go+1063

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openrouter/openrouter.go+121

This diff is too big to show here.

vendor/charm.land/fantasy/providers/openrouter/provider_options.go+218

This diff is too big to show here.

vendor/charm.land/fantasy/providers/vercel/language_model_hooks.go+1074

This diff is too big to show here.

vendor/charm.land/fantasy/providers/vercel/provider_options.go+195

This diff is too big to show here.

vendor/charm.land/fantasy/providers/vercel/vercel.go+122

This diff is too big to show here.

vendor/charm.land/fantasy/retry.go+155

This diff is too big to show here.

vendor/charm.land/fantasy/schema/schema.go+442

This diff is too big to show here.

vendor/charm.land/fantasy/tool.go+176

This diff is too big to show here.

vendor/charm.land/fantasy/util.go+22

This diff is too big to show here.

vendor/charm.land/fantasy/version.go+12

This diff is too big to show here.

vendor/charm.land/fantasy/version.txt+1

This diff is too big to show here.

vendor/charm.land/glamour/v2/.editorconfig+18

This diff is too big to show here.

vendor/charm.land/glamour/v2/.gitattributes+2

This diff is too big to show here.

vendor/charm.land/glamour/v2/.gitignore+2

This diff is too big to show here.

vendor/charm.land/glamour/v2/.golangci.yml+44

This diff is too big to show here.

vendor/charm.land/glamour/v2/.goreleaser.yml+6

This diff is too big to show here.

vendor/charm.land/glamour/v2/CONTRIBUTING.md+23

This diff is too big to show here.

vendor/charm.land/glamour/v2/LICENSE+21

This diff is too big to show here.

vendor/charm.land/glamour/v2/README.md+129

This diff is too big to show here.

vendor/charm.land/glamour/v2/Taskfile.yml+25

This diff is too big to show here.

vendor/charm.land/glamour/v2/UPGRADE_GUIDE_V2.md+279

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/ansi.go+3

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/baseelement.go+157

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/blockelement.go+66

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/blockstack.go+95

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/codeblock.go+151

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/codespan.go+15

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/context.go+38

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/elements.go+481

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/emphasis.go+47

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/heading.go+80

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/image.go+57

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/link.go+112

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/listitem.go+29

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/margin.go+231

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/paragraph.go+63

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/renderer.go+166

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/style.go+252

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/table.go+206

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/table_links.go+234

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/task.go+27

This diff is too big to show here.

vendor/charm.land/glamour/v2/ansi/templatehelper.go+86

This diff is too big to show here.

vendor/charm.land/glamour/v2/examples.sh+19

This diff is too big to show here.

vendor/charm.land/glamour/v2/gallery.sh+23

This diff is too big to show here.

vendor/charm.land/glamour/v2/glamour.go+294

This diff is too big to show here.

vendor/charm.land/glamour/v2/internal/autolink/autolink.go+55

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/README.md+565

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/ascii.json+87

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/dark.json+191

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/dracula.go+216

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/dracula.json+188

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/light.json+190

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/notty.json+87

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/pink.json+90

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/styles.go+691

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/tokyo-night.go+209

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/tokyo-night.json+182

This diff is too big to show here.

vendor/charm.land/glamour/v2/styles/tokyo_night.json+182

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/.editorconfig+18

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/.gitattributes+1

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/.gitignore+3

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/.golangci.yml+50

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/.goreleaser.yml+5

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/LICENSE+21

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/README.md+996

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/Taskfile.yaml+24

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/UPGRADE_GUIDE_V2.md+504

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/align.go+82

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/ansi_unix.go+8

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/ansi_windows.go+30

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/blending.go+196

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/borders.go+587

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/canvas.go+88

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/color.go+359

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/get.go+657

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/join.go+175

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/layer.go+327

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/lipgloss.go+3

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/position.go+134

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/query.go+92

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/ranges.go+48

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/runes.go+43

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/set.go+932

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/size.go+40

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/style.go+637

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/table/resizing.go+489

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/table/rows.go+130

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/table/table.go+568

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/table/util.go+44

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/terminal.go+124

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/tree/children.go+100

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/tree/enumerator.go+74

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/tree/renderer.go+165

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/tree/tree.go+407

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/unset.go+359

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/whitespace.go+76

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/wrap.go+113

This diff is too big to show here.

vendor/charm.land/lipgloss/v2/writer.go+160

This diff is too big to show here.

vendor/charm.land/log/v2/.gitignore+17

This diff is too big to show here.

vendor/charm.land/log/v2/.golangci.yml+50

This diff is too big to show here.

vendor/charm.land/log/v2/.goreleaser.yml+6

This diff is too big to show here.

vendor/charm.land/log/v2/LICENSE+21

This diff is too big to show here.

vendor/charm.land/log/v2/README.md+367

This diff is too big to show here.

vendor/charm.land/log/v2/UPGRADE_GUIDE_V2.md+320

This diff is too big to show here.

vendor/charm.land/log/v2/context.go+23

This diff is too big to show here.

vendor/charm.land/log/v2/doc.go+3

This diff is too big to show here.

vendor/charm.land/log/v2/formatter.go+27

This diff is too big to show here.

vendor/charm.land/log/v2/json.go+157

This diff is too big to show here.

vendor/charm.land/log/v2/level.go+65

This diff is too big to show here.

vendor/charm.land/log/v2/logfmt.go+32

This diff is too big to show here.

vendor/charm.land/log/v2/logger.go+413

This diff is too big to show here.

vendor/charm.land/log/v2/logger_121.go+72

This diff is too big to show here.

vendor/charm.land/log/v2/logger_no121.go+69

This diff is too big to show here.

vendor/charm.land/log/v2/options.go+61

This diff is too big to show here.

vendor/charm.land/log/v2/pkg.go+248

This diff is too big to show here.

vendor/charm.land/log/v2/stdlog.go+67

This diff is too big to show here.

vendor/charm.land/log/v2/styles.go+83

This diff is too big to show here.

vendor/charm.land/log/v2/text.go+272

This diff is too big to show here.

vendor/charm.land/x/vcr/LICENSE+21

This diff is too big to show here.

vendor/charm.land/x/vcr/doc.go+3

This diff is too big to show here.

vendor/charm.land/x/vcr/hooks.go+33

This diff is too big to show here.

vendor/charm.land/x/vcr/marshaler.go+19

This diff is too big to show here.

vendor/charm.land/x/vcr/matcher.go+70

This diff is too big to show here.

vendor/charm.land/x/vcr/recorder.go+70

This diff is too big to show here.

vendor/cloud.google.com/go/LICENSE+202

This diff is too big to show here.

vendor/cloud.google.com/go/auth/CHANGES.md+483

This diff is too big to show here.

vendor/cloud.google.com/go/auth/LICENSE+202

This diff is too big to show here.

vendor/cloud.google.com/go/auth/README.md+40

This diff is too big to show here.

vendor/cloud.google.com/go/auth/auth.go+618

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/compute.go+102

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/detect.go+471

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/doc.go+45

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/filetypes.go+329

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/aws_provider.go+531

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/executable_provider.go+284

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/externalaccount.go+431

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/file_provider.go+78

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/info.go+74

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/programmatic_provider.go+30

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/url_provider.go+93

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/x509_provider.go+220

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/externalaccountuser/externalaccountuser.go+115

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/gdch/gdch.go+198

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/impersonate/idtoken.go+105

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/impersonate/impersonate.go+168

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/internal/stsexchange/sts_exchange.go+167

This diff is too big to show here.

vendor/cloud.google.com/go/auth/credentials/selfsignedjwt.go+89

This diff is too big to show here.

vendor/cloud.google.com/go/auth/grpctransport/dial_socketopt.go+62

This diff is too big to show here.

vendor/cloud.google.com/go/auth/grpctransport/directpath.go+177

This diff is too big to show here.

vendor/cloud.google.com/go/auth/grpctransport/grpctransport.go+675

This diff is too big to show here.

vendor/cloud.google.com/go/auth/grpctransport/pool.go+119

This diff is too big to show here.

vendor/cloud.google.com/go/auth/httptransport/httptransport.go+254

This diff is too big to show here.

vendor/cloud.google.com/go/auth/httptransport/transport.go+548

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/compute/compute.go+65

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/compute/manufacturer.go+22

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/compute/manufacturer_linux.go+23

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/compute/manufacturer_windows.go+46

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/credsfile/credsfile.go+63

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/credsfile/filetype.go+159

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/credsfile/parse.go+99

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/internal.go+285

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/jwt/jwt.go+208

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/retry/retry.go+117

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/transport/cba.go+361

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/transport/cert/default_cert.go+65

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/transport/cert/enterprise_cert.go+54

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/transport/cert/secureconnect_cert.go+124

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/transport/cert/workload_cert.go+138

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/transport/headers/headers.go+61

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/transport/s2a.go+138

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/transport/transport.go+137

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/trustboundary/external_accounts_config_providers.go+100

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/trustboundary/trust_boundary.go+392

This diff is too big to show here.

vendor/cloud.google.com/go/auth/internal/version.go+20

This diff is too big to show here.

vendor/cloud.google.com/go/auth/oauth2adapt/CHANGES.md+82

This diff is too big to show here.

vendor/cloud.google.com/go/auth/oauth2adapt/LICENSE+202

This diff is too big to show here.

vendor/cloud.google.com/go/auth/oauth2adapt/oauth2adapt.go+200

This diff is too big to show here.

vendor/cloud.google.com/go/auth/threelegged.go+382

This diff is too big to show here.

vendor/cloud.google.com/go/civil/civil.go+500

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/CHANGES.md+115

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/LICENSE+202

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/README.md+27

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/log.go+149

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/metadata.go+937

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/retry.go+117

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/retry_linux.go+31

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/syscheck.go+28

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/syscheck_linux.go+30

This diff is too big to show here.

vendor/cloud.google.com/go/compute/metadata/syscheck_windows.go+39

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/.gitignore+1

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/ARCHITECTURE.md+244

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/LICENSE+61

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/README.md+86

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/constants.go+65

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/data/xml/dom/xmldocument.go+73

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/ui/notifications/toastnotification.go+88

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/ui/notifications/toastnotificationmanager.go+53

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/ui/notifications/toastnotificationmanagerforuser.go+68

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/internal/winrt/ui/notifications/toastnotifier.go+64

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/tmpl/powershell.go.tmpl+14

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/tmpl/tmpl.go+28

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/tmpl/xml.go.tmpl+34

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/toast.go+225

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/bind.go+86

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/bind_noop.go+19

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/bind_windows.go+174

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/impl.go+179

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/procs.go+37

This diff is too big to show here.

vendor/git.sr.ht/~jackmordaunt/go-toast/wintoast/registry.go+110

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md+849

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/LICENSE.txt+21

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/README.md+39

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml+29

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud/cloud.go+44

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud/doc.go+53

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go+173

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/doc.go+264

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/errors.go+17

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/etag.go+57

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go+175

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/pipeline.go+77

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go+260

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go+201

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log/log.go+50

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go+159

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go+135

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/fake/fake.go+133

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go+123

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go+148

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/poller.go+24

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go+212

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go+44

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go+149

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/doc.go+10

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/log.go+55

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/doc.go+10

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go+198

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/doc.go+10

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/errors.go+27

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go+138

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pipeline.go+94

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_api_version.go+75

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go+236

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go+72

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_header.go+40

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go+154

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_include_response.go+35

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_key_credential.go+64

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_logging.go+264

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_request_id.go+34

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go+276

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_sas_credential.go+55

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_telemetry.go+83

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go+396

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go+281

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/response.go+109

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_other.go+15

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_wasm.go+15

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_http_client.go+48

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming/doc.go+9

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming/progress.go+89

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing/constants.go+41

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing/tracing.go+191

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/LICENSE.txt+21

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/diag/diag.go+51

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/diag/doc.go+7

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo/doc.go+7

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo/errorinfo.go+46

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/exported/exported.go+129

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/log/doc.go+7

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/log/log.go+104

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/poller/util.go+155

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/temporal/resource.go+123

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/uuid/doc.go+7

This diff is too big to show here.

vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/uuid/uuid.go+76

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/.gitignore+14

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/CONTRIBUTING.md

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/LICENSE+21

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/README.md+242

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/SECURITY.md+6

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/commonmark.go+393

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/escape/escape.go+65

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/from.go+464

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/logo_five_years.png

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/markdown.go+212

This diff is too big to show here.

vendor/github.com/JohannesKaufmann/html-to-markdown/utils.go+533

This diff is too big to show here.

vendor/github.com/KyleBanks/depth/.gitignore+16

This diff is too big to show here.

vendor/github.com/KyleBanks/depth/.travis.yml+9

This diff is too big to show here.

vendor/github.com/KyleBanks/depth/LICENSE+21

This diff is too big to show here.

vendor/github.com/KyleBanks/depth/Makefile+32

This diff is too big to show here.

vendor/github.com/KyleBanks/depth/README.md+232

This diff is too big to show here.

vendor/github.com/KyleBanks/depth/depth.go+129

This diff is too big to show here.

vendor/github.com/KyleBanks/depth/pkg.go+184

This diff is too big to show here.

vendor/github.com/MakeNowJust/heredoc/LICENSE+21

This diff is too big to show here.

vendor/github.com/MakeNowJust/heredoc/README.md+52

This diff is too big to show here.

vendor/github.com/MakeNowJust/heredoc/heredoc.go+105

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/.gitattributes+1

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/.gitignore+10

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/.golangci.yml+147

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/CODEOWNERS+1

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/LICENSE+22

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/README.md+89

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/SECURITY.md+41

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/backup.go+287

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/doc.go+22

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/ea.go+137

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/file.go+320

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/fileinfo.go+106

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/hvsock.go+582

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/internal/fs/doc.go+2

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/internal/fs/fs.go+262

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/internal/fs/security.go+12

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go+61

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go+20

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/internal/socket/socket.go+177

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go+69

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go+132

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/pipe.go+586

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go+232

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go+16

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go+13

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go+27

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/privilege.go+196

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/reparse.go+131

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/sd.go+133

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/syscall.go+5

This diff is too big to show here.

vendor/github.com/Microsoft/go-winio/zsyscall_windows.go+378

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/.gitattributes+1

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/.gitignore+16

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/LICENSE+12

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/README.md+218

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/array.go+124

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/doc.go+123

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/expand.go+70

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/filter.go+163

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/iteration.go+61

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/manipulation.go+679

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/property.go+275

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/query.go+49

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/traversal.go+704

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/type.go+203

This diff is too big to show here.

vendor/github.com/PuerkitoBio/goquery/utilities.go+177

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/.editorconfig+17

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/.gitignore+28

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/.golangci.yml+122

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/.goreleaser.yml+34

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/AGENTS.md+11

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/BUILD.bit+93

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/COPYING+118

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/Dockerfile+64

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/Justfile+59

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/README.md+309

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/biome.json+6

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/chroma.jpg

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/coalesce.go+35

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/colour.go+192

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/delegate.go+161

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/doc.go+7

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/emitters.go+233

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/formatter.go+43

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/formatters/api.go+57

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go+692

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/formatters/json.go+39

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go+51

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/formatters/svg/svg.go+222

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/formatters/tokens.go+18

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/formatters/tty_indexed.go+284

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/formatters/tty_truecolour.go+76

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/iterator.go+93

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexer.go+179

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/README.md+46

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/caddyfile.go+275

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/cl.go+243

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/dns.go+17

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/emacs.go+533

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abap.xml+154

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abnf.xml+66

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript.xml+68

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript_3.xml+163

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ada.xml+321

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/agda.xml+66

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/al.xml+75

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/alloy.xml+58

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ampl.xml+98

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml+109

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/antlr.xml+317

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apacheconf.xml+74

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apl.xml+59

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml+151

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arangodb_aql.xml+174

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml+322

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml+126

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arturo.xml+119

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/atl.xml+165

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autohotkey.xml+78

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autoit.xml+70

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/awk.xml+95

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ballerina.xml+97

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash.xml+222

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash_session.xml+25

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/batchfile.xml+660

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/beef.xml+120

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bibtex.xml+152

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bicep.xml+84

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/blitzbasic.xml+141

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bnf.xml+28

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bqn.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/brainfuck.xml+51

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c#.xml+121

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c++.xml+331

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c.xml+260

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c3.xml+374

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cap_n_proto.xml+122

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cassandra_cql.xml+137

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ceylon.xml+151

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml+197

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfstatement.xml+92

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chaiscript.xml+134

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chapel.xml+143

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cheetah.xml+55

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/clojure.xml+71

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cmake.xml+90

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cobol.xml+90

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coffeescript.xml+210

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/common_lisp.xml+184

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coq.xml+136

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/core.xml+79

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/crystal.xml+762

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml+323

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/csv.xml+53

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cue.xml+85

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cython.xml+372

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/d.xml+133

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml+213

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dax.xml+39

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/desktop_entry.xml+17

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/devicetree.xml+251

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/diff.xml+52

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/django_jinja.xml+153

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml+44

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml+68

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dtd.xml+168

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dylan.xml+176

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ebnf.xml+90

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elixir.xml+744

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elm.xml+119

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/emacslisp.xml+132

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erb.xml+37

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erlang.xml+166

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/factor.xml+412

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fennel.xml+68

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fish.xml+159

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/forth.xml+78

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml+102

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortranfixed.xml+71

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fsharp.xml+245

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml+150

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript.xml+259

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript3.xml+270

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gemfile_lock.xml+81

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gettext.xml+24

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gherkin.xml+263

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gleam.xml+100

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/glsl.xml+65

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gnuplot.xml+289

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/go_template.xml+114

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml+92

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groff.xml+90

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groovy.xml+135

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/handlebars.xml+147

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hare.xml+98

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/haskell.xml+275

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hcl.xml+143

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hexdump.xml+189

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml+131

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlsl.xml+110

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/holyc.xml+252

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/html.xml+159

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hy.xml+104

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/idris.xml+216

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/igor.xml+47

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ini.xml+52

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/io.xml+71

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/iscdhcpd.xml+96

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/j.xml+157

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/janet.xml+48

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml+206

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml+160

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml+117

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jsonata.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jsonnet.xml+138

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/julia.xml+400

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jungle.xml+98

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kakoune.xml+96

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kdl.xml+75

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml+234

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lateralus.xml+184

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lean.xml+56

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lighttpd_configuration_file.xml+42

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lilypond.xml+133

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/llvm.xml+73

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lox.xml+78

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml+158

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/luau.xml+173

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/makefile.xml+131

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mako.xml+120

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mason.xml+89

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml+155

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mathematica.xml+60

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/matlab.xml+114

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml+138

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml+86

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/metal.xml+270

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/microcad.xml+139

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/minizinc.xml+82

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mlir.xml+73

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/modelica.xml+106

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/modula-2.xml+245

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mojo.xml+228

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/monkeyc.xml+153

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/moonbit.xml+75

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/moonscript.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/morrowindscript.xml+90

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/myghty.xml+77

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml+121

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nasm.xml+126

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/natural.xml+143

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ndisasm.xml+123

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/newspeak.xml+121

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nginx_configuration_file.xml+101

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nim.xml+211

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nix.xml+258

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nsis.xml+59

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nu.xml+126

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objective-c.xml+510

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml+142

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ocaml.xml+153

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/octave.xml+101

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/odin.xml+127

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/onesenterprise.xml+92

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openedge_abl.xml+101

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openscad.xml+96

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/org_mode.xml+329

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pacmanconf.xml+37

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/perl.xml+400

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml+258

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pig.xml+105

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pkgconfig.xml+73

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pl_pgsql.xml+119

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plaintext.xml+21

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plutus_core.xml+105

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pony.xml+135

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postgresql_sql_dialect.xml+155

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml+93

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/povray.xml+58

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powerquery.xml+51

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powershell.xml+230

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prolog.xml+115

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promela.xml+119

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promql.xml+123

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml+45

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml+124

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prql.xml+161

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/psl.xml+213

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/puppet.xml+100

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python.xml+595

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python_2.xml+356

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qbasic.xml+173

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qml.xml+113

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/r.xml+128

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/racket.xml+260

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ragel.xml+149

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/react.xml+236

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reasonml.xml+147

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reg.xml+68

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rego.xml+94

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rexx.xml+127

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rgbasm.xml+239

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ring.xml+74

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpgle.xml+176

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpm_spec.xml+58

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml+728

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rust.xml+375

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sas.xml+191

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sass.xml+362

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scala.xml+274

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scdoc.xml+115

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scheme.xml+106

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scilab.xml+98

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scss.xml+373

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml+92

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sieve.xml+61

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smali.xml+73

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smalltalk.xml+294

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smarty.xml+79

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/snbt.xml+58

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/snobol.xml+95

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/solidity.xml+291

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sourcepawn.xml+59

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/spade.xml+292

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sparql.xml+160

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sql.xml+90

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/squidconf.xml+63

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/standard_ml.xml+548

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stas.xml+85

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stylus.xml+132

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/swift.xml+207

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemd.xml+63

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemverilog.xml+181

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tablegen.xml+69

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tal.xml+43

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tasm.xml+135

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcl.xml+272

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcsh.xml+121

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/templ.xml+315

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/termcap.xml+75

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terminfo.xml+84

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml+149

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tex.xml+113

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/thrift.xml+154

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml+45

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tradingview.xml+81

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml+137

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turing.xml+82

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turtle.xml+170

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/twig.xml+155

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/txtpb.xml+162

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml+302

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscript.xml+178

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscriptcssdata.xml+52

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscripthtmldata.xml+52

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typst.xml+108

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ucode.xml+147

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v.xml+355

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v_shell.xml+365

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vala.xml+72

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vb_net.xml+162

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/verilog.xml+158

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhdl.xml+171

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhs.xml+48

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/viml.xml+85

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vue.xml+295

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/wat.xml+149

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/wdte.xml+43

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/webgpu_shading_language.xml+142

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/webvtt.xml+283

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/whiley.xml+57

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml+96

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xorg.xml+35

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml+132

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yang.xml+99

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/z80_assembly.xml+74

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zed.xml+51

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml+187

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/erb.go+29

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/gemtext.go+37

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/genshi.go+118

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/go.go+81

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/haxe.go+647

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/html.go+8

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/http.go+131

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/lexers.go+85

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go+107

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/markless.go+168

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/mysql.go+33

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/php.go+37

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/raku.go+1710

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/rst.go+89

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/svelte.go+70

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/typoscript.go+85

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/yaml_jinja.go+20

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/lexers/zed.go+24

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/mutators.go+201

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/pygments-lexers.txt+605

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/quick/quick.go+44

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/regexp.go+533

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/registry.go+228

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/remap.go+94

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/renovate.json5+25

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/serialise.go+483

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/style.go+530

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/abap.xml+11

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/algol.xml+18

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/algol_nu.xml+18

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/api.go+95

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/arduino.xml+18

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/ashen.xml+69

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/aura-theme-dark-soft.xml+107

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/aura-theme-dark.xml+107

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/autumn.xml+36

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/average.xml+74

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/base16-snazzy.xml+74

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/borland.xml+26

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/bw.xml+23

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/colorful.xml+52

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/compat.go+69

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/darcula.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/doom-one.xml+51

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/doom-one2.xml+64

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/dracula.xml+74

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/emacs.xml+44

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/evergarden.xml+33

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/friendly.xml+44

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/fruity.xml+19

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml+46

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/github.xml+39

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.xml+34

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/gruvbox.xml+34

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/hr_high_contrast.xml+12

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/hrdark.xml+10

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/igor.xml+9

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-dragon.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-lotus.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/kanagawa-wave.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/lovelace.xml+53

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/manni.xml+44

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml+13

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/modus-vivendi.xml+13

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/monokai.xml+29

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/monokailight.xml+26

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/murphy.xml+52

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/native.xml+35

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/nord.xml+46

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/nordic.xml+46

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/onedark.xml+25

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/onesenterprise.xml+10

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/paraiso-dark.xml+37

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/paraiso-light.xml+37

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/pastie.xml+45

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/perldoc.xml+37

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/pygments.xml+42

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/rainbow_dash.xml+40

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-dawn.xml+29

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-moon.xml+29

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/rose-pine.xml+29

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/rpgle.xml+30

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/rrt.xml+19

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark.xml+39

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark256.xml+41

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml+17

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/swapoff.xml+18

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/tango.xml+72

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-day.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-moon.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-night.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-storm.xml+83

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/trac.xml+35

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/vim.xml+29

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/vs.xml+16

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/vulcan.xml+74

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/witchhazel.xml+31

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/xcode-dark.xml+31

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/styles/xcode.xml+22

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/table.py+31

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/test.jsonl+2

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/tokentype_enumer.go+588

This diff is too big to show here.

vendor/github.com/alecthomas/chroma/v2/types.go+357

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/.gitignore+2

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/LICENSE+19

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/README.md+19

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/backward_references.go+185

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/backward_references_hq.go+796

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/bit_cost.go+436

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/bit_reader.go+266

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/bitwriter.go+56

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/block_splitter.go+144

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/block_splitter_command.go+434

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/block_splitter_distance.go+433

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/block_splitter_literal.go+433

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/brotli_bit_stream.go+1435

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/cluster.go+30

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/cluster_command.go+164

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/cluster_distance.go+326

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/cluster_literal.go+326

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/command.go+254

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/compress_fragment.go+834

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/compress_fragment_two_pass.go+775

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/constants.go+77

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/context.go+2176

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/decode.go+2581

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/dictionary.go+122890

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/dictionary_hash.go+32779

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/encode.go+1220

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/encoder.go+177

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/encoder_dict.go+22

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/encoder_fast.go+197

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/entropy_encode.go+592

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/entropy_encode_static.go+4399

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/fast_log.go+290

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/find_match_length.go+45

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/flate/LICENSE+27

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/flate/README.md+2

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/flate/gzip.go+65

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/flate/huffman_bit_writer.go+517

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/flate/huffman_code.go+346

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/flate/token.go+80

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/flate/writer.go+66

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/h10.go+287

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/h5.go+214

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/h6.go+216

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/hash.go+342

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/hash_composite.go+93

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/hash_forgetful_chain.go+252

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/hash_longest_match_quickly.go+214

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/hash_rolling.go+168

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/histogram.go+226

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/http.go+189

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/huffman.go+653

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/literal_cost.go+182

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/bargain1.go+212

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/bargain2.go+248

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/bargain3.go+278

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/emitter.go+34

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/m0.go+175

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/m4.go+339

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/matchfinder.go+103

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/pathfinder.go+328

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/textencoder.go+53

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/trio.go+326

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/zdfast.go+258

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/zfast.go+206

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/matchfinder/zm.go+301

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/memory.go+66

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/metablock.go+574

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/metablock_command.go+165

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/metablock_distance.go+165

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/metablock_literal.go+165

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/params.go+37

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/platform.go+103

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/prefix.go+30

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/prefix_dec.go+723

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/quality.go+196

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/reader.go+111

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/ringbuffer.go+134

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/state.go+294

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/static_dict.go+662

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/static_dict_lut.go+75094

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/symbol_list.go+22

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/transform.go+641

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/utf8_util.go+70

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/util.go+7

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/write_bits.go+52

This diff is too big to show here.

vendor/github.com/andybalholm/brotli/writer.go+162

This diff is too big to show here.

vendor/github.com/andybalholm/cascadia/.travis.yml+14

This diff is too big to show here.

vendor/github.com/andybalholm/cascadia/LICENSE+24

This diff is too big to show here.

vendor/github.com/andybalholm/cascadia/README.md+144

This diff is too big to show here.

vendor/github.com/andybalholm/cascadia/parser.go+889

This diff is too big to show here.

vendor/github.com/andybalholm/cascadia/pseudo_classes.go+458

This diff is too big to show here.

vendor/github.com/andybalholm/cascadia/selector.go+586

This diff is too big to show here.

vendor/github.com/andybalholm/cascadia/serialize.go+176

This diff is too big to show here.

vendor/github.com/andybalholm/cascadia/specificity.go+26

This diff is too big to show here.

vendor/github.com/atotto/clipboard/.travis.yml+22

This diff is too big to show here.

vendor/github.com/atotto/clipboard/LICENSE+27

This diff is too big to show here.

vendor/github.com/atotto/clipboard/README.md+48

This diff is too big to show here.

vendor/github.com/atotto/clipboard/clipboard.go+20

This diff is too big to show here.

vendor/github.com/atotto/clipboard/clipboard_darwin.go+52

This diff is too big to show here.

vendor/github.com/atotto/clipboard/clipboard_plan9.go+42

This diff is too big to show here.

vendor/github.com/atotto/clipboard/clipboard_unix.go+149

This diff is too big to show here.

vendor/github.com/atotto/clipboard/clipboard_windows.go+157

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/NOTICE.txt+3

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/accountid_endpoint_mode.go+18

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/checksum.go+33

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/config.go+254

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/context.go+22

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/credential_cache.go+235

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/credentials.go+234

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/defaults/auto.go+38

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/defaults/configuration.go+43

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/defaults/defaults.go+50

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/defaults/doc.go+2

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/defaultsmode.go+95

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/doc.go+62

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/endpoints.go+247

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/errors.go+9

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/from_ptr.go+365

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/logging.go+119

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/logging_generate.go+95

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/metadata.go+213

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/middleware.go+168

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/osname.go+24

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/osname_go115.go+24

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/recursion_detection.go+94

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/request_id.go+27

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/request_id_retriever.go+57

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/user_agent.go+398

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/CHANGELOG.md+203

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/debug.go+144

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/decode.go+218

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/encode.go+167

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/error.go+23

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi/headers.go+24

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi/middleware.go+71

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi/transport.go+13

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/eventstreamapi/transport_go117.go+12

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/header.go+175

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/header_value.go+521

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/message.go+99

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/array.go+61

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/encoder.go+80

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/map.go+78

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/middleware.go+62

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/object.go+68

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/value.go+117

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/restjson/decoder_util.go+85

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/xml/error_utils.go+48

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/ratelimit/none.go+20

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/ratelimit/token_bucket.go+96

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/ratelimit/token_rate_limit.go+83

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/request.go+25

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/restrict_file_permissions.go+21

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/adaptive.go+156

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/adaptive_ratelimit.go+158

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/adaptive_token_bucket.go+83

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/attempt_metrics.go+51

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/doc.go+80

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/errors.go+20

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/jitter_backoff.go+124

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/metadata.go+52

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/middleware.go+487

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/retry.go+103

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/retryable_error.go+228

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/standard.go+343

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/throttle_error.go+60

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retry/timeout_error.go+52

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/retryer.go+127

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/runtime.go+14

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/cache.go+115

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/const.go+40

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/header_rules.go+82

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/headers.go+70

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/hmac.go+13

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/host.go+75

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/scope.go+13

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/time.go+36

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/util.go+80

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/v4/middleware.go+420

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/v4/presign_middleware.go+127

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/v4/stream.go+86

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/signer/v4/v4.go+564

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/to_ptr.go+297

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/client.go+355

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/content_type.go+42

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/response_error.go+33

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/response_error_middleware.go+56

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/transport/http/timeout_read_closer.go+109

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/types.go+42

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/aws/version.go+8

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/CHANGELOG.md+1097

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/auth_scheme_preference.go+19

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/config.go+237

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/defaultsmode.go+47

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/doc.go+20

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/env_config.go+966

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/generate.go+4

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/errors.go+22

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/ini.go+56

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/parse.go+109

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/sections.go+157

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/strings.go+89

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/token.go+32

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/tokenize.go+92

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/internal/ini/value.go+93

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/load_options.go+1371

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/local.go+51

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/provider.go+802

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/resolve.go+458

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/resolve_bearer_token.go+122

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/resolve_credentials.go+650

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/config/shared_config.go+1704

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/CHANGELOG.md+990

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/doc.go+4

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds/doc.go+58

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds/provider.go+241

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client/auth.go+48

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client/client.go+165

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client/endpoints.go+20

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client/middleware.go+164

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/provider.go+207

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/logincreds/dpop.go+150

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/logincreds/file.go+14

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/logincreds/provider.go+184

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/logincreds/token.go+110

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/processcreds/doc.go+92

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/processcreds/provider.go+296

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/doc.go+81

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_cached_token.go+232

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_credentials_provider.go+165

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_token_provider.go+147

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/static_provider.go+63

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/stscreds/assume_role_provider.go+338

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/credentials/stscreds/web_identity_provider.go+181

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/CHANGELOG.md+584

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_client.go+358

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetDynamicData.go+77

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetIAMInfo.go+103

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetInstanceIdentityDocument.go+110

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetMetadata.go+77

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetRegion.go+73

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetToken.go+119

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/api_op_GetUserData.go+61

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/auth.go+48

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/doc.go+12

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/endpoints.go+20

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/internal/config/resolvers.go+114

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/request_middleware.go+313

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/token_provider.go+261

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/auth/auth.go+45

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/auth/scheme.go+191

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/bearer_token_adapter.go+43

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/bearer_token_signer_adapter.go+35

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/credentials_adapter.go+46

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/smithy.go+2

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/v4signer_adapter.go+57

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/auth/smithy/v4signer_adapter_eventstream.go+51

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/CHANGELOG.md+544

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/config.go+65

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/endpoints.go+57

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/configsources/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/context/context.go+65

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/arn.go+94

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/doc.go+3

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/generate.go+7

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/host.go+51

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partition.go+76

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.go+496

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn/partitions.json+267

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/endpoints.go+201

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/CHANGELOG.md+519

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/endpoints.go+302

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/rand/rand.go+33

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/sdk/interfaces.go+9

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/sdk/time.go+74

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/sdkio/byte.go+12

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/shareddefaults/shared_config.go+47

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/strings/strings.go+11

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/LICENSE+28

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/docs.go+7

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/singleflight.go+210

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/timeconv/duration.go+13

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/CHANGELOG.md+486

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/credentials.go+141

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/error.go+17

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/crypto/compare.go+30

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/crypto/ecc.go+113

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/const.go+36

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/header_rules.go+82

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/headers.go+68

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/hmac.go+13

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/host.go+75

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/time.go+36

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/internal/v4/util.go+64

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/middleware.go+118

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/presign_middleware.go+117

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/smithy.go+92

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/internal/v4a/v4a.go+520

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/CHANGELOG.md+220

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/accept_encoding_gzip.go+176

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/doc.go+22

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/CHANGELOG.md+571

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/context.go+56

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/doc.go+3

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/middleware.go+110

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/CHANGELOG.md+85

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_client.go+945

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_CreateOAuth2Token.go+212

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteConsoleAuthorizationConfiguration.go+168

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_DeleteResourcePermissionStatement.go+196

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetConsoleAuthorizationConfiguration.go+168

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_GetResourcePolicy.go+155

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_ListResourcePermissionStatements.go+261

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutConsoleAuthorizationConfiguration.go+168

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/api_op_PutResourcePermissionStatement.go+216

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/auth.go+361

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/deserializers.go+2474

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/doc.go+9

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/endpoints.go+854

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/generated.json+40

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/internal/endpoints/endpoints.go+333

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/options.go+242

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/serializers.go+724

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/enums.go+46

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/errors.go+247

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/types/types.go+162

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/signin/validators.go+111

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/CHANGELOG.md+792

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_client.go+929

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_GetRoleCredentials.go+165

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccountRoles.go+263

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_ListAccounts.go+261

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/api_op_Logout.go+164

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/auth.go+379

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/deserializers.go+1171

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/doc.go+27

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/endpoints.go+570

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/generated.json+35

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints/endpoints.go+628

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/options.go+238

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/serializers.go+309

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/types/errors.go+115

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/types/types.go+63

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sso/validators.go+175

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/CHANGELOG.md+790

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_client.go+929

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateToken.go+235

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_CreateTokenWithIAM.go+282

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_RegisterClient.go+206

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/api_op_StartDeviceAuthorization.go+188

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/auth.go+373

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/deserializers.go+2244

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/doc.go+49

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/endpoints.go+570

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/generated.json+36

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/internal/endpoints/endpoints.go+628

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/options.go+238

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/serializers.go+512

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/enums.go+44

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/errors.go+430

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/types/types.go+25

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/ssooidc/validators.go+184

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/CHANGELOG.md+832

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/LICENSE.txt+202

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_client.go+1115

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRole.go+544

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithSAML.go+455

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoleWithWebIdentity.go+472

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_AssumeRoot.go+229

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_DecodeAuthorizationMessage.go+189

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetAccessKeyInfo.go+180

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetCallerIdentity.go+192

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetDelegatedAccessToken.go+169

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetFederationToken.go+393

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetSessionToken.go+239

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/api_op_GetWebIdentityToken.go+192

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/auth.go+377

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/deserializers.go+3456

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/doc.go+13

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/endpoints.go+683

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/generated.json+45

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints/endpoints.go+585

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/options.go+286

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/serializers.go+1198

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/types/errors.go+363

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/types/types.go+144

This diff is too big to show here.

vendor/github.com/aws/aws-sdk-go-v2/service/sts/validators.go+433

This diff is too big to show here.

vendor/github.com/aws/smithy-go/.gitignore+29

This diff is too big to show here.

vendor/github.com/aws/smithy-go/.travis.yml+28

This diff is too big to show here.

vendor/github.com/aws/smithy-go/AGENTS.md+172

This diff is too big to show here.

vendor/github.com/aws/smithy-go/CHANGELOG.md+454

This diff is too big to show here.

vendor/github.com/aws/smithy-go/CODE_OF_CONDUCT.md+4

This diff is too big to show here.

vendor/github.com/aws/smithy-go/CONTRIBUTING.md+90

This diff is too big to show here.

vendor/github.com/aws/smithy-go/LICENSE+175

This diff is too big to show here.

vendor/github.com/aws/smithy-go/Makefile+130

This diff is too big to show here.

vendor/github.com/aws/smithy-go/NOTICE+1

This diff is too big to show here.

vendor/github.com/aws/smithy-go/README.md+107

This diff is too big to show here.

vendor/github.com/aws/smithy-go/auth/auth.go+3

This diff is too big to show here.

vendor/github.com/aws/smithy-go/auth/bearer/docs.go+3

This diff is too big to show here.

vendor/github.com/aws/smithy-go/auth/bearer/middleware.go+104

This diff is too big to show here.

vendor/github.com/aws/smithy-go/auth/bearer/token.go+50

This diff is too big to show here.

vendor/github.com/aws/smithy-go/auth/bearer/token_cache.go+208

This diff is too big to show here.

vendor/github.com/aws/smithy-go/auth/identity.go+47

This diff is too big to show here.

vendor/github.com/aws/smithy-go/auth/option.go+25

This diff is too big to show here.

vendor/github.com/aws/smithy-go/auth/scheme_id.go+20

This diff is too big to show here.

vendor/github.com/aws/smithy-go/changelog-template.json+9

This diff is too big to show here.

vendor/github.com/aws/smithy-go/context/suppress_expired.go+81

This diff is too big to show here.

vendor/github.com/aws/smithy-go/doc.go+2

This diff is too big to show here.

vendor/github.com/aws/smithy-go/document.go+10

This diff is too big to show here.

vendor/github.com/aws/smithy-go/document/doc.go+12

This diff is too big to show here.

vendor/github.com/aws/smithy-go/document/document.go+239

This diff is too big to show here.

vendor/github.com/aws/smithy-go/document/errors.go+75

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/doc.go+4

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/encoding.go+40

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/httpbinding/encode.go+123

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/httpbinding/header.go+122

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/httpbinding/path_replace.go+108

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/httpbinding/query.go+107

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/httpbinding/uri.go+111

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/json/array.go+35

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/json/constants.go+15

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go+139

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/json/encoder.go+30

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/json/escape.go+198

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/json/object.go+40

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/json/value.go+154

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/array.go+49

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/constants.go+10

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/doc.go+49

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/element.go+91

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/encoder.go+51

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/error_utils.go+51

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/escape.go+137

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/map.go+53

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/value.go+302

This diff is too big to show here.

vendor/github.com/aws/smithy-go/encoding/xml/xml_decoder.go+154

This diff is too big to show here.

vendor/github.com/aws/smithy-go/endpoints/endpoint.go+23

This diff is too big to show here.

vendor/github.com/aws/smithy-go/endpoints/private/bdd/evaluate.go+35

This diff is too big to show here.

vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/doc.go+4

This diff is too big to show here.

vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/split.go+16

This diff is too big to show here.

vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/string_slice.go+18

This diff is too big to show here.

vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/strings.go+25

This diff is too big to show here.

vendor/github.com/aws/smithy-go/endpoints/private/rulesfn/uri.go+133

This diff is too big to show here.

vendor/github.com/aws/smithy-go/errors.go+137

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/const.go+24

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/debug.go+144

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/decode.go+218

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/deserializer.go+294

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/encode.go+167

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/error.go+23

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/header.go+175

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/header_value.go+521

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/message.go+99

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/serializer.go+228

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/signer.go+82

This diff is too big to show here.

vendor/github.com/aws/smithy-go/eventstream/types.go+26

This diff is too big to show here.

vendor/github.com/aws/smithy-go/go_module_metadata.go+6

This diff is too big to show here.

vendor/github.com/aws/smithy-go/internal/sync/singleflight/LICENSE+28

This diff is too big to show here.

vendor/github.com/aws/smithy-go/internal/sync/singleflight/docs.go+8

This diff is too big to show here.

vendor/github.com/aws/smithy-go/internal/sync/singleflight/singleflight.go+210

This diff is too big to show here.

vendor/github.com/aws/smithy-go/io/byte.go+12

This diff is too big to show here.

vendor/github.com/aws/smithy-go/io/doc.go+2

This diff is too big to show here.

vendor/github.com/aws/smithy-go/io/reader.go+16

This diff is too big to show here.

vendor/github.com/aws/smithy-go/io/ringbuffer.go+94

This diff is too big to show here.

vendor/github.com/aws/smithy-go/local-mod-replace.sh+39

This diff is too big to show here.

vendor/github.com/aws/smithy-go/logging/logger.go+82

This diff is too big to show here.

vendor/github.com/aws/smithy-go/metrics/metrics.go+136

This diff is too big to show here.

vendor/github.com/aws/smithy-go/metrics/nop.go+98

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/context.go+41

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/doc.go+67

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/eventstream_middleware.go+21

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/logging.go+46

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/metadata.go+65

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/middleware.go+71

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/ordered_group.go+270

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/stack.go+209

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/stack_values.go+100

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/step_build.go+298

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/step_deserialize.go+300

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/step_finalize.go+298

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/step_initialize.go+299

This diff is too big to show here.

vendor/github.com/aws/smithy-go/middleware/step_serialize.go+305

This diff is too big to show here.

vendor/github.com/aws/smithy-go/modman.toml+9

This diff is too big to show here.

vendor/github.com/aws/smithy-go/private/requestcompression/gzip.go+30

This diff is too big to show here.

vendor/github.com/aws/smithy-go/private/requestcompression/middleware_capture_request_compression.go+52

This diff is too big to show here.

vendor/github.com/aws/smithy-go/private/requestcompression/request_compression.go+103

This diff is too big to show here.

vendor/github.com/aws/smithy-go/properties.go+69

This diff is too big to show here.

vendor/github.com/aws/smithy-go/ptr/doc.go+5

This diff is too big to show here.

vendor/github.com/aws/smithy-go/ptr/from_ptr.go+601

This diff is too big to show here.

vendor/github.com/aws/smithy-go/ptr/gen_scalars.go+83

This diff is too big to show here.

vendor/github.com/aws/smithy-go/ptr/to_ptr.go+499

This diff is too big to show here.

vendor/github.com/aws/smithy-go/rand/doc.go+3

This diff is too big to show here.

vendor/github.com/aws/smithy-go/rand/rand.go+31

This diff is too big to show here.

vendor/github.com/aws/smithy-go/rand/uuid.go+87

This diff is too big to show here.

vendor/github.com/aws/smithy-go/schema.go+328

This diff is too big to show here.

vendor/github.com/aws/smithy-go/schema_ext.go+37

This diff is too big to show here.

vendor/github.com/aws/smithy-go/serde.go+229

This diff is too big to show here.

vendor/github.com/aws/smithy-go/sync/error.go+53

This diff is too big to show here.

vendor/github.com/aws/smithy-go/time/time.go+134

This diff is too big to show here.

vendor/github.com/aws/smithy-go/tracing/context.go+96

This diff is too big to show here.

vendor/github.com/aws/smithy-go/tracing/nop.go+32

This diff is too big to show here.

vendor/github.com/aws/smithy-go/tracing/tracing.go+95

This diff is too big to show here.

vendor/github.com/aws/smithy-go/trait.go+21

This diff is too big to show here.

vendor/github.com/aws/smithy-go/traits/http.go+69

This diff is too big to show here.

vendor/github.com/aws/smithy-go/traits/index.go+107

This diff is too big to show here.

vendor/github.com/aws/smithy-go/traits/serde.go+56

This diff is too big to show here.

vendor/github.com/aws/smithy-go/traits/traits.go+72

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/auth.go+30

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/auth_schemes.go+45

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/checksum_middleware.go+70

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/client.go+161

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/doc.go+5

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/eventstream.go+209

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/eventstream_middleware.go+69

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/headerlist.go+163

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/host.go+89

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/interceptor.go+321

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/interceptor_middleware.go+325

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/internal/io/safe.go+75

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/md5_checksum.go+25

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/metrics.go+204

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/middleware_close_response_body.go+79

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/middleware_content_length.go+84

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/middleware_header_comment.go+81

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/middleware_headers.go+167

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/middleware_http_logging.go+75

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/middleware_metadata.go+51

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/middleware_min_proto.go+79

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/properties.go+80

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/protocol.go+27

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/request.go+188

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/response.go+34

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/time.go+13

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/url.go+44

This diff is too big to show here.

vendor/github.com/aws/smithy-go/transport/http/user_agent.go+37

This diff is too big to show here.

vendor/github.com/aws/smithy-go/type_registry.go+70

This diff is too big to show here.

vendor/github.com/aws/smithy-go/validation.go+140

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/LICENSE-BSD+27

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/LICENSE-MIT+21

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/Makefile+4

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/README.md+142

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/diff.go+177

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/export.go+16

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/lcs/common.go+179

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/lcs/doc.go+156

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/lcs/export.go+11

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/lcs/git.sh+33

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/lcs/labels.go+55

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/lcs/old.go+475

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/lcs/sequence.go+70

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/merge.go+81

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/ndiff.go+118

This diff is too big to show here.

vendor/github.com/aymanbagabas/go-udiff/unified.go+314

This diff is too big to show here.

vendor/github.com/aymerick/douceur/LICENSE+22

This diff is too big to show here.

vendor/github.com/aymerick/douceur/css/declaration.go+60

This diff is too big to show here.