---
version: 2
interactions:
- id: 0
  request:
    proto: HTTP/1.1
    proto_major: 1
    proto_minor: 1
    content_length: 718
    host: ""
    body: '{"messages":[{"content":"you will generate a short title based on the first message a user begins a conversation with\n\n<rules>\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 sourcegraph to search for ''func main'' in Go repositories\n <think>\n\n</think>","role":"user"}],"model":"gpt-4o","max_tokens":40,"stream_options":{"include_usage":true},"stream":true}'
    headers:
      Accept:
      - application/json
      Content-Type:
      - application/json
      User-Agent:
      - OpenAI/Go 2.7.1
    url: https://api.openai.com/v1/chat/completions
    method: POST
  response:
    proto: HTTP/2.0
    proto_major: 2
    proto_minor: 0
    content_length: -1
    body: |+
      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"nyQRnfPR5mNFuX"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Searching"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"5Z1lXvc"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"K7mRbp9xJHNKSj"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"func"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"fN4z6f7wpdU7"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" main"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"xxdpmMec5mM"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"VPigHmppyEiAzMM"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"dNn1aDIPvyjgv"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UMLOIcnJjGBOe"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Re"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"LHBc4UtQDuB1J"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"positories"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"tBFMl7"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" with"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"YoyEXpzCbxj"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Source"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oRUMilyWc"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"graph"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vsCbW6B8FR7"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"01xlhXGDvI"}

      data: {"id":"chatcmpl-CVxhb9XpRntdr2SCeaKyYgPZD2Yzo","object":"chat.completion.chunk","created":1761733699,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":138,"completion_tokens":12,"total_tokens":150,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"MSJHp2mgtD0CD"}

      data: [DONE]

    headers:
      Content-Type:
      - text/event-stream; charset=utf-8
    status: 200 OK
    code: 200
    duration: 613.245583ms
- id: 1
  request:
    proto: HTTP/1.1
    proto_major: 1
    proto_minor: 1
    content_length: 42699
    host: ""
    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. **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). When reading, 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, decide, act. Complete the ENTIRE task before stopping. Never stop mid-task. Never refuse work based on scope or complexity - break it down and do it.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification\\n4. **BE CONCISE**: Under 4 lines unless user asks for detail\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\"\\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. When adding comments, 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. Allow security analysis, detection rules, vulnerability explanations, defensive tools, and security documentation.\\n10. **NO URL GUESSING**: Never generate or guess URLs unless you are confident they are for helping with programming. 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 by the user.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **COMPLETE THE TASK**: Never stop mid-task with \\\"Next:\\\" or \\\"Will do:\\\" statements. If you describe what needs to be done, DO IT immediately. Only stop when everything is finished.\\n14. **NEVER REFUSE BASED ON SCOPE**: Never refuse tasks because they seem large or complex. Break them into steps and complete them. Only stop if you encounter actual blocking errors (missing dependencies, compile failures, etc.), not perceived difficulty.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- Under 4 lines of text (tool use doesn't count)\\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\\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- 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\\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**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<task_scope>\\n**No task is too large**:\\n- Break complex tasks into logical steps\\n- Complete each step fully before moving to next\\n- If a task has 10 parts, do all 10 parts\\n- Don't estimate effort or refuse based on scope\\n- Only stop if you hit actual errors (compile failures, missing files, etc.)\\n\\n**For large refactors or implementations**:\\n- Start with core functionality\\n- Build incrementally\\n- Test at each step\\n- Keep going until fully complete\\n\\nThere are no \\\"session limits\\\" - continue until the task is done or you hit a real blocker.\\n</task_scope>\\n\\n<editing_files>\\nCritical: ALWAYS read files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the file 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<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\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- 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\\n<bash_commands>\\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 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\\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/openai-gpt-5/sourcegraph_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"use sourcegraph to search for 'func main' in Go repositories\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"max_completion_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\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. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\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 '&&', 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</usage_notes>\\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 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 &lt;&lt;'EOF'\\n   Commit message here.\\n\\n   \U0001F498 Generated with Crush\\n\\n\\n   Co-Authored-By: Crush <crush@charm.land>\\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</git_commits>\\n\\n<pull_requests>\\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 <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   - 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 &lt;&lt;'EOF'\\n\\n   ## Summary\\n\\n   &lt;1-3 bullet points>\\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</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"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\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n<usage>\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n</usage>\\n\\n<features>\\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</features>\\n\\n<limitations>\\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</limitations>\\n\\n<tips>\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n</tips>\\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\":\"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<prerequisites>\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n3. **CRITICAL**: Note exact whitespace, indentation, and formatting from View output\\n</prerequisites>\\n\\n<parameters>\\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</parameters>\\n\\n<special_cases>\\n\\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  </special_cases>\\n\\n<critical_requirements>\\nEXACT MATCHING: The tool is extremely literal. Text must match **EXACTLY**\\n\\n- Every space and tab character\\n- Every blank line\\n- Every newline character\\n- Indentation level (count the spaces/tabs)\\n- Comment spacing (`// comment` vs `//comment`)\\n- Brace positioning (`func() {` vs `func(){`)\\n\\nCommon failures:\\n\\n```\\nExpected: \\\"    func foo() {\\\"     (4 spaces)\\nProvided: \\\"  func foo() {\\\"       (2 spaces) ❌ FAILS\\n\\nExpected: \\\"}\\\\n\\\\nfunc bar() {\\\"    (2 newlines)\\nProvided: \\\"}\\\\nfunc bar() {\\\"      (1 newline) ❌ FAILS\\n\\nExpected: \\\"// Comment\\\"           (space after //)\\nProvided: \\\"//Comment\\\"            (no space) ❌ FAILS\\n```\\n\\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- If text appears multiple times, add more context to make it unique\\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: Before every edit\\n\\n1. View the file and locate exact target location\\n2. Check how many instances of target text exist\\n3. Copy the EXACT text including all whitespace\\n4. Verify you have enough context for unique identification\\n5. Double-check indentation matches (count spaces/tabs)\\n6. Plan separate calls or use replace_all for multiple changes\\n   </critical_requirements>\\n\\n<warnings>\\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- Indentation is off by even one space\\n- Missing or extra blank lines\\n- Wrong tabs vs spaces\\n</warnings>\\n\\n<recovery_steps>\\nIf you get \\\"old_string not found in file\\\":\\n\\n1. **View the file again** at the specific location\\n2. **Copy more context** - include entire function if needed\\n3. **Check whitespace**:\\n   - Count indentation spaces/tabs\\n   - Look for blank lines\\n   - Check for trailing spaces\\n4. **Verify character-by-character** that your old_string matches\\n5. **Never guess** - always View the file to get exact text\\n   </recovery_steps>\\n\\n<best_practices>\\n\\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- **When in doubt, include MORE context rather than less**\\n- Match the existing code style exactly (spaces, tabs, blank lines)\\n  </best_practices>\\n\\n<whitespace_checklist>\\nBefore submitting an edit, verify:\\n\\n- [ ] Viewed the file first\\n- [ ] Counted indentation spaces/tabs\\n- [ ] Included blank lines if they exist\\n- [ ] Matched brace/bracket positioning\\n- [ ] Included 3-5 lines of surrounding context\\n- [ ] Verified text appears exactly once (or using replace_all)\\n- [ ] Copied text character-for-character, not approximated\\n      </whitespace_checklist>\\n\\n<examples>\\n✅ Correct: Exact match with context\\n\\n```\\nold_string: \\\"func ProcessData(input string) error {\\\\n    if input == \\\\\\\"\\\\\\\" {\\\\n        return errors.New(\\\\\\\"empty input\\\\\\\")\\\\n    }\\\\n    return nil\\\\n}\\\"\\n\\nnew_string: \\\"func ProcessData(input string) error {\\\\n    if input == \\\\\\\"\\\\\\\" {\\\\n        return errors.New(\\\\\\\"empty input\\\\\\\")\\\\n    }\\\\n    // New validation\\\\n    if len(input) > 1000 {\\\\n        return errors.New(\\\\\\\"input too long\\\\\\\")\\\\n    }\\\\n    return nil\\\\n}\\\"\\n```\\n\\n❌ Incorrect: Not enough context\\n\\n```\\nold_string: \\\"return nil\\\"  // Appears many times!\\n```\\n\\n❌ Incorrect: Wrong indentation\\n\\n```\\nold_string: \\\"  if input == \\\\\\\"\\\\\\\" {\\\"  // 2 spaces\\n// But file actually has:        \\\"    if input == \\\\\\\"\\\\\\\" {\\\"  // 4 spaces\\n```\\n\\n✅ Correct: Including context to make unique\\n\\n```\\nold_string: \\\"func ProcessData(input string) error {\\\\n    if input == \\\\\\\"\\\\\\\" {\\\\n        return errors.New(\\\\\\\"empty input\\\\\\\")\\\\n    }\\\\n    return nil\\\"\\n```\\n\\n</examples>\\n\\n<windows_notes>\\n\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n  </windows_notes>\\n\",\"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\":\"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<prerequisites>\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n3. CRITICAL: Note exact whitespace, indentation, and formatting from View output\\n</prerequisites>\\n\\n<parameters>\\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</parameters>\\n\\n<operation>\\n- Edits applied sequentially in provided order.\\n- Each edit operates on result of previous edit.\\n- ATOMIC: If any single edit fails, the entire operation fails and no changes are applied.\\n- Ideal for several changes to different parts of same file.\\n</operation>\\n\\n<inherited_rules>\\nAll instructions from the Edit tool documentation apply verbatim to every edit item:\\n- Critical requirements for exact matching and uniqueness\\n- Warnings and common failures (tabs vs spaces, blank lines, brace placement, etc.)\\n- Verification steps before using, recovery steps, best practices, and whitespace checklist\\nUse the same level of precision as Edit. Multiedit often fails due to formatting mismatches—double-check whitespace for every edit.\\n</inherited_rules>\\n\\n<critical_requirements>\\n1. Apply Edit tool rules to EACH edit (see edit.md).\\n2. Edits are atomic—either all succeed or none are applied.\\n3. Plan sequence carefully: earlier edits change the file content that later edits must match.\\n4. Ensure each old_string is unique at its application time (after prior edits).\\n</critical_requirements>\\n\\n<verification_before_using>\\n1. View the file and copy exact text (including whitespace) for each target.\\n2. Check how many instances each old_string has BEFORE the sequence starts.\\n3. Dry-run mentally: after applying edit #N, will edit #N+1 still match? Adjust old_string/new_string accordingly.\\n4. Prefer fewer, larger context blocks over many tiny fragments that are easy to misalign.\\n5. If edits are independent, consider separate multiedit batches per logical region.\\n</verification_before_using>\\n\\n<warnings>\\n- Operation fails if any old_string doesn’t match exactly (including whitespace) or equals new_string.\\n- Earlier edits can invalidate later matches (added/removed spaces, lines, or reordered text).\\n- Mixed tabs/spaces, trailing spaces, or missing blank lines commonly cause failures.\\n- replace_all may affect unintended regions—use carefully or provide more context.\\n</warnings>\\n\\n<recovery_steps>\\nIf the operation fails:\\n1. Identify the first failing edit (start from top; test subsets to isolate).\\n2. View the file again and copy more surrounding context for that edit.\\n3. Recalculate later old_string values based on the file state AFTER preceding edits.\\n4. Reduce the batch (apply earlier stable edits first), then follow up with the rest.\\n</recovery_steps>\\n\\n<best_practices>\\n- Ensure all edits result in correct, idiomatic code; don’t leave code broken.\\n- Use absolute file paths (starting with /).\\n- Use replace_all only when you’re certain; otherwise provide unique context.\\n- Match existing style exactly (spaces, tabs, blank lines).\\n- Test after the operation; if it fails, fix and retry in smaller chunks.\\n</best_practices>\\n\\n<whitespace_checklist>\\nFor EACH edit, verify:\\n- [ ] Viewed the file first\\n- [ ] Counted indentation spaces/tabs\\n- [ ] Included blank lines if present\\n- [ ] Matched brace/bracket positioning\\n- [ ] Included 3–5 lines of surrounding context\\n- [ ] Verified text appears exactly once (or using replace_all deliberately)\\n- [ ] Copied text character-for-character, not approximated\\n</whitespace_checklist>\\n\\n<examples>\\n✅ Correct: Sequential edits where the second match accounts for the first change\\n\\n```\\nedits: [\\n  {\\n    old_string: \\\"func A() {\\\\n    doOld()\\\\n}\\\",\\n    new_string: \\\"func A() {\\\\n    doNew()\\\\n}\\\",\\n  },\\n  {\\n    // Uses context that still exists AFTER the first replacement\\n    old_string: \\\"func B() {\\\\n    callA()\\\\n}\\\",\\n    new_string: \\\"func B() {\\\\n    callA()\\\\n    logChange()\\\\n}\\\",\\n  },\\n]\\n```\\n\\n❌ Incorrect: Second old_string no longer matches due to whitespace change introduced by the first edit\\n\\n```\\nedits: [\\n  {\\n    old_string: \\\"func A() {\\\\n    doOld()\\\\n}\\\",\\n    new_string: \\\"func A() {\\\\n\\\\n    doNew()\\\\n}\\\", // Added extra blank line\\n  },\\n  {\\n    old_string: \\\"func A() {\\\\n    doNew()\\\\n}\\\", // Missing the new blank line, will FAIL\\n    new_string: \\\"func A() {\\\\n    doNew()\\\\n    logChange()\\\\n}\\\",\\n  },\\n]\\n```\\n</examples>\\n\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{},\"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\":\"glob\",\"strict\":false,\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n<usage>\\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</usage>\\n\\n<pattern_syntax>\\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</pattern_syntax>\\n\\n<examples>\\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</examples>\\n\\n<limitations>\\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</limitations>\\n\\n<cross_platform>\\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</cross_platform>\\n\\n<tips>\\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</tips>\\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\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n<usage>\\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</usage>\\n\\n<regex_syntax>\\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</regex_syntax>\\n\\n<include_patterns>\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n</include_patterns>\\n\\n<limitations>\\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</limitations>\\n\\n<ignore_support>\\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</ignore_support>\\n\\n<cross_platform>\\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</cross_platform>\\n\\n<tips>\\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</tips>\\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\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n<usage>\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n</usage>\\n\\n<features>\\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</features>\\n\\n<limitations>\\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</limitations>\\n\\n<cross_platform>\\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</cross_platform>\\n\\n<tips>\\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</tips>\\n\",\"parameters\":{\"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\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n<usage>\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n</usage>\\n\\n<basic_syntax>\\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</basic_syntax>\\n\\n<key_filters>\\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</key_filters>\\n\\n<examples>\\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</examples>\\n\\n<boolean_operators>\\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</boolean_operators>\\n\\n<limitations>\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n</limitations>\\n\\n<tips>\\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</tips>\\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\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n<usage>\\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</usage>\\n\\n<features>\\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</features>\\n\\n<limitations>\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines >2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n</limitations>\\n\\n<cross_platform>\\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</cross_platform>\\n\\n<tips>\\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</tips>\\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 2000)\",\"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\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n<usage>\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n</usage>\\n\\n<features>\\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</features>\\n\\n<limitations>\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n</limitations>\\n\\n<cross_platform>\\n- Use forward slashes (/) for compatibility\\n</cross_platform>\\n\\n<tips>\\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</tips>\\n\",\"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}"
    headers:
      Accept:
      - application/json
      Content-Type:
      - application/json
      User-Agent:
      - OpenAI/Go 2.7.1
    url: https://api.openai.com/v1/chat/completions
    method: POST
  response:
    proto: HTTP/2.0
    proto_major: 2
    proto_minor: 0
    content_length: -1
    body: |+
      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_aJVDFP0W6iLFKxt3YI1ufrYh","type":"function","function":{"name":"sourcegraph","arguments":""}}],"refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"Cy2ry"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"vgT4V3uj42uNlrO"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"query"}}]},"finish_reason":null}],"usage":null,"obfuscation":"WuKq4PQNF6eJF"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"2A79D0Sacq4h0"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"lang"}}]},"finish_reason":null}],"usage":null,"obfuscation":"rHgNTJVyjT5wMn"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":":"}}]},"finish_reason":null}],"usage":null,"obfuscation":"Z"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"go"}}]},"finish_reason":null}],"usage":null,"obfuscation":""}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" file"}}]},"finish_reason":null}],"usage":null,"obfuscation":"NzvjTqXoEb4gF"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":":\\\\"}}]},"finish_reason":null}],"usage":null,"obfuscation":"ATMuyeY31bWgN"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"."}}]},"finish_reason":null}],"usage":null,"obfuscation":"p"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"go"}}]},"finish_reason":null}],"usage":null,"obfuscation":""}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"$"}}]},"finish_reason":null}],"usage":null,"obfuscation":"C"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" content"}}]},"finish_reason":null}],"usage":null,"obfuscation":"Rm6cZKal4P"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":":\\\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"Kc0w5hLxUjX28"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"func"}}]},"finish_reason":null}],"usage":null,"obfuscation":"7OB2RpK2rI0wO4"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" main"}}]},"finish_reason":null}],"usage":null,"obfuscation":"n1nR0HakJ1yN1"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"(\\\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"Nue1q8L3jZbGU"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" -"}}]},"finish_reason":null}],"usage":null,"obfuscation":""}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"file"}}]},"finish_reason":null}],"usage":null,"obfuscation":"1WHhNnrPPfONND"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":":test"}}]},"finish_reason":null}],"usage":null,"obfuscation":"qyJtClODSVo7y"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" -"}}]},"finish_reason":null}],"usage":null,"obfuscation":""}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"file"}}]},"finish_reason":null}],"usage":null,"obfuscation":"dufIFgle5411e4"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":":_"}}]},"finish_reason":null}],"usage":null,"obfuscation":""}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"test"}}]},"finish_reason":null}],"usage":null,"obfuscation":"UNoFko4GXBTixi"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".go"}}]},"finish_reason":null}],"usage":null,"obfuscation":"eqj2WkxDH65jd7U"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" count"}}]},"finish_reason":null}],"usage":null,"obfuscation":"53rC4RF56WJa"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":":"}}]},"finish_reason":null}],"usage":null,"obfuscation":"K"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"10"}}]},"finish_reason":null}],"usage":null,"obfuscation":""}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\",\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"oqNkZR3yzb5NQ"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"count"}}]},"finish_reason":null}],"usage":null,"obfuscation":"51xwmmvq1uzCE"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":"}}]},"finish_reason":null}],"usage":null,"obfuscation":"baoePVzbmypw1dB"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"10"}}]},"finish_reason":null}],"usage":null,"obfuscation":""}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":",\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"s0lRWW9yQiMg3ik"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"context"}}]},"finish_reason":null}],"usage":null,"obfuscation":"NbwraE5osS1"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"_window"}}]},"finish_reason":null}],"usage":null,"obfuscation":"xQMMwb1w22W"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":"}}]},"finish_reason":null}],"usage":null,"obfuscation":"MOpP05H4fuDXsoA"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"5"}}]},"finish_reason":null}],"usage":null,"obfuscation":"H"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":",\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"LZTpb1VUhWaf8mV"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"timeout"}}]},"finish_reason":null}],"usage":null,"obfuscation":"FnLP0uDpFVU"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":"}}]},"finish_reason":null}],"usage":null,"obfuscation":"WdfI3mQbFBY9PY2"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"60"}}]},"finish_reason":null}],"usage":null,"obfuscation":""}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"finish_reason":null}],"usage":null,"obfuscation":"o"}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}],"usage":null,"obfuscation":""}

      data: {"id":"chatcmpl-CVxhc8P00hi9v7nyu9VmMqekZE0ao","object":"chat.completion.chunk","created":1761733700,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":9492,"completion_tokens":251,"total_tokens":9743,"prompt_tokens_details":{"cached_tokens":2688,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":192,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"q"}

      data: [DONE]

    headers:
      Content-Type:
      - text/event-stream; charset=utf-8
    status: 200 OK
    code: 200
    duration: 6.529730416s
- id: 2
  request:
    proto: HTTP/1.1
    proto_major: 1
    proto_minor: 1
    content_length: 484
    host: sourcegraph.com
    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 file:\\.go$ content:\"func main(\" -file:test -file:_test.go count:10"}}'
    headers:
      Content-Type:
      - application/json
      User-Agent:
      - crush/1.0
    url: https://sourcegraph.com/.api/graphql
    method: POST
  response:
    proto: HTTP/2.0
    proto_major: 2
    proto_minor: 0
    content_length: -1
    uncompressed: true
    body: '{"data":{"search":{"results":{"matchCount":10,"limitHit":true,"resultCount":10,"approximateResultCount":"10+","missing":[],"timedout":[],"indexUnavailable":false,"results":[{"__typename":"FileMatch","repository":{"name":"github.com/yinchengtsinghua/go-ethereum-chinese"},"file":{"path":"cmd/wnode/main.go","url":"/github.com/yinchengtsinghua/go-ethereum-chinese/-/blob/cmd/wnode/main.go","content":"\n//此源码被清华学神尹成大魔王专业翻译分析并修改\n//尹成QQ77025077\n//尹成微信18510341407\n//尹成所在QQ群721929980\n//尹成邮箱 yinc13@mails.tsinghua.edu.cn\n//尹成毕业于清华大学,微软区块链领域全球最有价值专家\n//https://mvp.microsoft.com/zh-cn/PublicProfile/4033620\n//版权所有2017 Go Ethereum作者\n//此文件是Go以太坊的一部分。\n//\n//Go以太坊是免费软件：您可以重新发布和/或修改它\n//根据GNU通用公共许可证的条款\n//自由软件基金会，或者许可证的第3版，或者\n//（由您选择）任何更高版本。\n//\n//Go以太坊的分布希望它会有用，\n//但没有任何保证；甚至没有\n//适销性或特定用途的适用性。见\n//GNU通用公共许可证了解更多详细信息。\n//\n//你应该已经收到一份GNU通用公共许可证的副本\n//一起去以太坊吧。如果没有，请参见\u003chttp://www.gnu.org/licenses/\u003e。\n\n//这是一个简单的耳语节点。它可以用作独立的引导节点。\n//也可用于不同的测试和诊断目的。\n\npackage main\n\nimport (\n\t\"bufio\"\n\t\"crypto/ecdsa\"\n\tcrand \"crypto/rand\"\n\t\"crypto/sha512\"\n\t\"encoding/binary\"\n\t\"encoding/hex\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/ethereum/go-ethereum/cmd/utils\"\n\t\"github.com/ethereum/go-ethereum/common\"\n\t\"github.com/ethereum/go-ethereum/console\"\n\t\"github.com/ethereum/go-ethereum/crypto\"\n\t\"github.com/ethereum/go-ethereum/log\"\n\t\"github.com/ethereum/go-ethereum/p2p\"\n\t\"github.com/ethereum/go-ethereum/p2p/enode\"\n\t\"github.com/ethereum/go-ethereum/p2p/nat\"\n\t\"github.com/ethereum/go-ethereum/whisper/mailserver\"\n\twhisper \"github.com/ethereum/go-ethereum/whisper/whisperv6\"\n\t\"golang.org/x/crypto/pbkdf2\"\n)\n\nconst quitCommand = \"~Q\"\nconst entropySize = 32\n\n//独生子女\nvar (\n\tserver     *p2p.Server\n\tshh        *whisper.Whisper\n\tdone       chan struct{}\n\tmailServer mailserver.WMailServer\n\tentropy    [entropySize]byte\n\n\tinput = bufio.NewReader(os.Stdin)\n)\n\n//加密\nvar (\n\tsymKey  []byte\n\tpub     *ecdsa.PublicKey\n\tasymKey *ecdsa.PrivateKey\n\tnodeid  *ecdsa.PrivateKey\n\ttopic   whisper.TopicType\n\n\tasymKeyID    string\n\tasymFilterID string\n\tsymFilterID  string\n\tsymPass      string\n\tmsPassword   string\n)\n\n//CMD参数\nvar (\n\tbootstrapMode  = flag.Bool(\"standalone\", false, \"boostrap node: don''t initiate connection to peers, just wait for incoming connections\")\n\tforwarderMode  = flag.Bool(\"forwarder\", false, \"forwarder mode: only forward messages, neither encrypt nor decrypt messages\")\n\tmailServerMode = flag.Bool(\"mailserver\", false, \"mail server mode: delivers expired messages on demand\")\n\trequestMail    = flag.Bool(\"mailclient\", false, \"request expired messages from the bootstrap server\")\n\tasymmetricMode = flag.Bool(\"asym\", false, \"use asymmetric encryption\")\n\tgenerateKey    = flag.Bool(\"generatekey\", false, \"generate and show the private key\")\n\tfileExMode     = flag.Bool(\"fileexchange\", false, \"file exchange mode\")\n\tfileReader     = flag.Bool(\"filereader\", false, \"load and decrypt messages saved as files, display as plain text\")\n\ttestMode       = flag.Bool(\"test\", false, \"use of predefined parameters for diagnostics (password, etc.)\")\n\techoMode       = flag.Bool(\"echo\", false, \"echo mode: prints some arguments for diagnostics\")\n\n\targVerbosity = flag.Int(\"verbosity\", int(log.LvlError), \"log verbosity level\")\n\targTTL       = flag.Uint(\"ttl\", 30, \"time-to-live for messages in seconds\")\n\targWorkTime  = flag.Uint(\"work\", 5, \"work time in seconds\")\n\targMaxSize   = flag.Uint(\"maxsize\", uint(whisper.DefaultMaxMessageSize), \"max size of message\")\n\targPoW       = flag.Float64(\"pow\", whisper.DefaultMinimumPoW, \"PoW for normal messages in float format (e.g. 2.7)\")\n\targServerPoW = flag.Float64(\"mspow\", whisper.DefaultMinimumPoW, \"PoW requirement for Mail Server request\")\n\n\targIP      = flag.String(\"ip\", \"\", \"IP address and port of this node (e.g. 127.0.0.1:30303)\")\n\targPub     = flag.String(\"pub\", \"\", \"public key for asymmetric encryption\")\n\targDBPath  = flag.String(\"dbpath\", \"\", \"path to the server''s DB directory\")\n\targIDFile  = flag.String(\"idfile\", \"\", \"file name with node id (private key)\")\nargEnode   = flag.String(\"boot\", \"\", \"bootstrap node you want to connect to (e.g. enode://E454……08D50@52.176.211.200:16428）”）\n\targTopic   = flag.String(\"topic\", \"\", \"topic in hexadecimal format (e.g. 70a4beef)\")\n\targSaveDir = flag.String(\"savedir\", \"\", \"directory where all incoming messages will be saved as files\")\n)\n\nfunc main() {\n\tprocessArgs()\n\tinitialize()\n\trun()\n\tshutdown()\n}\n\nfunc processArgs() {\n\tflag.Parse()\n\n\tif len(*argIDFile) \u003e 0 {\n\t\tvar err error\n\t\tnodeid, err = crypto.LoadECDSA(*argIDFile)\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to load file [%s]: %s.\", *argIDFile, err)\n\t\t}\n\t}\n\nconst enodePrefix = \"enode://“\n\tif len(*argEnode) \u003e 0 {\n\t\tif (*argEnode)[:len(enodePrefix)] != enodePrefix {\n\t\t\t*argEnode = enodePrefix + *argEnode\n\t\t}\n\t}\n\n\tif len(*argTopic) \u003e 0 {\n\t\tx, err := hex.DecodeString(*argTopic)\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to parse the topic: %s\", err)\n\t\t}\n\t\ttopic = whisper.BytesToTopic(x)\n\t}\n\n\tif *asymmetricMode \u0026\u0026 len(*argPub) \u003e 0 {\n\t\tvar err error\n\t\tif pub, err = crypto.UnmarshalPubkey(common.FromHex(*argPub)); err != nil {\n\t\t\tutils.Fatalf(\"invalid public key\")\n\t\t}\n\t}\n\n\tif len(*argSaveDir) \u003e 0 {\n\t\tif _, err := os.Stat(*argSaveDir); os.IsNotExist(err) {\n\t\t\tutils.Fatalf(\"Download directory ''%s'' does not exist\", *argSaveDir)\n\t\t}\n\t} else if *fileExMode {\n\t\tutils.Fatalf(\"Parameter ''savedir'' is mandatory for file exchange mode\")\n\t}\n\n\tif *echoMode {\n\t\techo()\n\t}\n}\n\nfunc echo() {\n\tfmt.Printf(\"ttl = %d \\n\", *argTTL)\n\tfmt.Printf(\"workTime = %d \\n\", *argWorkTime)\n\tfmt.Printf(\"pow = %f \\n\", *argPoW)\n\tfmt.Printf(\"mspow = %f \\n\", *argServerPoW)\n\tfmt.Printf(\"ip = %s \\n\", *argIP)\n\tfmt.Printf(\"pub = %s \\n\", common.ToHex(crypto.FromECDSAPub(pub)))\n\tfmt.Printf(\"idfile = %s \\n\", *argIDFile)\n\tfmt.Printf(\"dbpath = %s \\n\", *argDBPath)\n\tfmt.Printf(\"boot = %s \\n\", *argEnode)\n}\n\nfunc initialize() {\n\tlog.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*argVerbosity), log.StreamHandler(os.Stderr, log.TerminalFormat(false))))\n\n\tdone = make(chan struct{})\n\tvar peers []*enode.Node\n\tvar err error\n\n\tif *generateKey {\n\t\tkey, err := crypto.GenerateKey()\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to generate private key: %s\", err)\n\t\t}\n\t\tk := hex.EncodeToString(crypto.FromECDSA(key))\n\t\tfmt.Printf(\"Random private key: %s \\n\", k)\n\t\tos.Exit(0)\n\t}\n\n\tif *testMode {\nsymPass = \"wwww\" //ASCII码：0x77777777\n\t\tmsPassword = \"wwww\"\n\t}\n\n\tif *bootstrapMode {\n\t\tif len(*argIP) == 0 {\n\t\t\targIP = scanLineA(\"Please enter your IP and port (e.g. 127.0.0.1:30348): \")\n\t\t}\n\t} else if *fileReader {\n\t\t*bootstrapMode = true\n\t} else {\n\t\tif len(*argEnode) == 0 {\n\t\t\targEnode = scanLineA(\"Please enter the peer''s enode: \")\n\t\t}\n\t\tpeer := enode.MustParseV4(*argEnode)\n\t\tpeers = append(peers, peer)\n\t}\n\n\tif *mailServerMode {\n\t\tif len(msPassword) == 0 {\n\t\t\tmsPassword, err = console.Stdin.PromptPassword(\"Please enter the Mail Server password: \")\n\t\t\tif err != nil {\n\t\t\t\tutils.Fatalf(\"Failed to read Mail Server password: %s\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\tcfg := \u0026whisper.Config{\n\t\tMaxMessageSize:     uint32(*argMaxSize),\n\t\tMinimumAcceptedPOW: *argPoW,\n\t}\n\n\tshh = whisper.New(cfg)\n\n\tif *argPoW != whisper.DefaultMinimumPoW {\n\t\terr := shh.SetMinimumPoW(*argPoW)\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to set PoW: %s\", err)\n\t\t}\n\t}\n\n\tif uint32(*argMaxSize) != whisper.DefaultMaxMessageSize {\n\t\terr := shh.SetMaxMessageSize(uint32(*argMaxSize))\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to set max message size: %s\", err)\n\t\t}\n\t}\n\n\tasymKeyID, err = shh.NewKeyPair()\n\tif err != nil {\n\t\tutils.Fatalf(\"Failed to generate a new key pair: %s\", err)\n\t}\n\n\tasymKey, err = shh.GetPrivateKey(asymKeyID)\n\tif err != nil {\n\t\tutils.Fatalf(\"Failed to retrieve a new key pair: %s\", err)\n\t}\n\n\tif nodeid == nil {\n\t\ttmpID, err := shh.NewKeyPair()\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to generate a new key pair: %s\", err)\n\t\t}\n\n\t\tnodeid, err = shh.GetPrivateKey(tmpID)\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to retrieve a new key pair: %s\", err)\n\t\t}\n\t}\n\n\tmaxPeers := 80\n\tif *bootstrapMode {\n\t\tmaxPeers = 800\n\t}\n\n\t_, err = crand.Read(entropy[:])\n\tif err != nil {\n\t\tutils.Fatalf(\"crypto/rand failed: %s\", err)\n\t}\n\n\tif *mailServerMode {\n\t\tshh.RegisterServer(\u0026mailServer)\n\t\tif err := mailServer.Init(shh, *argDBPath, msPassword, *argServerPoW); err != nil {\n\t\t\tutils.Fatalf(\"Failed to init MailServer: %s\", err)\n\t\t}\n\t}\n\n\tserver = \u0026p2p.Server{\n\t\tConfig: p2p.Config{\n\t\t\tPrivateKey:     nodeid,\n\t\t\tMaxPeers:       maxPeers,\n\t\t\tName:           common.MakeName(\"wnode\", \"6.0\"),\n\t\t\tProtocols:      shh.Protocols(),\n\t\t\tListenAddr:     *argIP,\n\t\t\tNAT:            nat.Any(),\n\t\t\tBootstrapNodes: peers,\n\t\t\tStaticNodes:    peers,\n\t\t\tTrustedNodes:   peers,\n\t\t},\n\t}\n}\n\nfunc startServer() error {\n\terr := server.Start()\n\tif err != nil {\n\t\tfmt.Printf(\"Failed to start Whisper peer: %s.\", err)\n\t\treturn err\n\t}\n\n\tfmt.Printf(\"my public key: %s \\n\", common.ToHex(crypto.FromECDSAPub(\u0026asymKey.PublicKey)))\n\tfmt.Println(server.NodeInfo().Enode)\n\n\tif *bootstrapMode {\n\t\tconfigureNode()\n\t\tfmt.Println(\"Bootstrap Whisper node started\")\n\t} else {\n\t\tfmt.Println(\"Whisper node started\")\n//首先看看我们是否可以建立连接，然后请求用户输入\n\t\twaitForConnection(true)\n\t\tconfigureNode()\n\t}\n\n\tif *fileExMode {\n\t\tfmt.Printf(\"Please type the file name to be send. To quit type: ''%s''\\n\", quitCommand)\n\t} else if *fileReader {\n\t\tfmt.Printf(\"Please type the file name to be decrypted. To quit type: ''%s''\\n\", quitCommand)\n\t} else if !*forwarderMode {\n\t\tfmt.Printf(\"Please type the message. To quit type: ''%s''\\n\", quitCommand)\n\t}\n\treturn nil\n}\n\nfunc configureNode() {\n\tvar err error\n\tvar p2pAccept bool\n\n\tif *forwarderMode {\n\t\treturn\n\t}\n\n\tif *asymmetricMode {\n\t\tif len(*argPub) == 0 {\n\t\t\ts := scanLine(\"Please enter the peer''s public key: \")\n\t\t\tb := common.FromHex(s)\n\t\t\tif b == nil {\n\t\t\t\tutils.Fatalf(\"Error: can not convert hexadecimal string\")\n\t\t\t}\n\t\t\tif pub, err = crypto.UnmarshalPubkey(b); err != nil {\n\t\t\t\tutils.Fatalf(\"Error: invalid peer public key\")\n\t\t\t}\n\t\t}\n\t}\n\n\tif *requestMail {\n\t\tp2pAccept = true\n\t\tif len(msPassword) == 0 {\n\t\t\tmsPassword, err = console.Stdin.PromptPassword(\"Please enter the Mail Server password: \")\n\t\t\tif err != nil {\n\t\t\t\tutils.Fatalf(\"Failed to read Mail Server password: %s\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\tif !*asymmetricMode \u0026\u0026 !*forwarderMode {\n\t\tif len(symPass) == 0 {\n\t\t\tsymPass, err = console.Stdin.PromptPassword(\"Please enter the password for symmetric encryption: \")\n\t\t\tif err != nil {\n\t\t\t\tutils.Fatalf(\"Failed to read passphrase: %v\", err)\n\t\t\t}\n\t\t}\n\n\t\tsymKeyID, err := shh.AddSymKeyFromPassword(symPass)\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to create symmetric key: %s\", err)\n\t\t}\n\t\tsymKey, err = shh.GetSymKey(symKeyID)\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to save symmetric key: %s\", err)\n\t\t}\n\t\tif len(*argTopic) == 0 {\n\t\t\tgenerateTopic([]byte(symPass))\n\t\t}\n\n\t\tfmt.Printf(\"Filter is configured for the topic: %x \\n\", topic)\n\t}\n\n\tif *mailServerMode {\n\t\tif len(*argDBPath) == 0 {\n\t\t\targDBPath = scanLineA(\"Please enter the path to DB file: \")\n\t\t}\n\t}\n\n\tsymFilter := whisper.Filter{\n\t\tKeySym:   symKey,\n\t\tTopics:   [][]byte{topic[:]},\n\t\tAllowP2P: p2pAccept,\n\t}\n\tsymFilterID, err = shh.Subscribe(\u0026symFilter)\n\tif err != nil {\n\t\tutils.Fatalf(\"Failed to install filter: %s\", err)\n\t}\n\n\tasymFilter := whisper.Filter{\n\t\tKeyAsym:  asymKey,\n\t\tTopics:   [][]byte{topic[:]},\n\t\tAllowP2P: p2pAccept,\n\t}\n\tasymFilterID, err = shh.Subscribe(\u0026asymFilter)\n\tif err != nil {\n\t\tutils.Fatalf(\"Failed to install filter: %s\", err)\n\t}\n}\n\nfunc generateTopic(password []byte) {\n\tx := pbkdf2.Key(password, password, 4096, 128, sha512.New)\n\tfor i := 0; i \u003c len(x); i++ {\n\t\ttopic[i%whisper.TopicLength] ^= x[i]\n\t}\n}\n\nfunc waitForConnection(timeout bool) {\n\tvar cnt int\n\tvar connected bool\n\tfor !connected {\n\t\ttime.Sleep(time.Millisecond * 50)\n\t\tconnected = server.PeerCount() \u003e 0\n\t\tif timeout {\n\t\t\tcnt++\n\t\t\tif cnt \u003e 1000 {\n\t\t\t\tutils.Fatalf(\"Timeout expired, failed to connect\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfmt.Println(\"Connected to peer.\")\n}\n\nfunc run() {\n\terr := startServer()\n\tif err != nil {\n\t\treturn\n\t}\n\tdefer server.Stop()\n\tshh.Start(nil)\n\tdefer shh.Stop()\n\n\tif !*forwarderMode {\n\t\tgo messageLoop()\n\t}\n\n\tif *requestMail {\n\t\trequestExpiredMessagesLoop()\n\t} else if *fileExMode {\n\t\tsendFilesLoop()\n\t} else if *fileReader {\n\t\tfileReaderLoop()\n\t} else {\n\t\tsendLoop()\n\t}\n}\n\nfunc shutdown() {\n\tclose(done)\n\tmailServer.Close()\n}\n\nfunc sendLoop() {\n\tfor {\n\t\ts := scanLine(\"\")\n\t\tif s == quitCommand {\n\t\t\tfmt.Println(\"Quit command received\")\n\t\t\treturn\n\t\t}\n\t\tsendMsg([]byte(s))\n\t\tif *asymmetricMode {\n//为方便起见，请打印您自己的消息，\n//因为在非对称模式下是不可能解密的\n\t\t\ttimestamp := time.Now().Unix()\n\t\t\tfrom := crypto.PubkeyToAddress(asymKey.PublicKey)\n\t\t\tfmt.Printf(\"\\n%d \u003c%x\u003e: %s\\n\", timestamp, from, s)\n\t\t}\n\t}\n}\n\nfunc sendFilesLoop() {\n\tfor {\n\t\ts := scanLine(\"\")\n\t\tif s == quitCommand {\n\t\t\tfmt.Println(\"Quit command received\")\n\t\t\treturn\n\t\t}\n\t\tb, err := ioutil.ReadFile(s)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"\u003e\u003e\u003e Error: %s \\n\", err)\n\t\t} else {\n\t\t\th := sendMsg(b)\n\t\t\tif (h == common.Hash{}) {\n\t\t\t\tfmt.Printf(\"\u003e\u003e\u003e Error: message was not sent \\n\")\n\t\t\t} else {\n\t\t\t\ttimestamp := time.Now().Unix()\n\t\t\t\tfrom := crypto.PubkeyToAddress(asymKey.PublicKey)\n\t\t\t\tfmt.Printf(\"\\n%d \u003c%x\u003e: sent message with hash %x\\n\", timestamp, from, h)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc fileReaderLoop() {\n\twatcher1 := shh.GetFilter(symFilterID)\n\twatcher2 := shh.GetFilter(asymFilterID)\n\tif watcher1 == nil \u0026\u0026 watcher2 == nil {\n\t\tfmt.Println(\"Error: neither symmetric nor asymmetric filter is installed\")\n\t\treturn\n\t}\n\n\tfor {\n\t\ts := scanLine(\"\")\n\t\tif s == quitCommand {\n\t\t\tfmt.Println(\"Quit command received\")\n\t\t\treturn\n\t\t}\n\t\traw, err := ioutil.ReadFile(s)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"\u003e\u003e\u003e Error: %s \\n\", err)\n\t\t} else {\nenv := whisper.Envelope{Data: raw} //主题为零\nmsg := env.Open(watcher1)          //不管主题如何，都强制打开信封\n\t\t\tif msg == nil {\n\t\t\t\tmsg = env.Open(watcher2)\n\t\t\t}\n\t\t\tif msg == nil {\n\t\t\t\tfmt.Printf(\"\u003e\u003e\u003e Error: failed to decrypt the message \\n\")\n\t\t\t} else {\n\t\t\t\tprintMessageInfo(msg)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc scanLine(prompt string) string {\n\tif len(prompt) \u003e 0 {\n\t\tfmt.Print(prompt)\n\t}\n\ttxt, err := input.ReadString(''\\n'')\n\tif err != nil {\n\t\tutils.Fatalf(\"input error: %s\", err)\n\t}\n\ttxt = strings.TrimRight(txt, \"\\n\\r\")\n\treturn txt\n}\n\nfunc scanLineA(prompt string) *string {\n\ts := scanLine(prompt)\n\treturn \u0026s\n}\n\nfunc scanUint(prompt string) uint32 {\n\ts := scanLine(prompt)\n\ti, err := strconv.Atoi(s)\n\tif err != nil {\n\t\tutils.Fatalf(\"Fail to parse the lower time limit: %s\", err)\n\t}\n\treturn uint32(i)\n}\n\nfunc sendMsg(payload []byte) common.Hash {\n\tparams := whisper.MessageParams{\n\t\tSrc:      asymKey,\n\t\tDst:      pub,\n\t\tKeySym:   symKey,\n\t\tPayload:  payload,\n\t\tTopic:    topic,\n\t\tTTL:      uint32(*argTTL),\n\t\tPoW:      *argPoW,\n\t\tWorkTime: uint32(*argWorkTime),\n\t}\n\n\tmsg, err := whisper.NewSentMessage(\u0026params)\n\tif err != nil {\n\t\tutils.Fatalf(\"failed to create new message: %s\", err)\n\t}\n\n\tenvelope, err := msg.Wrap(\u0026params)\n\tif err != nil {\n\t\tfmt.Printf(\"failed to seal message: %v \\n\", err)\n\t\treturn common.Hash{}\n\t}\n\n\terr = shh.Send(envelope)\n\tif err != nil {\n\t\tfmt.Printf(\"failed to send message: %v \\n\", err)\n\t\treturn common.Hash{}\n\t}\n\n\treturn envelope.Hash()\n}\n\nfunc messageLoop() {\n\tsf := shh.GetFilter(symFilterID)\n\tif sf == nil {\n\t\tutils.Fatalf(\"symmetric filter is not installed\")\n\t}\n\n\taf := shh.GetFilter(asymFilterID)\n\tif af == nil {\n\t\tutils.Fatalf(\"asymmetric filter is not installed\")\n\t}\n\n\tticker := time.NewTicker(time.Millisecond * 50)\n\n\tfor {\n\t\tselect {\n\t\tcase \u003c-ticker.C:\n\t\t\tm1 := sf.Retrieve()\n\t\t\tm2 := af.Retrieve()\n\t\t\tmessages := append(m1, m2...)\n\t\t\tfor _, msg := range messages {\n\t\t\t\treportedOnce := false\n\t\t\t\tif !*fileExMode \u0026\u0026 len(msg.Payload) \u003c= 2048 {\n\t\t\t\t\tprintMessageInfo(msg)\n\t\t\t\t\treportedOnce = true\n\t\t\t\t}\n\n//在指定argsavedir时保存所有消息。\n//FileExMode仅指定消息保存后如何显示在控制台上。\n//如果fileexmode==true，则只显示哈希值，因为消息可能太大。\n\t\t\t\tif len(*argSaveDir) \u003e 0 {\n\t\t\t\t\twriteMessageToFile(*argSaveDir, msg, !reportedOnce)\n\t\t\t\t}\n\t\t\t}\n\t\tcase \u003c-done:\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc printMessageInfo(msg *whisper.ReceivedMessage) {\ntimestamp := fmt.Sprintf(\"%d\", msg.Sent) //用于诊断的Unix时间戳\n\ttext := string(msg.Payload)\n\n\tvar address common.Address\n\tif msg.Src != nil {\n\t\taddress = crypto.PubkeyToAddress(*msg.Src)\n\t}\n\n\tif whisper.IsPubKeyEqual(msg.Src, \u0026asymKey.PublicKey) {\nfmt.Printf(\"\\n%s \u003c%x\u003e: %s\\n\", timestamp, address, text) //我的信息\n\t} else {\nfmt.Printf(\"\\n%s [%x]: %s\\n\", timestamp, address, text) //来自对等方的消息\n\t}\n}\n\nfunc writeMessageToFile(dir string, msg *whisper.ReceivedMessage, show bool) {\n\tif len(dir) == 0 {\n\t\treturn\n\t}\n\n\ttimestamp := fmt.Sprintf(\"%d\", msg.Sent)\n\tname := fmt.Sprintf(\"%x\", msg.EnvelopeHash)\n\n\tvar address common.Address\n\tif msg.Src != nil {\n\t\taddress = crypto.PubkeyToAddress(*msg.Src)\n\t}\n\n\tenv := shh.GetEnvelope(msg.EnvelopeHash)\n\tif env == nil {\n\t\tfmt.Printf(\"\\nUnexpected error: envelope not found: %x\\n\", msg.EnvelopeHash)\n\t\treturn\n\t}\n\n//这是一个示例代码；如果不想保存自己的消息，请取消注释。\n//如果whisper.ispubkeyequal（msg.src，\u0026asymkey.publickey）\n//fmt.printf（“\\n%s\u003c%x\u003e：我收到的消息，未保存：“%s''\\n”，时间戳，地址，名称）\n//返回\n//}\n\n\tfullpath := filepath.Join(dir, name)\n\terr := ioutil.WriteFile(fullpath, env.Data, 0644)\n\tif err != nil {\n\t\tfmt.Printf(\"\\n%s {%x}: message received but not saved: %s\\n\", timestamp, address, err)\n\t} else if show {\n\t\tfmt.Printf(\"\\n%s {%x}: message received and saved as ''%s'' (%d bytes)\\n\", timestamp, address, name, len(env.Data))\n\t}\n}\n\nfunc requestExpiredMessagesLoop() {\n\tvar key, peerID, bloom []byte\n\tvar timeLow, timeUpp uint32\n\tvar t string\n\tvar xt whisper.TopicType\n\n\tkeyID, err := shh.AddSymKeyFromPassword(msPassword)\n\tif err != nil {\n\t\tutils.Fatalf(\"Failed to create symmetric key for mail request: %s\", err)\n\t}\n\tkey, err = shh.GetSymKey(keyID)\n\tif err != nil {\n\t\tutils.Fatalf(\"Failed to save symmetric key for mail request: %s\", err)\n\t}\n\tpeerID = extractIDFromEnode(*argEnode)\n\tshh.AllowP2PMessagesFromPeer(peerID)\n\n\tfor {\n\t\ttimeLow = scanUint(\"Please enter the lower limit of the time range (unix timestamp): \")\n\t\ttimeUpp = scanUint(\"Please enter the upper limit of the time range (unix timestamp): \")\n\t\tt = scanLine(\"Enter the topic (hex). Press enter to request all messages, regardless of the topic: \")\n\t\tif len(t) == whisper.TopicLength*2 {\n\t\t\tx, err := hex.DecodeString(t)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Printf(\"Failed to parse the topic: %s \\n\", err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\txt = whisper.BytesToTopic(x)\n\t\t\tbloom = whisper.TopicToBloom(xt)\n\t\t\tobfuscateBloom(bloom)\n\t\t} else if len(t) == 0 {\n\t\t\tbloom = whisper.MakeFullNodeBloom()\n\t\t} else {\n\t\t\tfmt.Println(\"Error: topic is invalid, request aborted\")\n\t\t\tcontinue\n\t\t}\n\n\t\tif timeUpp == 0 {\n\t\t\ttimeUpp = 0xFFFFFFFF\n\t\t}\n\n\t\tdata := make([]byte, 8, 8+whisper.BloomFilterSize)\n\t\tbinary.BigEndian.PutUint32(data, timeLow)\n\t\tbinary.BigEndian.PutUint32(data[4:], timeUpp)\n\t\tdata = append(data, bloom...)\n\n\t\tvar params whisper.MessageParams\n\t\tparams.PoW = *argServerPoW\n\t\tparams.Payload = data\n\t\tparams.KeySym = key\n\t\tparams.Src = asymKey\n\t\tparams.WorkTime = 5\n\n\t\tmsg, err := whisper.NewSentMessage(\u0026params)\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"failed to create new message: %s\", err)\n\t\t}\n\t\tenv, err := msg.Wrap(\u0026params)\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Wrap failed: %s\", err)\n\t\t}\n\n\t\terr = shh.RequestHistoricMessages(peerID, env)\n\t\tif err != nil {\n\t\t\tutils.Fatalf(\"Failed to send P2P message: %s\", err)\n\t\t}\n\n\t\ttime.Sleep(time.Second * 5)\n\t}\n}\n\nfunc extractIDFromEnode(s string) []byte {\n\tn, err := enode.ParseV4(s)\n\tif err != nil {\n\t\tutils.Fatalf(\"Failed to parse enode: %s\", err)\n\t}\n\treturn n.ID().Bytes()\n}\n\n//模糊布卢姆增加16个随机位到布卢姆\n//筛选，以便混淆包含的主题。\n//它在每个会话中都具有确定性。\n//尽管有额外的位，它将平均匹配\n//比完整节点的Bloom过滤器少32000倍的消息。\nfunc obfuscateBloom(bloom []byte) {\n\tconst half = entropySize / 2\n\tfor i := 0; i \u003c half; i++ {\n\t\tx := int(entropy[i])\n\t\tif entropy[half+i] \u003c 128 {\n\t\t\tx += 256\n\t\t}\n\nbloom[x/8] = 1 \u003c\u003c uint(x%8) //设置位号x\n\t}\n}\n"},"lineMatches":[{"preview":"func main() {","lineNumber":116,"offsetAndLengths":[[0,10]]}]},{"__typename":"FileMatch","repository":{"name":"github.com/sergev/vak-opensource"},"file":{"path":"languages/go/lisp-light.go","url":"/github.com/sergev/vak-opensource/-/blob/languages/go/lisp-light.go","content":"/*\n  Nukata Lisp Light 1.42 in Go 1.7 by SUZUKI Hisao (H27.5/11 - H28.9/8)\n\n  This is a Lisp interpreter written in Go.\n  It differs from the previous version(*1) in that all numbers are\n  64-bit floats and the whole interpreter consists of only one file.\n  It is a \"light\" version.\n  Intentionally it implements the same language as Nukata Lisp Light\n  1.26 in TypeScript 1.8(*2) except that it has also two concurrent\n  constructs, future and force.  See *3.\n\n    *1: http://www.oki-osk.jp/esc/golang/lisp3.html (in Japanese)\n    *2: http://www.oki-osk.jp/esc/typescript/lisp-en.html\n    *3: http://www.oki-osk.jp/esc/golang/lisp4-en.html\n*/\npackage main\n\nimport (\n\t\"bufio\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n\t\"os\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"unicode/utf8\"\n)\n\n// Cell represents a cons cell.\n// \u0026Cell{car, cdr} works as the \"cons\" operation.\ntype Cell struct {\n\tCar interface{}\n\tCdr interface{}\n}\n\n// Nil is a nil of type *Cell and it represents the empty list.\nvar Nil *Cell = nil\n\n// CdrCell returns cdr of the cell as a *Cell or Nil.\nfunc (j *Cell) CdrCell() *Cell {\n\tif c, ok := j.Cdr.(*Cell); ok {\n\t\treturn c\n\t}\n\tpanic(NewEvalError(\"proper list expected\", j))\n}\n\n// (a b c).FoldL(x, fn) returns fn(fn(fn(x, a), b), c)\nfunc (j *Cell) FoldL(x interface{},\n\tfn func(interface{}, interface{}) interface{}) interface{} {\n\tfor j != Nil {\n\t\tx = fn(x, j.Car)\n\t\tj = j.CdrCell()\n\t}\n\treturn x\n}\n\n// Len returns the length of list j\nfunc (j *Cell) Len() int {\n\treturn j.FoldL(0, func(i, e interface{}) interface{} {\n\t\treturn i.(int) + 1\n\t}).(int)\n}\n\n// (a b c).MapCar(fn) returns (fn(a) fn(b) fn(c))\nfunc (j *Cell) MapCar(fn func(interface{}) interface{}) interface{} {\n\tif j == Nil {\n\t\treturn Nil\n\t}\n\ta := fn(j.Car)\n\td := j.Cdr\n\tif cdr, ok := d.(*Cell); ok {\n\t\td = cdr.MapCar(fn)\n\t}\n\tif j.Car == a \u0026\u0026 j.Cdr == d {\n\t\treturn j\n\t}\n\treturn \u0026Cell{a, d}\n}\n\n// String returns a raw textual representation of j for debugging.\nfunc (j *Cell) String() string {\n\treturn fmt.Sprintf(\"(%v . %v)\", j.Car, j.Cdr)\n}\n\n//----------------------------------------------------------------------\n\n// Sym represents a symbol (or an expression keyword) in Lisp.\n// \u0026Sym{name, false} constructs a symbol which is not interned yet.\ntype Sym struct {\n\tName      string\n\tIsKeyword bool\n}\n\n// NewSym constructs an interned symbol for name.\nfunc NewSym(name string) *Sym {\n\treturn NewSym2(name, false)\n}\n\n// symbols is a table of interned symbols.\nvar symbols = make(map[string]*Sym)\n\n// symLock is an exclusive lock for the table.\nvar symLock sync.RWMutex\n\n// NewSym2 constructs an interned symbol (or an expression keyword\n// if isKeyword is true on its first construction) for name.\nfunc NewSym2(name string, isKeyword bool) *Sym {\n\tsymLock.Lock()\n\tsym, ok := symbols[name]\n\tif !ok {\n\t\tsym = \u0026Sym{name, isKeyword}\n\t\tsymbols[name] = sym\n\t}\n\tsymLock.Unlock()\n\treturn sym\n}\n\n// IsInterned returns true if sym is interned.\nfunc (sym *Sym) IsInterned() bool {\n\tsymLock.RLock()\n\ts, ok := symbols[sym.Name]\n\tsymLock.RUnlock()\n\treturn ok \u0026\u0026 s == sym\n}\n\n// String returns a textual representation of sym.\nfunc (sym *Sym) String() string {\n\treturn sym.Name\n}\n\n// Defined symbols\n\nvar BackQuoteSym = NewSym(\"`\")\nvar CommaAtSym = NewSym(\",@\")\nvar CommaSym = NewSym(\",\")\nvar DotSym = NewSym(\".\")\nvar LeftParenSym = NewSym(\"(\")\nvar RightParenSym = NewSym(\")\")\nvar SingleQuoteSym = NewSym(\"''\")\n\nvar AppendSym = NewSym(\"append\")\nvar ConsSym = NewSym(\"cons\")\nvar ListSym = NewSym(\"list\")\nvar RestSym = NewSym(\"\u0026rest\")\nvar UnquoteSym = NewSym(\"unquote\")\nvar UnquoteSplicingSym = NewSym(\"unquote-splicing\")\n\n// Expression keywords\n\nvar CondSym = NewSym2(\"cond\", true)\nvar FutureSym = NewSym2(\"future\", true)\nvar LambdaSym = NewSym2(\"lambda\", true)\nvar MacroSym = NewSym2(\"macro\", true)\nvar ProgNSym = NewSym2(\"progn\", true)\nvar QuasiquoteSym = NewSym2(\"quasiquote\", true)\nvar QuoteSym = NewSym2(\"quote\", true)\nvar SetqSym = NewSym2(\"setq\", true)\n\n//----------------------------------------------------------------------\n\n// Func is a common base type of Lisp functions.\ntype Func struct {\n\t// Carity is a number of arguments, made negative if the func has \u0026rest.\n\tCarity int\n}\n\n// hasRest returns true if fn has \u0026rest.\nfunc (fn *Func) hasRest() bool {\n\treturn fn.Carity \u003c 0\n}\n\n// fixedArgs returns the number of fixed arguments.\nfunc (fn *Func) fixedArgs() int {\n\tif c := fn.Carity; c \u003c 0 {\n\t\treturn -c - 1\n\t} else {\n\t\treturn c\n\t}\n}\n\n// MakeFrame makes a call-frame from a list of actual arguments.\n// Argument x will be used instead of fn only in error messages.\nfunc (fn *Func) MakeFrame(arg *Cell, x interface{}) []interface{} {\n\tarity := fn.Carity // number of arguments, counting the whole rests as one\n\tif arity \u003c 0 {\n\t\tarity = -arity\n\t}\n\tframe := make([]interface{}, arity)\n\tn := fn.fixedArgs()\n\ti := 0\n\tfor i \u003c n \u0026\u0026 arg != Nil { // Set the list of fixed arguments.\n\t\tframe[i] = arg.Car\n\t\targ = arg.CdrCell()\n\t\ti++\n\t}\n\tif i != n || (arg != Nil \u0026\u0026 !fn.hasRest()) {\n\t\tpanic(NewEvalError(\"arity not matched\", x))\n\t}\n\tif fn.hasRest() {\n\t\tframe[n] = arg\n\t}\n\treturn frame\n}\n\n// EvalFrame evaluates each expression of frame with interp in env.\nfunc (fn *Func) EvalFrame(frame []interface{}, interp *Interp, env *Cell) {\n\tn := fn.fixedArgs()\n\tfor i := 0; i \u003c n; i++ {\n\t\tframe[i] = interp.Eval(frame[i], env)\n\t}\n\tif fn.hasRest() {\n\t\tif j, ok := frame[n].(*Cell); ok {\n\t\t\tz := Nil\n\t\t\ty := Nil\n\t\t\tfor j != Nil {\n\t\t\t\te := interp.Eval(j.Car, env)\n\t\t\t\tx := \u0026Cell{e, Nil}\n\t\t\t\tif z == Nil {\n\t\t\t\t\tz = x\n\t\t\t\t} else {\n\t\t\t\t\ty.Cdr = x\n\t\t\t\t}\n\t\t\t\ty = x\n\t\t\t\tj = j.CdrCell()\n\t\t\t}\n\t\t\tframe[n] = z\n\t\t}\n\t}\n}\n\n//----------------------------------------------------------------------\n\n// Macro represents a compiled macro expression.\ntype Macro struct {\n\tFunc\n\t// body is a list which will be used as the function body.\n\tbody *Cell\n}\n\n// NewMacro constructs a Macro.\nfunc NewMacro(carity int, body *Cell, env *Cell) interface{} {\n\treturn \u0026Macro{Func{carity}, body}\n}\n\n// ExpandWith expands the macro with a list of actual arguments.\nfunc (x *Macro) ExpandWith(interp *Interp, arg *Cell) interface{} {\n\tframe := x.MakeFrame(arg, x)\n\tenv := \u0026Cell{frame, Nil}\n\tvar y interface{} = Nil\n\tfor j := x.body; j != Nil; j = j.CdrCell() {\n\t\ty = interp.Eval(j.Car, env)\n\t}\n\treturn y\n}\n\n// String returns a textual representation of the macro.\nfunc (x *Macro) String() string {\n\treturn fmt.Sprintf(\"#\u003cmacro:%d:%s\u003e\", x.Carity, Str(x.body))\n}\n\n// Lambda represents a compiled lambda expression (within another function).\ntype Lambda struct {\n\tFunc\n\t// Body is a list which will be used as the function body.\n\tBody *Cell\n}\n\n// NewLambda constructs a Lambda.\nfunc NewLambda(carity int, body *Cell, env *Cell) interface{} {\n\treturn \u0026Lambda{Func{carity}, body}\n}\n\n// String returns a textual representation of the lambda.\nfunc (x *Lambda) String() string {\n\treturn fmt.Sprintf(\"#\u003clambda:%d:%s\u003e\", x.Carity, Str(x.Body))\n}\n\n// Closure represents a compiled lambda expression with its own environment.\ntype Closure struct {\n\tLambda\n\t// Env is the closure''s own environment.\n\tEnv *Cell\n}\n\n// NewClosure constructs a Closure.\nfunc NewClosure(carity int, body *Cell, env *Cell) interface{} {\n\treturn \u0026Closure{Lambda{Func{carity}, body}, env}\n}\n\n// MakeEnv makes a new environment from a list of acutual arguments,\n// which will be used in evaluation of the body of the closure.\nfunc (x *Closure) MakeEnv(interp *Interp, arg *Cell, interpEnv *Cell) *Cell {\n\tframe := x.MakeFrame(arg, x)\n\tx.EvalFrame(frame, interp, interpEnv)\n\treturn \u0026Cell{frame, x.Env} // Prepend the frame to Env of the closure.\n}\n\n// String returns a textual representation of the closure.\nfunc (x *Closure) String() string {\n\treturn fmt.Sprintf(\"#\u003cclosure:%d:%s:%s\u003e\",\n\t\tx.Carity, Str(x.Env), Str(x.Body))\n}\n\n//----------------------------------------------------------------------\n\n// BuiltInFunc represents a built-in function.\ntype BuiltInFunc struct {\n\tFunc\n\tname string\n\tbody func([]interface{}) interface{}\n}\n\n// NewBuiltInFunc constructs a BuiltInFunc.\nfunc NewBuiltInFunc(name string, carity int,\n\tbody func([]interface{}) interface{}) *BuiltInFunc {\n\treturn \u0026BuiltInFunc{Func{carity}, name, body}\n}\n\n// EvalWith invokes the built-in function with a list of actual arguments.\nfunc (x *BuiltInFunc) EvalWith(interp *Interp, arg *Cell,\n\tinterpEnv *Cell) interface{} {\n\tframe := x.MakeFrame(arg, x)\n\tx.EvalFrame(frame, interp, interpEnv)\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tif _, ok := err.(*EvalError); ok {\n\t\t\t\tpanic(err)\n\t\t\t} else {\n\t\t\t\tmsg := fmt.Sprintf(\"%v -- %s\", err, x.name)\n\t\t\t\tpanic(NewEvalError(msg, frame))\n\t\t\t}\n\t\t}\n\t}()\n\treturn x.body(frame)\n}\n\n// String returns a textual representation of the BuiltInFunc.\nfunc (x *BuiltInFunc) String() string {\n\treturn fmt.Sprintf(\"#\u003c%s:%d\u003e\", x.name, x.Carity)\n}\n\n//----------------------------------------------------------------------\n\n// Arg represents a bound variable in a compiled lambda/macro expression.\n// It is constructed with \u0026Arg{level, offset, symbol}.\ntype Arg struct {\n\t// Level is a nesting level of the lexical scope.\n\t// 0 for the innermost scope.\n\tLevel int\n\n\t// Offset is an offset of the variable within the frame of the Level.\n\t// 0 for the first variable within the frame.\n\tOffset int\n\n\t// Sym is a symbol which represented the variable before compilation.\n\tSymbol *Sym\n}\n\n// GetValue gets a value from the location corresponding to the variable x\n// within an environment env.\nfunc (x *Arg) GetValue(env *Cell) interface{} {\n\tfor i := 0; i \u003c x.Level; i++ {\n\t\tenv = env.Cdr.(*Cell)\n\t}\n\treturn (env.Car.([]interface{}))[x.Offset]\n}\n\n// SetValue sets a value y to the location corresponding to the variable x\n// within an environment env.\nfunc (x *Arg) SetValue(y interface{}, env *Cell) {\n\tfor i := 0; i \u003c x.Level; i++ {\n\t\tenv = env.Cdr.(*Cell)\n\t}\n\t(env.Car.([]interface{}))[x.Offset] = y\n}\n\n// String returns a textual representation of the Arg.\nfunc (x *Arg) String() string {\n\treturn fmt.Sprintf(\"#%d:%d:%v\", x.Level, x.Offset, x.Symbol)\n}\n\n//----------------------------------------------------------------------\n\n// EvalError represents an error in evaluation.\ntype EvalError struct {\n\tMessage string\n\tTrace   []string\n}\n\n// NewEvalError constructs an EvalError.\nfunc NewEvalError(msg string, x interface{}) *EvalError {\n\treturn \u0026EvalError{msg + \": \" + Str(x), nil}\n}\n\n// NewNotVariableError constructs an EvalError which indicates an absence\n// of variable.\nfunc NewNotVariableError(x interface{}) *EvalError {\n\treturn NewEvalError(\"variable expected\", x)\n}\n\n// Error returns a textual representation of the error.\n// It is defined in compliance with the error type.\nfunc (err *EvalError) Error() string {\n\ts := \"EvalError: \" + err.Message\n\tfor _, line := range err.Trace {\n\t\ts += \"\\n\\t\" + line\n\t}\n\treturn s\n}\n\n// EofToken is a token which represents the end of file.\nvar EofToken error = errors.New(\"end of file\")\n\n//----------------------------------------------------------------------\n\n// Interp represents a core of the interpreter.\ntype Interp struct {\n\tglobals map[*Sym]interface{}\n\tlock    sync.RWMutex\n}\n\n// Future represents a \"promise\" for future/force.\ntype Future struct {\n\t// Chan is a channel which transmits a pair of result and error.\n\t// The pair is represented by Cell.\n\tChan \u003c-chan Cell\n\n\t// Result is a pair of the result (in a narrow meaning) and the error.\n\tResult Cell\n\n\t// Lock is an exclusive lock to receive the result at \"force\".\n\tLock sync.Mutex\n}\n\n// String returns a textual representation of the Future.\nfunc (fu *Future) String() string {\n\treturn fmt.Sprintf(\"#\u003cfuture:%v:%s:%v\u003e\",\n\t\tfu.Chan, Str(\u0026fu.Result), \u0026fu.Lock)\n}\n\n// GetGlobalVar gets a global value of symbol sym within the interpreter.\nfunc (interp *Interp) GetGlobalVar(sym *Sym) (interface{}, bool) {\n\tinterp.lock.RLock()\n\tval, ok := interp.globals[sym]\n\tinterp.lock.RUnlock()\n\treturn val, ok\n}\n\n// SetGlobalVar sets a global value of symbol sym within the interpreter.\nfunc (interp *Interp) SetGlobalVar(sym *Sym, val interface{}) {\n\tinterp.lock.Lock()\n\tinterp.globals[sym] = val\n\tinterp.lock.Unlock()\n}\n\n// NewInterp constructs an interpreter and sets built-in functions etc. as\n// the global values of symbols within the interpreter.\nfunc NewInterp() *Interp {\n\tinterp := \u0026Interp{globals: make(map[*Sym]interface{})}\n\n\tinterp.Def(\"car\", 1, func(a []interface{}) interface{} {\n\t\tif a[0] == Nil {\n\t\t\treturn Nil\n\t\t}\n\t\treturn a[0].(*Cell).Car\n\t})\n\n\tinterp.Def(\"cdr\", 1, func(a []interface{}) interface{} {\n\t\tif a[0] == Nil {\n\t\t\treturn Nil\n\t\t}\n\t\treturn a[0].(*Cell).Cdr\n\t})\n\n\tinterp.Def(\"cons\", 2, func(a []interface{}) interface{} {\n\t\treturn \u0026Cell{a[0], a[1]}\n\t})\n\n\tinterp.Def(\"atom\", 1, func(a []interface{}) interface{} {\n\t\tif j, ok := a[0].(*Cell); ok \u0026\u0026 j != Nil {\n\t\t\treturn Nil\n\t\t}\n\t\treturn true\n\t})\n\n\tinterp.Def(\"eq\", 2, func(a []interface{}) interface{} {\n\t\tif a[0] == a[1] { // Cells are compared by address.\n\t\t\treturn true\n\t\t}\n\t\treturn Nil\n\t})\n\n\tinterp.Def(\"list\", -1, func(a []interface{}) interface{} {\n\t\treturn a[0]\n\t})\n\n\tinterp.Def(\"rplaca\", 2, func(a []interface{}) interface{} {\n\t\ta[0].(*Cell).Car = a[1]\n\t\treturn a[1]\n\t})\n\n\tinterp.Def(\"rplacd\", 2, func(a []interface{}) interface{} {\n\t\ta[0].(*Cell).Cdr = a[1]\n\t\treturn a[1]\n\t})\n\n\tinterp.Def(\"length\", 1, func(a []interface{}) interface{} {\n\t\tswitch x := a[0].(type) {\n\t\tcase *Cell:\n\t\t\treturn float64(x.Len())\n\t\tcase string: // Each multi-bytes character counts 1.\n\t\t\treturn float64(utf8.RuneCountInString(x))\n\t\tdefault:\n\t\t\tpanic(NewEvalError(\"list or string expected\", x))\n\t\t}\n\t})\n\n\tinterp.Def(\"stringp\", 1, func(a []interface{}) interface{} {\n\t\tif _, ok := a[0].(string); ok {\n\t\t\treturn true\n\t\t}\n\t\treturn Nil\n\t})\n\n\tinterp.Def(\"numberp\", 1, func(a []interface{}) interface{} {\n\t\tif _, ok := a[0].(float64); ok {\n\t\t\treturn true\n\t\t}\n\t\treturn Nil\n\t})\n\n\tinterp.Def(\"eql\", 2, func(a []interface{}) interface{} {\n\t\tif a[0] == a[1] { // Numbers are compared by value.  See \"eq\".\n\t\t\treturn true\n\t\t}\n\t\treturn Nil\n\t})\n\n\tinterp.Def(\"\u003c\", 2, func(a []interface{}) interface{} {\n\t\tif a[0].(float64) \u003c a[1].(float64) {\n\t\t\treturn true\n\t\t}\n\t\treturn Nil\n\t})\n\n\tinterp.Def(\"%\", 2, func(a []interface{}) interface{} {\n\t\treturn math.Mod(a[0].(float64), a[1].(float64))\n\t})\n\n\tinterp.Def(\"mod\", 2, func(a []interface{}) interface{} {\n\t\tx, y := a[0].(float64), a[1].(float64)\n\t\tif (x \u003c 0 \u0026\u0026 y \u003e 0) || (x \u003e 0 \u0026\u0026 y \u003c 0) {\n\t\t\treturn math.Mod(x, y) + y\n\t\t}\n\t\treturn math.Mod(x, y)\n\t})\n\n\tinterp.Def(\"+\", -1, func(a []interface{}) interface{} {\n\t\treturn a[0].(*Cell).FoldL(0.0,\n\t\t\tfunc(x, y interface{}) interface{} {\n\t\t\t\treturn x.(float64) + y.(float64)\n\t\t\t})\n\t})\n\n\tinterp.Def(\"*\", -1, func(a []interface{}) interface{} {\n\t\treturn a[0].(*Cell).FoldL(1.0,\n\t\t\tfunc(x, y interface{}) interface{} {\n\t\t\t\treturn x.(float64) * y.(float64)\n\t\t\t})\n\t})\n\n\tinterp.Def(\"-\", -2, func(a []interface{}) interface{} {\n\t\tif a[1] == Nil {\n\t\t\treturn -a[0].(float64)\n\t\t} else {\n\t\t\treturn a[1].(*Cell).FoldL(a[0].(float64),\n\t\t\t\tfunc(x, y interface{}) interface{} {\n\t\t\t\t\treturn x.(float64) - y.(float64)\n\t\t\t\t})\n\t\t}\n\t})\n\n\tinterp.Def(\"/\", -3, func(a []interface{}) interface{} {\n\t\treturn a[2].(*Cell).FoldL(a[0].(float64)/a[1].(float64),\n\t\t\tfunc(x, y interface{}) interface{} {\n\t\t\t\treturn x.(float64) / y.(float64)\n\t\t\t})\n\t})\n\n\tinterp.Def(\"truncate\", -2, func(a []interface{}) interface{} {\n\t\tx, y := a[0].(float64), a[1].(*Cell)\n\t\tif y == Nil {\n\t\t\treturn math.Trunc(x)\n\t\t} else if y.Cdr == Nil {\n\t\t\treturn math.Trunc(x / y.Car.(float64))\n\t\t} else {\n\t\t\tpanic(\"one or two arguments expected\")\n\t\t}\n\t})\n\n\tinterp.Def(\"prin1\", 1, func(a []interface{}) interface{} {\n\t\tfmt.Print(Str2(a[0], true))\n\t\treturn a[0]\n\t})\n\n\tinterp.Def(\"princ\", 1, func(a []interface{}) interface{} {\n\t\tfmt.Print(Str2(a[0], false))\n\t\treturn a[0]\n\t})\n\n\tinterp.Def(\"terpri\", 0, func(a []interface{}) interface{} {\n\t\tfmt.Println()\n\t\treturn true\n\t})\n\n\tgensymCounterSym := NewSym(\"*gensym-counter*\")\n\tinterp.SetGlobalVar(gensymCounterSym, 1.0)\n\tinterp.Def(\"gensym\", 0, func(a []interface{}) interface{} {\n\t\tinterp.lock.Lock()\n\t\tdefer interp.lock.Unlock()\n\t\tx := interp.globals[gensymCounterSym].(float64)\n\t\tinterp.globals[gensymCounterSym] = x + 1.0\n\t\treturn \u0026Sym{fmt.Sprintf(\"G%d\", int(x)), false}\n\t})\n\n\tinterp.Def(\"make-symbol\", 1, func(a []interface{}) interface{} {\n\t\treturn \u0026Sym{a[0].(string), false}\n\t})\n\n\tinterp.Def(\"intern\", 1, func(a []interface{}) interface{} {\n\t\treturn NewSym(a[0].(string))\n\t})\n\n\tinterp.Def(\"symbol-name\", 1, func(a []interface{}) interface{} {\n\t\treturn a[0].(*Sym).Name\n\t})\n\n\tinterp.Def(\"apply\", 2, func(a []interface{}) interface{} {\n\t\targs := a[1].(*Cell).MapCar(QqQuote)\n\t\treturn interp.Eval(\u0026Cell{a[0], args}, Nil)\n\t})\n\n\tinterp.Def(\"exit\", 1, func(a []interface{}) interface{} {\n\t\tn := int(a[0].(float64))\n\t\tos.Exit(n)\n\t\treturn Nil // *not reached*\n\t})\n\n\tinterp.Def(\"dump\", 0, func(a []interface{}) interface{} {\n\t\tinterp.lock.RLock()\n\t\tdefer interp.lock.RUnlock()\n\t\tr := Nil\n\t\tfor key := range interp.globals {\n\t\t\tr = \u0026Cell{key, r}\n\t\t}\n\t\treturn r\n\t})\n\n\t// Wait until the \"promise\" of Future is delivered.\n\tinterp.Def(\"force\", 1, func(a []interface{}) interface{} {\n\t\tif fu, ok := a[0].(*Future); ok {\n\t\t\tfu.Lock.Lock()\n\t\t\tdefer fu.Lock.Unlock()\n\t\t\tif fu.Chan != nil {\n\t\t\t\tfu.Result = \u003c-fu.Chan\n\t\t\t\tfu.Chan = nil\n\t\t\t}\n\t\t\tif err := fu.Result.Cdr; err != nil {\n\t\t\t\tfu.Result.Cdr = nil\n\t\t\t\tpanic(err) // Transmit the error.\n\t\t\t}\n\t\t\treturn fu.Result.Car\n\t\t} else {\n\t\t\treturn a[0]\n\t\t}\n\t})\n\n\tinterp.SetGlobalVar(NewSym(\"*version*\"),\n\t\t\u0026Cell{\n\t\t\t1.42,\n\t\t\t\u0026Cell{\n\t\t\t\tfmt.Sprintf(\"%s %s/%s\",\n\t\t\t\t\truntime.Version(), runtime.GOOS, runtime.GOARCH),\n\t\t\t\t\u0026Cell{\n\t\t\t\t\t\"Nukata Lisp Light\",\n\t\t\t\t\tNil}}})\n\t// named after Nukata-gun (額田郡) in Tōkai-dō Mikawa-koku (東海道 三河国)\n\n\treturn interp\n}\n\n// Def defines a built-in function by giving a name, arity, and body.\nfunc (interp *Interp) Def(name string, carity int,\n\tbody func([]interface{}) interface{}) {\n\tsym := NewSym(name)\n\tfnc := NewBuiltInFunc(name, carity, body)\n\tinterp.SetGlobalVar(sym, fnc)\n}\n\n// Eval evaluates a Lisp expression in a given environment env.\nfunc (interp *Interp) Eval(expression interface{}, env *Cell) interface{} {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tif ex, ok := err.(*EvalError); ok {\n\t\t\t\tif ex.Trace == nil {\n\t\t\t\t\tex.Trace = make([]string, 0, 10)\n\t\t\t\t}\n\t\t\t\tif len(ex.Trace) \u003c 10 {\n\t\t\t\t\tex.Trace = append(ex.Trace, Str(expression))\n\t\t\t\t}\n\t\t\t}\n\t\t\tpanic(err)\n\t\t}\n\t}()\n\tfor {\n\t\tswitch x := expression.(type) {\n\t\tcase *Arg:\n\t\t\treturn x.GetValue(env)\n\t\tcase *Sym:\n\t\t\tr, ok := interp.GetGlobalVar(x)\n\t\t\tif ok {\n\t\t\t\treturn r\n\t\t\t}\n\t\t\tpanic(NewEvalError(\"void variable\", x))\n\t\tcase *Cell:\n\t\t\tif x == Nil {\n\t\t\t\treturn x // an empty list\n\t\t\t}\n\t\t\tfn := x.Car\n\t\t\targ := x.CdrCell()\n\t\t\tsym, ok := fn.(*Sym)\n\t\t\tif ok \u0026\u0026 sym.IsKeyword {\n\t\t\t\tswitch sym {\n\t\t\t\tcase QuoteSym:\n\t\t\t\t\tif arg != Nil \u0026\u0026 arg.Cdr == Nil {\n\t\t\t\t\t\treturn arg.Car\n\t\t\t\t\t}\n\t\t\t\t\tpanic(NewEvalError(\"bad quote\", x))\n\t\t\t\tcase ProgNSym:\n\t\t\t\t\texpression = interp.evalProgN(arg, env)\n\t\t\t\tcase CondSym:\n\t\t\t\t\texpression = interp.evalCond(arg, env)\n\t\t\t\tcase SetqSym:\n\t\t\t\t\treturn interp.evalSetQ(arg, env)\n\t\t\t\tcase LambdaSym:\n\t\t\t\t\treturn interp.compile(arg, env, NewClosure)\n\t\t\t\tcase MacroSym:\n\t\t\t\t\tif env != Nil {\n\t\t\t\t\t\tpanic(NewEvalError(\"nested macro\", x))\n\t\t\t\t\t}\n\t\t\t\t\treturn interp.compile(arg, Nil, NewMacro)\n\t\t\t\tcase QuasiquoteSym:\n\t\t\t\t\tif arg != Nil \u0026\u0026 arg.Cdr == Nil {\n\t\t\t\t\t\texpression = QqExpand(arg.Car)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpanic(NewEvalError(\"bad quasiquote\", x))\n\t\t\t\t\t}\n\t\t\t\tcase FutureSym:\n\t\t\t\t\tch := make(chan Cell)\n\t\t\t\t\tgo interp.futureTask(arg, env, ch)\n\t\t\t\t\treturn \u0026Future{Chan: ch}\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(NewEvalError(\"bad keyword\", fn))\n\t\t\t\t}\n\t\t\t} else { // Apply fn to arg.\n\t\t\t\t// Expand fn = interp.Eval(fn, env) here on Sym for speed.\n\t\t\t\tif ok {\n\t\t\t\t\tfn, ok = interp.GetGlobalVar(sym)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\tpanic(NewEvalError(\"undefined\", x.Car))\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfn = interp.Eval(fn, env)\n\t\t\t\t}\n\t\t\t\tswitch f := fn.(type) {\n\t\t\t\tcase *Closure:\n\t\t\t\t\tenv = f.MakeEnv(interp, arg, env)\n\t\t\t\t\texpression = interp.evalProgN(f.Body, env)\n\t\t\t\tcase *Macro:\n\t\t\t\t\texpression = f.ExpandWith(interp, arg)\n\t\t\t\tcase *BuiltInFunc:\n\t\t\t\t\treturn f.EvalWith(interp, arg, env)\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(NewEvalError(\"not applicable\", fn))\n\t\t\t\t}\n\t\t\t}\n\t\tcase *Lambda:\n\t\t\treturn \u0026Closure{*x, env}\n\t\tdefault:\n\t\t\treturn x // numbers, strings etc.\n\t\t}\n\t}\n}\n\n// SafeEval evaluates a Lisp expression in a given environment env and\n// returns the result and nil.\n// If an error happens, it returns Nil and the error\nfunc (interp *Interp) SafeEval(expression interface{}, env *Cell) (\n\tresult interface{}, err interface{}) {\n\tdefer func() {\n\t\tif e := recover(); e != nil {\n\t\t\tresult, err = Nil, e\n\t\t}\n\t}()\n\treturn interp.Eval(expression, env), nil\n}\n\n// evalProgN evaluates E1, E2, .., E(n-1) and returns the tail expression En.\nfunc (interp *Interp) evalProgN(j *Cell, env *Cell) interface{} {\n\tif j == Nil {\n\t\treturn Nil\n\t}\n\tfor {\n\t\tx := j.Car\n\t\tj = j.CdrCell()\n\t\tif j == Nil {\n\t\t\treturn x // The tail expression will be evaluated at the caller.\n\t\t}\n\t\tinterp.Eval(x, env)\n\t}\n}\n\n// futureTask is a task for goroutine to deliver the \"promise\" of Future.\n// It returns the En value of (future E1 E2 .. En) via the channel and\n// closes the channel.\nfunc (interp *Interp) futureTask(j *Cell, env *Cell, ch chan\u003c- Cell) {\n\tdefer close(ch)\n\tresult, err := interp.safeProgN(j, env)\n\tch \u003c- Cell{result, err}\n}\n\n// safeProgN evaluates E1, E2, .. En and returns the value of En and nil.\n// If an error happens, it returns Nil and the error.\nfunc (interp *Interp) safeProgN(j *Cell, env *Cell) (result interface{},\n\terr interface{}) {\n\tdefer func() {\n\t\tif e := recover(); e != nil {\n\t\t\tresult, err = Nil, e\n\t\t}\n\t}()\n\tx := interp.evalProgN(j, env)\n\treturn interp.Eval(x, env), nil\n}\n\n// evalCond evaluates a conditional expression and returns the selection\n// unevaluated.\nfunc (interp *Interp) evalCond(j *Cell, env *Cell) interface{} {\n\tfor j != Nil {\n\t\tclause, ok := j.Car.(*Cell)\n\t\tif ok {\n\t\t\tif clause != Nil {\n\t\t\t\tresult := interp.Eval(clause.Car, env)\n\t\t\t\tif result != Nil { // If the condition holds...\n\t\t\t\t\tbody := clause.CdrCell()\n\t\t\t\t\tif body == Nil {\n\t\t\t\t\t\treturn QqQuote(result)\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn interp.evalProgN(body, env)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tpanic(NewEvalError(\"cond test expected\", j.Car))\n\t\t}\n\t\tj = j.CdrCell()\n\t}\n\treturn Nil // No clause holds.\n}\n\n// evalSeqQ evaluates each Ei of (setq .. Vi Ei ..) and assigns it to Vi\n// repectively.  It returns the value of the last expression En.\nfunc (interp *Interp) evalSetQ(j *Cell, env *Cell) interface{} {\n\tvar result interface{} = Nil\n\tfor j != Nil {\n\t\tlval := j.Car\n\t\tj = j.CdrCell()\n\t\tif j == Nil {\n\t\t\tpanic(NewEvalError(\"right value expected\", lval))\n\t\t}\n\t\tresult = interp.Eval(j.Car, env)\n\t\tswitch v := lval.(type) {\n\t\tcase *Arg:\n\t\t\tv.SetValue(result, env)\n\t\tcase *Sym:\n\t\t\tif v.IsKeyword {\n\t\t\t\tpanic(NewNotVariableError(lval))\n\t\t\t}\n\t\t\tinterp.SetGlobalVar(v, result)\n\t\tdefault:\n\t\t\tpanic(NewNotVariableError(lval))\n\t\t}\n\t\tj = j.CdrCell()\n\t}\n\treturn result\n}\n\n// compile compiles a Lisp list (macro ...) or (lambda ...).\nfunc (interp *Interp) compile(arg *Cell, env *Cell,\n\tfactory func(int, *Cell, *Cell) interface{}) interface{} {\n\tif arg == Nil {\n\t\tpanic(NewEvalError(\"arglist and body expected\", arg))\n\t}\n\ttable := make(map[*Sym]*Arg)\n\thasRest := makeArgTable(arg.Car, table)\n\tarity := len(table)\n\tbody := arg.CdrCell()\n\tbody = scanForArgs(body, table).(*Cell)\n\tbody = interp.expandMacros(body, 20).(*Cell) // Expand up to 20 nestings.\n\tbody = interp.compileInners(body).(*Cell)\n\tif hasRest {\n\t\tarity = -arity\n\t}\n\treturn factory(arity, body, env)\n}\n\n// expandMacros expands macros and quasi-quotes in x up to count nestings.\nfunc (interp *Interp) expandMacros(x interface{}, count int) interface{} {\n\tif count \u003e 0 {\n\t\tif j, ok := x.(*Cell); ok {\n\t\t\tif j == Nil {\n\t\t\t\treturn Nil\n\t\t\t}\n\t\t\tswitch k := j.Car; k {\n\t\t\tcase QuoteSym, LambdaSym, MacroSym:\n\t\t\t\treturn j\n\t\t\tcase QuasiquoteSym:\n\t\t\t\td := j.CdrCell()\n\t\t\t\tif d != Nil \u0026\u0026 d.Cdr == Nil {\n\t\t\t\t\tz := QqExpand(d.Car)\n\t\t\t\t\treturn interp.expandMacros(z, count)\n\t\t\t\t}\n\t\t\t\tpanic(NewEvalError(\"bad quasiquote\", j))\n\t\t\tdefault:\n\t\t\t\tif sym, ok := k.(*Sym); ok {\n\t\t\t\t\tif v, ok := interp.GetGlobalVar(sym); ok {\n\t\t\t\t\t\tk = v\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif f, ok := k.(*Macro); ok {\n\t\t\t\t\td := j.CdrCell()\n\t\t\t\t\tz := f.ExpandWith(interp, d)\n\t\t\t\t\treturn interp.expandMacros(z, count-1)\n\t\t\t\t} else {\n\t\t\t\t\treturn j.MapCar(func(y interface{}) interface{} {\n\t\t\t\t\t\treturn interp.expandMacros(y, count)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn x\n}\n\n// compileInners replaces inner lambda-expressions with Lambda instances.\nfunc (interp *Interp) compileInners(x interface{}) interface{} {\n\tif j, ok := x.(*Cell); ok {\n\t\tif j == Nil {\n\t\t\treturn Nil\n\t\t}\n\t\tswitch k := j.Car; k {\n\t\tcase QuoteSym:\n\t\t\treturn j\n\t\tcase LambdaSym:\n\t\t\td := j.CdrCell()\n\t\t\treturn interp.compile(d, Nil, NewLambda)\n\t\tcase MacroSym:\n\t\t\tpanic(NewEvalError(\"nested macro\", j))\n\t\tdefault:\n\t\t\treturn j.MapCar(func(y interface{}) interface{} {\n\t\t\t\treturn interp.compileInners(y)\n\t\t\t})\n\t\t}\n\t}\n\treturn x\n}\n\n//----------------------------------------------------------------------\n\n// makeArgTable makes an argument-table.  It returns true if x has \u0026rest.\nfunc makeArgTable(x interface{}, table map[*Sym]*Arg) bool {\n\targ, ok := x.(*Cell)\n\tif !ok {\n\t\tpanic(NewEvalError(\"arglist expected\", x))\n\t}\n\tif arg == Nil {\n\t\treturn false\n\t} else {\n\t\toffset := 0 // offset value within the call-frame\n\t\thasRest := false\n\t\tfor arg != Nil {\n\t\t\tj := arg.Car\n\t\t\tif hasRest {\n\t\t\t\tpanic(NewEvalError(\"2nd rest\", j))\n\t\t\t}\n\t\t\tif j == RestSym { // \u0026rest var\n\t\t\t\targ = arg.CdrCell()\n\t\t\t\tif arg == Nil {\n\t\t\t\t\tpanic(NewNotVariableError(arg))\n\t\t\t\t}\n\t\t\t\tj = arg.Car\n\t\t\t\tif j == RestSym {\n\t\t\t\t\tpanic(NewNotVariableError(j))\n\t\t\t\t}\n\t\t\t\thasRest = true\n\t\t\t}\n\t\t\tvar sym *Sym\n\t\t\tswitch v := j.(type) {\n\t\t\tcase *Sym:\n\t\t\t\tsym = v\n\t\t\tcase *Arg:\n\t\t\t\tsym = v.Symbol\n\t\t\tdefault:\n\t\t\t\tpanic(NewNotVariableError(j))\n\t\t\t}\n\t\t\tif _, ok := table[sym]; ok {\n\t\t\t\tpanic(NewEvalError(\"duplicated argument name\", sym))\n\t\t\t}\n\t\t\ttable[sym] = \u0026Arg{0, offset, sym}\n\t\t\toffset++\n\t\t\targ = arg.CdrCell()\n\t\t}\n\t\treturn hasRest\n\t}\n}\n\n// scanForArgs scans x for formal arguments in table and replaces them\n// with Args.\n// Also it scans x for free Args not in table and promotes their levels.\nfunc scanForArgs(x interface{}, table map[*Sym]*Arg) interface{} {\n\tswitch j := x.(type) {\n\tcase *Sym:\n\t\tif a, ok := table[j]; ok {\n\t\t\treturn a\n\t\t}\n\t\treturn j\n\tcase *Arg:\n\t\tif a, ok := table[j.Symbol]; ok {\n\t\t\treturn a\n\t\t}\n\t\treturn \u0026Arg{j.Level + 1, j.Offset, j.Symbol}\n\tcase *Cell:\n\t\tif j == Nil {\n\t\t\treturn Nil\n\t\t}\n\t\tswitch j.Car {\n\t\tcase QuoteSym:\n\t\t\treturn j\n\t\tcase QuasiquoteSym:\n\t\t\treturn \u0026Cell{QuasiquoteSym, scanForQQ(j.Cdr, table, 0)}\n\t\tdefault:\n\t\t\treturn j.MapCar(func(y interface{}) interface{} {\n\t\t\t\treturn scanForArgs(y, table)\n\t\t\t})\n\t\t}\n\tdefault:\n\t\treturn j\n\t}\n}\n\n// scanForQQ scans x for quasi-quotes and executes scanForArgs on the\n// nesting level of quotes.\nfunc scanForQQ(x interface{}, table map[*Sym]*Arg,\n\tlevel int) interface{} {\n\tj, ok := x.(*Cell)\n\tif ok {\n\t\tif j == Nil {\n\t\t\treturn Nil\n\t\t}\n\t\tswitch k := j.Car; k {\n\t\tcase QuasiquoteSym:\n\t\t\treturn \u0026Cell{k, scanForQQ(j.Cdr, table, level+1)}\n\t\tcase UnquoteSym, UnquoteSplicingSym:\n\t\t\tvar d interface{}\n\t\t\tif level == 0 {\n\t\t\t\td = scanForArgs(j.Cdr, table)\n\t\t\t} else {\n\t\t\t\td = scanForQQ(j.Cdr, table, level-1)\n\t\t\t}\n\t\t\tif d == j.Cdr {\n\t\t\t\treturn j\n\t\t\t}\n\t\t\treturn \u0026Cell{k, d}\n\t\tdefault:\n\t\t\treturn j.MapCar(func(y interface{}) interface{} {\n\t\t\t\treturn scanForQQ(y, table, level)\n\t\t\t})\n\t\t}\n\t} else {\n\t\treturn x\n\t}\n}\n\n//----------------------------------------------------------------------\n// Quasi-Quotation\n\n// QqExpand expands x of any quasi-quote `x into the equivalent S-expression.\nfunc QqExpand(x interface{}) interface{} {\n\treturn qqExpand0(x, 0) // Begin with the nesting level 0.\n}\n\n// QqQuote quotes x so that the result evaluates to x.\nfunc QqQuote(x interface{}) interface{} {\n\tif x == Nil {\n\t\treturn Nil\n\t}\n\tswitch x.(type) {\n\tcase *Sym, *Cell:\n\t\treturn \u0026Cell{QuoteSym, \u0026Cell{x, Nil}}\n\tdefault:\n\t\treturn x\n\t}\n}\n\nfunc qqExpand0(x interface{}, level int) interface{} {\n\tif j, ok := x.(*Cell); ok {\n\t\tif j == Nil {\n\t\t\treturn Nil\n\t\t}\n\t\tif j.Car == UnquoteSym { // ,a\n\t\t\tif level == 0 {\n\t\t\t\treturn j.CdrCell().Car // ,a =\u003e a\n\t\t\t}\n\t\t}\n\t\tt := qqExpand1(j, level)\n\t\tif t.Cdr == Nil {\n\t\t\tif k, ok := t.Car.(*Cell); ok {\n\t\t\t\tif k.Car == ListSym || k.Car == ConsSym {\n\t\t\t\t\treturn k\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn \u0026Cell{AppendSym, t}\n\t} else {\n\t\treturn QqQuote(x)\n\t}\n}\n\n// qqExpand1 expands x of `x so that the result can be used as an argument of\n// append.  Example 1: (,a b) =\u003e ((list a ''b))\n//          Example 2: (,a ,@(cons 2 3)) =\u003e ((cons a (cons 2 3)))\nfunc qqExpand1(x interface{}, level int) *Cell {\n\tif j, ok := x.(*Cell); ok {\n\t\tif j == Nil {\n\t\t\treturn \u0026Cell{Nil, Nil}\n\t\t}\n\t\tswitch j.Car {\n\t\tcase UnquoteSym: // ,a\n\t\t\tif level == 0 {\n\t\t\t\treturn j.CdrCell() // ,a =\u003e (a)\n\t\t\t}\n\t\t\tlevel--\n\t\tcase QuasiquoteSym: // `a\n\t\t\tlevel++\n\t\t}\n\t\th := qqExpand2(j.Car, level)\n\t\tt := qqExpand1(j.Cdr, level) // != Nil\n\t\tif t.Car == Nil \u0026\u0026 t.Cdr == Nil {\n\t\t\treturn \u0026Cell{h, Nil}\n\t\t} else if hc, ok := h.(*Cell); ok {\n\t\t\tif hc.Car == ListSym {\n\t\t\t\tif tcar, ok := t.Car.(*Cell); ok {\n\t\t\t\t\tif tcar.Car == ListSym {\n\t\t\t\t\t\thh := qqConcat(hc, tcar.Cdr)\n\t\t\t\t\t\treturn \u0026Cell{hh, t.Cdr}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif hcdr, ok := hc.Cdr.(*Cell); ok {\n\t\t\t\t\thh := qqConsCons(hcdr, t.Car)\n\t\t\t\t\treturn \u0026Cell{hh, t.Cdr}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn \u0026Cell{h, t}\n\t} else {\n\t\treturn \u0026Cell{QqQuote(x), Nil}\n\t}\n}\n\n// (1 2), (3 4) =\u003e (1 2 3 4)\nfunc qqConcat(x *Cell, y interface{}) interface{} {\n\tif x == Nil {\n\t\treturn y\n\t} else {\n\t\treturn \u0026Cell{x.Car, qqConcat(x.CdrCell(), y)}\n\t}\n}\n\n// (1 2 3), \"a\" =\u003e (cons 1 (cons 2 (cons 3 \"a\")))\nfunc qqConsCons(x *Cell, y interface{}) interface{} {\n\tif x == Nil {\n\t\treturn y\n\t} else {\n\t\treturn \u0026Cell{ConsSym, \u0026Cell{x.Car,\n\t\t\t\u0026Cell{qqConsCons(x.CdrCell(), y), Nil}}}\n\t}\n}\n\n// qqExpand2 expands x.car (= y) of `x so that the result can be used as an\n// argument of append.\n// Examples: ,a =\u003e (list a); ,@(foo 1 2) =\u003e (foo 1 2); b =\u003e (list ''b)\nfunc qqExpand2(y interface{}, level int) interface{} {\n\tif j, ok := y.(*Cell); ok {\n\t\tif j == Nil {\n\t\t\treturn \u0026Cell{ListSym, \u0026Cell{Nil, Nil}} // (list nil)\n\t\t}\n\t\tswitch j.Car {\n\t\tcase UnquoteSym: // ,a\n\t\t\tif level == 0 {\n\t\t\t\treturn \u0026Cell{ListSym, j.Cdr} // ,a =\u003e (list a)\n\t\t\t}\n\t\t\tlevel--\n\t\tcase UnquoteSplicingSym: // ,@a\n\t\t\tif level == 0 {\n\t\t\t\treturn j.CdrCell().Car // ,@a =\u003e a\n\t\t\t}\n\t\t\tlevel--\n\t\tcase QuasiquoteSym: // `a\n\t\t\tlevel++\n\t\t}\n\t}\n\treturn \u0026Cell{ListSym, \u0026Cell{qqExpand0(y, level), Nil}}\n}\n\n//----------------------------------------------------------------------\n\n// Reader represents a reader of Lisp expressions.\ntype Reader struct {\n\tscanner *bufio.Scanner\n\ttoken   interface{} // the current token\n\ttokens  []string    // tokens read from the current line\n\tindex   int         // the next index of tokens\n\tline    string      // the current line\n\tlineNo  int         // the current line number\n\terred   bool        // a flag if an error has happened\n}\n\n// NewReader constructs a reader which will read Lisp expressions from r.\nfunc NewReader(r io.Reader) *Reader {\n\tscanner := bufio.NewScanner(r)\n\treturn \u0026Reader{scanner, nil, nil, 0, \"\", 0, false}\n}\n\n// Read reads a Lisp expression and returns the expression and nil.\n// If the input runs out, it returns EofToken and nil.\n// If an error happens, it returns Nil and the error.\nfunc (rr *Reader) Read() (result interface{}, err interface{}) {\n\tdefer func() {\n\t\tif e := recover(); e != nil {\n\t\t\tresult, err = Nil, e\n\t\t}\n\t}()\n\trr.readToken()\n\treturn rr.parseExpression(), nil\n}\n\nfunc (rr *Reader) newSynatxError(msg string, arg interface{}) *EvalError {\n\trr.erred = true\n\ts := fmt.Sprintf(\"syntax error: %s -- %d: %s\",\n\t\tfmt.Sprintf(msg, arg), rr.lineNo, rr.line)\n\treturn \u0026EvalError{s, nil}\n}\n\nfunc (rr *Reader) parseExpression() interface{} {\n\tswitch rr.token {\n\tcase LeftParenSym: // (a b c)\n\t\trr.readToken()\n\t\treturn rr.parseListBody()\n\tcase SingleQuoteSym: // ''a =\u003e (quote a)\n\t\trr.readToken()\n\t\treturn \u0026Cell{QuoteSym, \u0026Cell{rr.parseExpression(), Nil}}\n\tcase BackQuoteSym: // `a =\u003e (quasiquote a)\n\t\trr.readToken()\n\t\treturn \u0026Cell{QuasiquoteSym, \u0026Cell{rr.parseExpression(), Nil}}\n\tcase CommaSym: // ,a =\u003e (unquote a)\n\t\trr.readToken()\n\t\treturn \u0026Cell{UnquoteSym, \u0026Cell{rr.parseExpression(), Nil}}\n\tcase CommaAtSym: // ,@a =\u003e (unquote-splicing a)\n\t\trr.readToken()\n\t\treturn \u0026Cell{UnquoteSplicingSym, \u0026Cell{rr.parseExpression(), Nil}}\n\tcase DotSym, RightParenSym:\n\t\tpanic(rr.newSynatxError(\"unexpected \\\"%v\\\"\", rr.token))\n\tdefault:\n\t\treturn rr.token\n\t}\n}\n\nfunc (rr *Reader) parseListBody() *Cell {\n\tif rr.token == EofToken {\n\t\tpanic(rr.newSynatxError(\"unexpected EOF%s\", \"\"))\n\t} else if rr.token == RightParenSym {\n\t\treturn Nil\n\t} else {\n\t\te1 := rr.parseExpression()\n\t\trr.readToken()\n\t\tvar e2 interface{}\n\t\tif rr.token == DotSym { // (a . b)\n\t\t\trr.readToken()\n\t\t\te2 = rr.parseExpression()\n\t\t\trr.readToken()\n\t\t\tif rr.token != RightParenSym {\n\t\t\t\tpanic(rr.newSynatxError(\"\\\")\\\" expected: %v\", rr.token))\n\t\t\t}\n\t\t} else {\n\t\t\te2 = rr.parseListBody()\n\t\t}\n\t\treturn \u0026Cell{e1, e2}\n\t}\n}\n\n// readToken reads the next token and set it to rr.token.\nfunc (rr *Reader) readToken() {\n\t// Read the next line if the line ends or an error happened last time.\n\tfor len(rr.tokens) \u003c= rr.index || rr.erred {\n\t\trr.erred = false\n\t\tif rr.scanner.Scan() {\n\t\t\trr.line = rr.scanner.Text()\n\t\t\trr.lineNo++\n\t\t} else {\n\t\t\tif err := rr.scanner.Err(); err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\trr.token = EofToken\n\t\t\treturn\n\t\t}\n\t\tmm := tokenPat.FindAllStringSubmatch(rr.line, -1)\n\t\ttt := make([]string, 0, len(mm)*3/5) // Estimate 40% will be spaces.\n\t\tfor _, m := range mm {\n\t\t\tif m[1] != \"\" {\n\t\t\t\ttt = append(tt, m[1])\n\t\t\t}\n\t\t}\n\t\trr.tokens = tt\n\t\trr.index = 0\n\t}\n\t// Read the next token.\n\ts := rr.tokens[rr.index]\n\trr.index++\n\tif s[0] == ''\"'' {\n\t\tn := len(s) - 1\n\t\tif n \u003c 1 || s[n] != ''\"'' {\n\t\t\tpanic(rr.newSynatxError(\"bad string: ''%s''\", s))\n\t\t}\n\t\ts = s[1:n]\n\t\ts = escapePat.ReplaceAllStringFunc(s, func(t string) string {\n\t\t\tr, ok := escapes[t] // r, err := strconv.Unquote(\"''\" + t + \"''\")\n\t\t\tif !ok {\n\t\t\t\tr = t // Leave any invalid escape sequence as it is.\n\t\t\t}\n\t\t\treturn r\n\t\t})\n\t\trr.token = s\n\t\treturn\n\t}\n\tf, err := strconv.ParseFloat(s, 64) // Try to read s as a float64.\n\tif err == nil {\n\t\trr.token = f\n\t\treturn\n\t}\n\tif s == \"nil\" {\n\t\trr.token = Nil\n\t\treturn\n\t} else if s == \"t\" {\n\t\trr.token = true\n\t\treturn\n\t}\n\trr.token = NewSym(s)\n\treturn\n}\n\n// tokenPat is a regular expression to split a line to Lisp tokens.\nvar tokenPat = regexp.MustCompile(`\\s+|;.*$|(\"(\\\\.?|.)*?\"|,@?|[^()''` +\n\t\"`\" + `~\"; \\t]+|.)`)\n\n// escapePat is a reg. expression to take an escape sequence out of a string.\nvar escapePat = regexp.MustCompile(`\\\\(.)`)\n\n// escapes is a mapping from an escape sequence to its string value.\nvar escapes = map[string]string{\n\t`\\\\`: `\\`,\n\t`\\\"`: `\"`,\n\t`\\n`: \"\\n\", `\\r`: \"\\r\", `\\f`: \"\\f\", `\\b`: \"\\b\", `\\t`: \"\\t\", `\\v`: \"\\v\",\n}\n\n//----------------------------------------------------------------------\n\n// Str returns a textual representation of any Lisp expression x.\nfunc Str(x interface{}) string {\n\treturn Str2(x, true)\n}\n\n// Str2 returns a textual representation of any Lisp expression x.\n// If quoteString is true, any strings in the expression are represented\n// with enclosing quotes respectively.\nfunc Str2(x interface{}, quoteString bool) string {\n\treturn str4(x, quoteString, -1, nil)\n}\n\n// quotes is a mapping from a quote symbol to its string representation.\nvar quotes = map[*Sym]string{\n\tQuoteSym:           \"''\",\n\tQuasiquoteSym:      \"`\",\n\tUnquoteSym:         \",\",\n\tUnquoteSplicingSym: \",@\",\n}\n\nfunc str4(a interface{}, quoteString bool, count int,\n\tprinted map[*Cell]bool) string {\n\tif a == true {\n\t\treturn \"t\"\n\t}\n\tswitch x := a.(type) {\n\tcase *Cell:\n\t\tif x == Nil {\n\t\t\treturn \"nil\"\n\t\t}\n\t\tif s, ok := x.Car.(*Sym); ok {\n\t\t\tif q, ok := quotes[s]; ok {\n\t\t\t\tif d, ok := x.Cdr.(*Cell); ok {\n\t\t\t\t\tif d.Cdr == Nil {\n\t\t\t\t\t\treturn q + str4(d.Car, true, count, printed)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn \"(\" + strListBody(x, count, printed) + \")\"\n\tcase string:\n\t\tif quoteString {\n\t\t\treturn strconv.Quote(x)\n\t\t}\n\t\treturn x\n\tcase []interface{}:\n\t\ts := make([]string, len(x))\n\t\tfor i, e := range x {\n\t\t\ts[i] = str4(e, true, count, printed)\n\t\t}\n\t\treturn \"[\" + strings.Join(s, \", \") + \"]\"\n\tcase *Sym:\n\t\tif x.IsInterned() {\n\t\t\treturn x.Name\n\t\t}\n\t\treturn \"#:\" + x.Name\n\t}\n\treturn fmt.Sprintf(\"%v\", a)\n}\n\n// strListBody makes a string representation of a list, omitting its parens.\nfunc strListBody(x *Cell, count int, printed map[*Cell]bool) string {\n\tif printed == nil {\n\t\tprinted = make(map[*Cell]bool)\n\t}\n\tif count \u003c 0 {\n\t\tcount = 4 // threshold of ellipsis for circular lists\n\t}\n\ts := make([]string, 0, 10)\n\ty := x\n\tfor y != Nil {\n\t\tif _, ok := printed[y]; ok {\n\t\t\tcount--\n\t\t\tif count \u003c 0 {\n\t\t\t\ts = append(s, \"...\") // ellipsis for a circular list\n\t\t\t\treturn strings.Join(s, \" \")\n\t\t\t}\n\t\t} else {\n\t\t\tprinted[y] = true\n\t\t\tcount = 4\n\t\t}\n\t\ts = append(s, str4(y.Car, true, count, printed))\n\t\tif cdr, ok := y.Cdr.(*Cell); ok {\n\t\t\ty = cdr\n\t\t} else {\n\t\t\ts = append(s, \".\")\n\t\t\ts = append(s, str4(y.Cdr, true, count, printed))\n\t\t\tbreak\n\t\t}\n\t}\n\ty = x\n\tfor y != Nil {\n\t\tdelete(printed, y)\n\t\tif cdr, ok := y.Cdr.(*Cell); ok {\n\t\t\ty = cdr\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn strings.Join(s, \" \")\n}\n\n//----------------------------------------------------------------------\n\n// Run executes REPL (Read-Eval-Print Loop).\n// It returns false if REPL was ceased by an error.\n// It returns true if REPL was finished normally.\nfunc Run(interp *Interp, input io.Reader) bool {\n\tinteractive := (input == nil)\n\tif interactive {\n\t\tinput = os.Stdin\n\t}\n\treader := NewReader(input)\n\tfor {\n\t\tif interactive {\n\t\t\tos.Stdout.WriteString(\"\u003e \")\n\t\t}\n\t\tx, err := reader.Read()\n\t\tif err == nil {\n\t\t\tif x == EofToken {\n\t\t\t\treturn true // Finished normally.\n\t\t\t}\n\t\t\tx, err = interp.SafeEval(x, Nil)\n\t\t\tif err == nil {\n\t\t\t\tif interactive {\n\t\t\t\t\tfmt.Println(Str(x))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif err != nil {\n\t\t\tfmt.Println(err)\n\t\t\tif !interactive {\n\t\t\t\treturn false // Ceased by an error.\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Main runs each element of args as a name of Lisp script file.\n// It ignores args[0].\n// If it does not have args[1] or some element is \"-\", it begins REPL.\nfunc Main(args []string) int {\n\tinterp := NewInterp()\n\tss := strings.NewReader(Prelude)\n\tif !Run(interp, ss) {\n\t\treturn 1\n\t}\n\tif len(args) \u003c 2 {\n\t\targs = []string{args[0], \"-\"}\n\t}\n\tfor i, fileName := range args {\n\t\tif i == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif fileName == \"-\" {\n\t\t\tRun(interp, nil)\n\t\t\tfmt.Println(\"Goodbye\")\n\t\t} else {\n\t\t\tfile, err := os.Open(fileName)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Println(err)\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tif !Run(interp, file) {\n\t\t\t\treturn 1\n\t\t\t}\n\t\t}\n\t}\n\treturn 0\n}\n\nfunc main() {\n\tos.Exit(Main(os.Args))\n}\n\n// Prelude is an initialization script of Lisp.\n// Each \"~\" is replaced by \"`\" at runtime.\nvar Prelude = strings.Replace(`\n(setq defmacro\n      (macro (name args \u0026rest body)\n             ~(progn (setq ,name (macro ,args ,@body))\n                     '',name)))\n\n(defmacro defun (name args \u0026rest body)\n  ~(progn (setq ,name (lambda ,args ,@body))\n          '',name))\n\n(defun caar (x) (car (car x)))\n(defun cadr (x) (car (cdr x)))\n(defun cdar (x) (cdr (car x)))\n(defun cddr (x) (cdr (cdr x)))\n(defun caaar (x) (car (car (car x))))\n(defun caadr (x) (car (car (cdr x))))\n(defun cadar (x) (car (cdr (car x))))\n(defun caddr (x) (car (cdr (cdr x))))\n(defun cdaar (x) (cdr (car (car x))))\n(defun cdadr (x) (cdr (car (cdr x))))\n(defun cddar (x) (cdr (cdr (car x))))\n(defun cdddr (x) (cdr (cdr (cdr x))))\n(defun not (x) (eq x nil))\n(defun consp (x) (not (atom x)))\n(defun print (x) (prin1 x) (terpri) x)\n(defun identity (x) x)\n\n(setq\n = eql\n null not\n setcar rplaca\n setcdr rplacd)\n\n(defun \u003e (x y) (\u003c y x))\n(defun \u003e= (x y) (not (\u003c x y)))\n(defun \u003c= (x y) (not (\u003c y x)))\n(defun /= (x y) (not (= x y)))\n\n(defun equal (x y)\n  (cond ((atom x) (eql x y))\n        ((atom y) nil)\n        ((equal (car x) (car y)) (equal (cdr x) (cdr y)))))\n\n(defmacro if (test then \u0026rest else)\n  ~(cond (,test ,then)\n         ,@(cond (else ~((t ,@else))))))\n\n(defmacro when (test \u0026rest body)\n  ~(cond (,test ,@body)))\n\n(defmacro let (args \u0026rest body)\n  ((lambda (vars vals)\n     (defun vars (x)\n       (cond (x (cons (if (atom (car x))\n                          (car x)\n                        (caar x))\n                      (vars (cdr x))))))\n     (defun vals (x)\n       (cond (x (cons (if (atom (car x))\n                          nil\n                        (cadar x))\n                      (vals (cdr x))))))\n     ~((lambda ,(vars args) ,@body) ,@(vals args)))\n   nil nil))\n\n(defmacro letrec (args \u0026rest body)      ; (letrec ((v e) ...) body...)\n  (let (vars setqs)\n    (defun vars (x)\n      (cond (x (cons (caar x)\n                     (vars (cdr x))))))\n    (defun sets (x)\n      (cond (x (cons ~(setq ,(caar x) ,(cadar x))\n                     (sets (cdr x))))))\n    ~(let ,(vars args) ,@(sets args) ,@body)))\n\n(defun _append (x y)\n  (if (null x)\n      y\n    (cons (car x) (_append (cdr x) y))))\n(defmacro append (x \u0026rest y)\n  (if (null y)\n      x\n    ~(_append ,x (append ,@y))))\n\n(defmacro and (x \u0026rest y)\n  (if (null y)\n      x\n    ~(cond (,x (and ,@y)))))\n\n(defun mapcar (f x)\n  (and x (cons (f (car x)) (mapcar f (cdr x)))))\n\n(defmacro or (x \u0026rest y)\n  (if (null y)\n      x\n    ~(cond (,x)\n           ((or ,@y)))))\n\n(defun listp (x)\n  (or (null x) (consp x)))    ; NB (listp (lambda (x) (+ x 1))) =\u003e nil\n\n(defun memq (key x)\n  (cond ((null x) nil)\n        ((eq key (car x)) x)\n        (t (memq key (cdr x)))))\n\n(defun member (key x)\n  (cond ((null x) nil)\n        ((equal key (car x)) x)\n        (t (member key (cdr x)))))\n\n(defun assq (key alist)\n  (cond (alist (let ((e (car alist)))\n                 (if (and (consp e) (eq key (car e)))\n                     e\n                   (assq key (cdr alist)))))))\n\n(defun assoc (key alist)\n  (cond (alist (let ((e (car alist)))\n                 (if (and (consp e) (equal key (car e)))\n                     e\n                   (assoc key (cdr alist)))))))\n\n(defun _nreverse (x prev)\n  (let ((next (cdr x)))\n    (setcdr x prev)\n    (if (null next)\n        x\n      (_nreverse next x))))\n(defun nreverse (list)            ; (nreverse ''(a b c d)) =\u003e (d c b a)\n  (cond (list (_nreverse list nil))))\n\n(defun last (list)\n  (if (atom (cdr list))\n      list\n    (last (cdr list))))\n\n(defun nconc (\u0026rest lists)\n  (if (null (cdr lists))\n      (car lists)\n    (if (null (car lists))\n        (apply nconc (cdr lists))\n      (setcdr (last (car lists))\n              (apply nconc (cdr lists)))\n      (car lists))))\n\n(defmacro while (test \u0026rest body)\n  (let ((loop (gensym)))\n    ~(letrec ((,loop (lambda () (cond (,test ,@body (,loop))))))\n       (,loop))))\n\n(defmacro dolist (spec \u0026rest body) ; (dolist (name list [result]) body...)\n  (let ((name (car spec))\n        (list (gensym)))\n    ~(let (,name\n           (,list ,(cadr spec)))\n       (while ,list\n         (setq ,name (car ,list))\n         ,@body\n         (setq ,list (cdr ,list)))\n       ,@(if (cddr spec)\n             ~((setq ,name nil)\n               ,(caddr spec))))))\n\n(defmacro dotimes (spec \u0026rest body) ; (dotimes (name count [result]) body...)\n  (let ((name (car spec))\n        (count (gensym)))\n    ~(let ((,name 0)\n           (,count ,(cadr spec)))\n       (while (\u003c ,name ,count)\n         ,@body\n         (setq ,name (+ ,name 1)))\n       ,@(if (cddr spec)\n             ~(,(caddr spec))))))\n`, \"~\", \"`\", -1)\n\n/*\n  Copyright (c) 2015, 2016 OKI Software Co., Ltd.\n\n  Permission is hereby granted, free of charge, to any person obtaining a\n  copy of this software and associated documentation files (the \"Software\"),\n  to deal in the Software without restriction, including without limitation\n  the rights to use, copy, modify, merge, publish, distribute, sublicense,\n  and/or sell copies of the Software, and to permit persons to whom the\n  Software is furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n  DEALINGS IN THE SOFTWARE.\n*/\n"},"lineMatches":[{"preview":"func Main(args []string) int {","lineNumber":1530,"offsetAndLengths":[[0,10]]},{"preview":"func main() {","lineNumber":1560,"offsetAndLengths":[[0,10]]}]},{"__typename":"FileMatch","repository":{"name":"github.com/devspace-sh/devspace"},"file":{"path":"vendor/github.com/google/gnostic-models/extensions/extensions.go","url":"/github.com/devspace-sh/devspace/-/blob/vendor/github.com/google/gnostic-models/extensions/extensions.go","content":"// Copyright 2017 Google LLC. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//    http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage gnostic_extension_v1\n\nimport (\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\n\t\"github.com/golang/protobuf/proto\"\n\t\"github.com/golang/protobuf/ptypes\"\n)\n\ntype extensionHandler func(name string, yamlInput string) (bool, proto.Message, error)\n\n// Main implements the main program of an extension handler.\nfunc Main(handler extensionHandler) {\n\t// unpack the request\n\tdata, err := ioutil.ReadAll(os.Stdin)\n\tif err != nil {\n\t\tlog.Println(\"File error:\", err.Error())\n\t\tos.Exit(1)\n\t}\n\tif len(data) == 0 {\n\t\tlog.Println(\"No input data.\")\n\t\tos.Exit(1)\n\t}\n\trequest := \u0026ExtensionHandlerRequest{}\n\terr = proto.Unmarshal(data, request)\n\tif err != nil {\n\t\tlog.Println(\"Input error:\", err.Error())\n\t\tos.Exit(1)\n\t}\n\t// call the handler\n\thandled, output, err := handler(request.Wrapper.ExtensionName, request.Wrapper.Yaml)\n\t// respond with the output of the handler\n\tresponse := \u0026ExtensionHandlerResponse{\n\t\tHandled: false, // default assumption\n\t\tErrors:  make([]string, 0),\n\t}\n\tif err != nil {\n\t\tresponse.Errors = append(response.Errors, err.Error())\n\t} else if handled {\n\t\tresponse.Handled = true\n\t\tresponse.Value, err = ptypes.MarshalAny(output)\n\t\tif err != nil {\n\t\t\tresponse.Errors = append(response.Errors, err.Error())\n\t\t}\n\t}\n\tresponseBytes, _ := proto.Marshal(response)\n\tos.Stdout.Write(responseBytes)\n}\n"},"lineMatches":[{"preview":"func Main(handler extensionHandler) {","lineNumber":28,"offsetAndLengths":[[0,10]]}]},{"__typename":"FileMatch","repository":{"name":"github.com/cubefs/cubefs"},"file":{"path":"blobstore/cmd/cmd.go","url":"/github.com/cubefs/cubefs/-/blob/blobstore/cmd/cmd.go","content":"// Copyright 2022 The CubeFS Authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n// implied. See the License for the specific language governing\n// permissions and limitations under the License.\n\npackage cmd\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/signal\"\n\t\"runtime\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"gopkg.in/natefinch/lumberjack.v2\"\n\n\t\"github.com/cubefs/cubefs/blobstore/common/config\"\n\t\"github.com/cubefs/cubefs/blobstore/common/profile\"\n\t\"github.com/cubefs/cubefs/blobstore/common/rpc\"\n\t\"github.com/cubefs/cubefs/blobstore/common/rpc/auditlog\"\n\t\"github.com/cubefs/cubefs/blobstore/common/rpc/auth\"\n\tauth_proto \"github.com/cubefs/cubefs/blobstore/common/rpc/auth/proto\"\n\t\"github.com/cubefs/cubefs/blobstore/common/rpc2\"\n\t\"github.com/cubefs/cubefs/blobstore/util/graceful\"\n\t\"github.com/cubefs/cubefs/blobstore/util/log\"\n\n\t// module release init functions\n\t_ \"github.com/cubefs/cubefs/blobstore/util/version\"\n)\n\nconst (\n\tdefaultShutdownTimeoutS = 30\n)\n\ntype LogConfig struct {\n\tLevel      log.Level `json:\"level\"`\n\tFilename   string    `json:\"filename\"`\n\tMaxSize    int       `json:\"maxsize\"`\n\tMaxAge     int       `json:\"maxage\"`\n\tMaxBackups int       `json:\"maxbackups\"`\n\tCompress   bool      `json:\"compress\"`\n}\n\ntype Config struct {\n\tMaxProcs         int       `json:\"max_procs\"`\n\tLogConf          LogConfig `json:\"log\"`\n\tBindAddr         string    `json:\"bind_addr\"`\n\tShutdownTimeoutS int       `json:\"shutdown_timeout_s\"`\n\n\tAuditLog auditlog.Config   `json:\"auditlog\"`\n\tAuth     auth_proto.Config `json:\"auth\"`\n\n\tRpc2Server *rpc2.Server `json:\"rpc2_server,omitempty\"`\n}\n\ntype Module struct {\n\tName       string\n\tInitConfig func(args []string) (*Config, error)\n\tSetUp      func() (*rpc.Router, []rpc.ProgressHandler)\n\tSetUp2     func() (*rpc2.Router, []rpc2.Interceptor)\n\tTearDown   func()\n\tgraceful   bool\n}\n\nvar mod *Module\n\nfunc RegisterModule(m *Module) {\n\tmod = m\n\tmod.graceful = false\n}\n\nfunc RegisterGracefulModule(m *Module) {\n\tmod = m\n\tmod.graceful = true\n}\n\nfunc NewLogWriter(cfg *LogConfig) io.Writer {\n\tmaxsize := cfg.MaxSize\n\tif maxsize == 0 {\n\t\tmaxsize = 1024\n\t}\n\tmaxage := cfg.MaxAge\n\tif maxage == 0 {\n\t\tmaxage = 7\n\t}\n\tmaxbackups := cfg.MaxBackups\n\tif maxbackups == 0 {\n\t\tmaxbackups = 7\n\t}\n\treturn \u0026lumberjack.Logger{\n\t\tFilename:   cfg.Filename,\n\t\tMaxSize:    maxsize,\n\t\tMaxAge:     maxage,\n\t\tMaxBackups: maxbackups,\n\t\tLocalTime:  true,\n\t\tCompress:   cfg.Compress,\n\t}\n}\n\nfunc Main(args []string) {\n\tcfg, err := mod.InitConfig(args)\n\tif err != nil {\n\t\tlog.Fatalf(\"init config error: %v\", err)\n\t}\n\tif cfg.MaxProcs \u003e 0 {\n\t\truntime.GOMAXPROCS(cfg.MaxProcs)\n\t}\n\tlog.SetOutputLevel(cfg.LogConf.Level)\n\tregisterLogLevel()\n\tif cfg.LogConf.Filename != \"\" {\n\t\tlog.SetOutput(NewLogWriter(\u0026cfg.LogConf))\n\t}\n\tif cfg.ShutdownTimeoutS \u003c= 0 {\n\t\tcfg.ShutdownTimeoutS = defaultShutdownTimeoutS\n\t}\n\n\tlh, logf, err := auditlog.Open(mod.Name, \u0026cfg.AuditLog)\n\tif err != nil {\n\t\tlog.Fatal(\"failed to open auditlog:\", err)\n\t}\n\tif logf != nil {\n\t\tdefer logf.Close()\n\t}\n\n\tctx, cancel1 := context.WithCancel(context.Background())\n\tdefer cancel1()\n\tconfig.HotReload(ctx, config.ConfName())\n\n\t// new profile handler firstly\n\tprofileHandler := profile.NewProfileHandler(cfg.BindAddr)\n\n\tif mod.SetUp != nil \u0026\u0026 mod.graceful {\n\t\tprogramEntry := func(state *graceful.State) {\n\t\t\trouter, handlers := mod.SetUp()\n\t\t\thttpServer := \u0026http.Server{\n\t\t\t\tAddr:         cfg.BindAddr,\n\t\t\t\tHandler:      reorderMiddleWareHandlers(router, lh, profileHandler, cfg.Auth, handlers),\n\t\t\t\tReadTimeout:  5 * time.Minute,\n\t\t\t\tWriteTimeout: 5 * time.Minute,\n\t\t\t}\n\n\t\t\tlog.Info(\"server is running at:\", cfg.BindAddr)\n\t\t\tgo func() {\n\t\t\t\tif err := httpServer.Serve(state.ListenerFds[0].(*net.TCPListener)); err != nil \u0026\u0026 err != http.ErrServerClosed {\n\t\t\t\t\tlog.Fatal(\"server exits:\", err)\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\t// wait for signal\n\t\t\t\u003c-state.CloseCh\n\t\t\tlog.Info(\"graceful shutdown...\")\n\t\t\tctx, cancel := context.WithTimeout(context.Background(), time.Duration(cfg.ShutdownTimeoutS)*time.Second)\n\t\t\tdefer cancel()\n\t\t\thttpServer.Shutdown(ctx)\n\n\t\t\tif mod.TearDown != nil {\n\t\t\t\tmod.TearDown()\n\t\t\t}\n\t\t}\n\t\tgraceful.Run(\u0026graceful.Config{\n\t\t\tEntry:           programEntry,\n\t\t\tListenAddresses: []string{cfg.BindAddr},\n\t\t})\n\t\treturn\n\t}\n\n\tvar shutdowns []func(context.Context)\n\tif mod.SetUp2 != nil {\n\t\trouter, interceptors := mod.SetUp2()\n\t\trpc2Server := cfg.Rpc2Server\n\t\trpc2Server.Handler = rpc2Handler(router, lh, cfg.Auth, interceptors)\n\t\tlog.Info(\"rpc2 Server is running at\", rpc2Server.Addresses)\n\t\tgo func() {\n\t\t\tif err := rpc2Server.Serve(); err != nil \u0026\u0026 err != rpc2.ErrServerClosed {\n\t\t\t\tlog.Fatalf(\"rpc2 Server exits, err: %v\", err)\n\t\t\t}\n\t\t}()\n\t\tshutdowns = append(shutdowns, func(ctx context.Context) { rpc2Server.Shutdown(ctx) })\n\t}\n\n\tif mod.SetUp != nil {\n\t\trouter, handlers := mod.SetUp()\n\t\thttpServer := \u0026http.Server{\n\t\t\tAddr:         cfg.BindAddr,\n\t\t\tHandler:      reorderMiddleWareHandlers(router, lh, profileHandler, cfg.Auth, handlers),\n\t\t\tReadTimeout:  5 * time.Minute,\n\t\t\tWriteTimeout: 5 * time.Minute,\n\t\t}\n\n\t\tlog.Info(\"Server is running at\", cfg.BindAddr)\n\t\tgo func() {\n\t\t\tif err := httpServer.ListenAndServe(); err != nil \u0026\u0026 err != http.ErrServerClosed {\n\t\t\t\tlog.Fatalf(\"Server exits, err: %v\", err)\n\t\t\t}\n\t\t}()\n\t\tshutdowns = append(shutdowns, func(ctx context.Context) { httpServer.Shutdown(ctx) })\n\t}\n\n\t// wait for signal\n\tch := make(chan os.Signal, 1)\n\tsignal.Notify(ch, syscall.SIGTERM, syscall.SIGINT)\n\tsig := \u003c-ch\n\tlog.Infof(\"receive signal: %s, stop service...\", sig.String())\n\tctx, cancel := context.WithTimeout(context.Background(), time.Duration(cfg.ShutdownTimeoutS)*time.Second)\n\tdefer cancel()\n\tfor _, shutdown := range shutdowns {\n\t\tshutdown(ctx)\n\t}\n\n\tif mod.TearDown != nil {\n\t\tmod.TearDown()\n\t}\n}\n\n// reorderMiddleWareHandlers\n//\n//\tthe order of handlers in MiddlewareHandler has some constraints:\n//\t1. the first is router,\n//\t2. the second is AuditLog handler,\n//\t3. the third is profile handler if config,\n//\t4. the fourth is Auth handler if config,\n//\t5. others self define handlers by modules.\nfunc reorderMiddleWareHandlers(r *rpc.Router, lh, profileHandler rpc.ProgressHandler,\n\tauthCfg auth_proto.Config, handlers []rpc.ProgressHandler,\n) (mux http.Handler) {\n\ths := []rpc.ProgressHandler{lh}\n\tif profileHandler != nil {\n\t\ths = append(hs, profileHandler)\n\t}\n\tif authCfg.EnableAuth \u0026\u0026 authCfg.Secret != \"\" {\n\t\ths = append(hs, auth.New(\u0026authCfg))\n\t}\n\ths = append(hs, handlers...)\n\treturn rpc.MiddlewareHandlerWith(r, hs...)\n}\n\nfunc rpc2Handler(r *rpc2.Router, auditlogIc rpc2.Interceptor,\n\tauthCfg auth_proto.Config, interceptors []rpc2.Interceptor,\n) rpc2.Handle {\n\tr.Interceptor(auditlogIc)\n\tif authCfg.EnableAuth \u0026\u0026 authCfg.Secret != \"\" {\n\t\tr.Interceptor(auth.New(\u0026authCfg))\n\t}\n\tr.Interceptor(interceptors...)\n\treturn r.MakeHandler()\n}\n\nfunc registerLogLevel() {\n\tlogLevelPath, logLevelHandler := log.ChangeDefaultLevelHandler()\n\tprofile.HandleFunc(http.MethodPost, logLevelPath, func(c *rpc.Context) {\n\t\tlogLevelHandler.ServeHTTP(c.Writer, c.Request)\n\t})\n\tprofile.HandleFunc(http.MethodGet, logLevelPath, func(c *rpc.Context) {\n\t\tlogLevelHandler.ServeHTTP(c.Writer, c.Request)\n\t})\n}\n"},"lineMatches":[{"preview":"func Main(args []string) {","lineNumber":112,"offsetAndLengths":[[0,10]]}]},{"__typename":"FileMatch","repository":{"name":"github.com/aarzilli/gdlv"},"file":{"path":"vendor/golang.org/x/exp/shiny/driver/driver.go","url":"/github.com/aarzilli/gdlv/-/blob/vendor/golang.org/x/exp/shiny/driver/driver.go","content":"// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package driver provides the default driver for accessing a screen.\npackage driver // import \"golang.org/x/exp/shiny/driver\"\n\n// TODO: figure out what to say about the responsibility for users of this\n// package to check any implicit dependencies'' LICENSEs. For example, the\n// driver might use third party software outside of golang.org/x, like an X11\n// or OpenGL library.\n\nimport (\n\t\"golang.org/x/exp/shiny/screen\"\n)\n\n// Main is called by the program''s main function to run the graphical\n// application.\n//\n// It calls f on the Screen, possibly in a separate goroutine, as some OS-\n// specific libraries require being on ''the main thread''. It returns when f\n// returns.\nfunc Main(f func(screen.Screen)) {\n\tmain(f)\n}\n"},"lineMatches":[{"preview":"func Main(f func(screen.Screen)) {","lineNumber":22,"offsetAndLengths":[[0,10]]}]},{"__typename":"FileMatch","repository":{"name":"github.com/aarzilli/gdlv"},"file":{"path":"vendor/golang.org/x/exp/shiny/driver/windriver/other.go","url":"/github.com/aarzilli/gdlv/-/blob/vendor/golang.org/x/exp/shiny/driver/windriver/other.go","content":"// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !windows\n\npackage windriver\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\n\t\"golang.org/x/exp/shiny/driver/internal/errscreen\"\n\t\"golang.org/x/exp/shiny/screen\"\n)\n\n// Main is called by the program''s main function to run the graphical\n// application.\n//\n// It calls f on the Screen, possibly in a separate goroutine, as some OS-\n// specific libraries require being on ''the main thread''. It returns when f\n// returns.\nfunc Main(f func(screen.Screen)) {\n\tf(errscreen.Stub(fmt.Errorf(\n\t\t\"windriver: unsupported GOOS/GOARCH %s/%s\", runtime.GOOS, runtime.GOARCH)))\n}\n"},"lineMatches":[{"preview":"func Main(f func(screen.Screen)) {","lineNumber":22,"offsetAndLengths":[[0,10]]}]},{"__typename":"FileMatch","repository":{"name":"github.com/aarzilli/gdlv"},"file":{"path":"vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go","url":"/github.com/aarzilli/gdlv/-/blob/vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go","content":"// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package gldriver provides an OpenGL driver for accessing a screen.\npackage gldriver // import \"golang.org/x/exp/shiny/driver/gldriver\"\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"math\"\n\n\t\"golang.org/x/exp/shiny/driver/internal/errscreen\"\n\t\"golang.org/x/exp/shiny/screen\"\n\t\"golang.org/x/image/math/f64\"\n\t\"golang.org/x/mobile/gl\"\n)\n\n// Main is called by the program''s main function to run the graphical\n// application.\n//\n// It calls f on the Screen, possibly in a separate goroutine, as some OS-\n// specific libraries require being on ''the main thread''. It returns when f\n// returns.\nfunc Main(f func(screen.Screen)) {\n\tif err := main(f); err != nil {\n\t\tf(errscreen.Stub(err))\n\t}\n}\n\nfunc mul(a, b f64.Aff3) f64.Aff3 {\n\treturn f64.Aff3{\n\t\ta[0]*b[0] + a[1]*b[3],\n\t\ta[0]*b[1] + a[1]*b[4],\n\t\ta[0]*b[2] + a[1]*b[5] + a[2],\n\n\t\ta[3]*b[0] + a[4]*b[3],\n\t\ta[3]*b[1] + a[4]*b[4],\n\t\ta[3]*b[2] + a[4]*b[5] + a[5],\n\t}\n}\n\n// writeAff3 must only be called while holding windowImpl.glctxMu.\nfunc writeAff3(glctx gl.Context, u gl.Uniform, a f64.Aff3) {\n\tvar m [9]float32\n\tm[0*3+0] = float32(a[0*3+0])\n\tm[0*3+1] = float32(a[1*3+0])\n\tm[0*3+2] = 0\n\tm[1*3+0] = float32(a[0*3+1])\n\tm[1*3+1] = float32(a[1*3+1])\n\tm[1*3+2] = 0\n\tm[2*3+0] = float32(a[0*3+2])\n\tm[2*3+1] = float32(a[1*3+2])\n\tm[2*3+2] = 1\n\tglctx.UniformMatrix3fv(u, m[:])\n}\n\n// f32Bytes returns the byte representation of float32 values in the given byte\n// order. byteOrder must be either binary.BigEndian or binary.LittleEndian.\nfunc f32Bytes(byteOrder binary.ByteOrder, values ...float32) []byte {\n\tle := false\n\tswitch byteOrder {\n\tcase binary.BigEndian:\n\tcase binary.LittleEndian:\n\t\tle = true\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"invalid byte order %v\", byteOrder))\n\t}\n\n\tb := make([]byte, 4*len(values))\n\tfor i, v := range values {\n\t\tu := math.Float32bits(v)\n\t\tif le {\n\t\t\tb[4*i+0] = byte(u \u003e\u003e 0)\n\t\t\tb[4*i+1] = byte(u \u003e\u003e 8)\n\t\t\tb[4*i+2] = byte(u \u003e\u003e 16)\n\t\t\tb[4*i+3] = byte(u \u003e\u003e 24)\n\t\t} else {\n\t\t\tb[4*i+0] = byte(u \u003e\u003e 24)\n\t\t\tb[4*i+1] = byte(u \u003e\u003e 16)\n\t\t\tb[4*i+2] = byte(u \u003e\u003e 8)\n\t\t\tb[4*i+3] = byte(u \u003e\u003e 0)\n\t\t}\n\t}\n\treturn b\n}\n\n// compileProgram must only be called while holding windowImpl.glctxMu.\nfunc compileProgram(glctx gl.Context, vSrc, fSrc string) (gl.Program, error) {\n\tprogram := glctx.CreateProgram()\n\tif program.Value == 0 {\n\t\treturn gl.Program{}, fmt.Errorf(\"gldriver: no programs available\")\n\t}\n\n\tvertexShader, err := compileShader(glctx, gl.VERTEX_SHADER, vSrc)\n\tif err != nil {\n\t\treturn gl.Program{}, err\n\t}\n\tfragmentShader, err := compileShader(glctx, gl.FRAGMENT_SHADER, fSrc)\n\tif err != nil {\n\t\tglctx.DeleteShader(vertexShader)\n\t\treturn gl.Program{}, err\n\t}\n\n\tglctx.AttachShader(program, vertexShader)\n\tglctx.AttachShader(program, fragmentShader)\n\tglctx.LinkProgram(program)\n\n\t// Flag shaders for deletion when program is unlinked.\n\tglctx.DeleteShader(vertexShader)\n\tglctx.DeleteShader(fragmentShader)\n\n\tif glctx.GetProgrami(program, gl.LINK_STATUS) == 0 {\n\t\tdefer glctx.DeleteProgram(program)\n\t\treturn gl.Program{}, fmt.Errorf(\"gldriver: program compile: %s\", glctx.GetProgramInfoLog(program))\n\t}\n\treturn program, nil\n}\n\n// compileShader must only be called while holding windowImpl.glctxMu.\nfunc compileShader(glctx gl.Context, shaderType gl.Enum, src string) (gl.Shader, error) {\n\tshader := glctx.CreateShader(shaderType)\n\tif shader.Value == 0 {\n\t\treturn gl.Shader{}, fmt.Errorf(\"gldriver: could not create shader (type %v)\", shaderType)\n\t}\n\tglctx.ShaderSource(shader, src)\n\tglctx.CompileShader(shader)\n\tif glctx.GetShaderi(shader, gl.COMPILE_STATUS) == 0 {\n\t\tdefer glctx.DeleteShader(shader)\n\t\treturn gl.Shader{}, fmt.Errorf(\"gldriver: shader compile: %s\", glctx.GetShaderInfoLog(shader))\n\t}\n\treturn shader, nil\n}\n"},"lineMatches":[{"preview":"func Main(f func(screen.Screen)) {","lineNumber":24,"offsetAndLengths":[[0,10]]}]},{"__typename":"FileMatch","repository":{"name":"github.com/aarzilli/gdlv"},"file":{"path":"vendor/golang.org/x/exp/shiny/driver/mtldriver/mtldriver.go","url":"/github.com/aarzilli/gdlv/-/blob/vendor/golang.org/x/exp/shiny/driver/mtldriver/mtldriver.go","content":"// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build darwin \u0026\u0026 cgo\n\n// Package mtldriver provides a Metal driver for accessing a screen.\n//\n// At this time, the Metal API is used only to present the final pixels\n// to the screen. All rendering is performed on the CPU via the image/draw\n// algorithms. Future work is to use mtl.Buffer, mtl.Texture, etc., and\n// do more of the rendering work on the GPU.\npackage mtldriver\n\nimport (\n\t\"runtime\"\n\t\"unsafe\"\n\n\t\"dmitri.shuralyov.com/gpu/mtl\"\n\t\"github.com/go-gl/glfw/v3.3/glfw\"\n\t\"golang.org/x/exp/shiny/driver/internal/errscreen\"\n\t\"golang.org/x/exp/shiny/driver/mtldriver/internal/appkit\"\n\t\"golang.org/x/exp/shiny/driver/mtldriver/internal/coreanim\"\n\t\"golang.org/x/exp/shiny/screen\"\n\t\"golang.org/x/mobile/event/key\"\n\t\"golang.org/x/mobile/event/mouse\"\n\t\"golang.org/x/mobile/event/paint\"\n\t\"golang.org/x/mobile/event/size\"\n)\n\nfunc init() {\n\truntime.LockOSThread()\n}\n\n// Main is called by the program''s main function to run the graphical\n// application.\n//\n// It calls f on the Screen, possibly in a separate goroutine, as some OS-\n// specific libraries require being on ''the main thread''. It returns when f\n// returns.\nfunc Main(f func(screen.Screen)) {\n\tif err := main(f); err != nil {\n\t\tf(errscreen.Stub(err))\n\t}\n}\n\nfunc main(f func(screen.Screen)) error {\n\tdevice, err := mtl.CreateSystemDefaultDevice()\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = glfw.Init()\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer glfw.Terminate()\n\tglfw.WindowHint(glfw.ClientAPI, glfw.NoAPI)\n\t{\n\t\t// TODO(dmitshur): Delete this when https://github.com/go-gl/glfw/issues/272 is resolved.\n\t\t// Post an empty event from the main thread before it can happen in a non-main thread,\n\t\t// to work around https://github.com/glfw/glfw/issues/1649.\n\t\tglfw.PostEmptyEvent()\n\t}\n\tvar (\n\t\tdone            = make(chan struct{})\n\t\tnewWindowCh     = make(chan newWindowReq, 1)\n\t\treleaseWindowCh = make(chan releaseWindowReq, 1)\n\t)\n\tgo func() {\n\t\tf(\u0026screenImpl{\n\t\t\tnewWindowCh: newWindowCh,\n\t\t})\n\t\tclose(done)\n\t\tglfw.PostEmptyEvent() // Break main loop out of glfw.WaitEvents so it can receive on done.\n\t}()\n\tfor {\n\t\tselect {\n\t\tcase \u003c-done:\n\t\t\treturn nil\n\t\tcase req := \u003c-newWindowCh:\n\t\t\tw, err := newWindow(device, releaseWindowCh, req.opts)\n\t\t\treq.respCh \u003c- newWindowResp{w, err}\n\t\tcase req := \u003c-releaseWindowCh:\n\t\t\treq.window.Destroy()\n\t\t\treq.respCh \u003c- struct{}{}\n\t\tdefault:\n\t\t\tglfw.WaitEvents()\n\t\t}\n\t}\n}\n\ntype newWindowReq struct {\n\topts   *screen.NewWindowOptions\n\trespCh chan newWindowResp\n}\n\ntype newWindowResp struct {\n\tw   screen.Window\n\terr error\n}\n\ntype releaseWindowReq struct {\n\twindow *glfw.Window\n\trespCh chan struct{}\n}\n\n// newWindow creates a new GLFW window.\n// It must be called on the main thread.\nfunc newWindow(device mtl.Device, releaseWindowCh chan releaseWindowReq, opts *screen.NewWindowOptions) (screen.Window, error) {\n\twidth, height := optsSize(opts)\n\twindow, err := glfw.CreateWindow(width, height, opts.GetTitle(), nil, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tml := coreanim.MakeMetalLayer()\n\tml.SetDevice(device)\n\tml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm)\n\tml.SetMaximumDrawableCount(3)\n\tml.SetDisplaySyncEnabled(true)\n\tcv := appkit.NewWindow(unsafe.Pointer(window.GetCocoaWindow())).ContentView()\n\tcv.SetLayer(ml)\n\tcv.SetWantsLayer(true)\n\n\tw := \u0026windowImpl{\n\t\tdevice:          device,\n\t\twindow:          window,\n\t\treleaseWindowCh: releaseWindowCh,\n\t\tml:              ml,\n\t\tcq:              device.MakeCommandQueue(),\n\t}\n\n\t// Set callbacks.\n\tframebufferSizeCallback := func(_ *glfw.Window, width, height int) {\n\t\tw.Send(size.Event{\n\t\t\tWidthPx:  width,\n\t\t\tHeightPx: height,\n\t\t\t// TODO(dmitshur): ppp,\n\t\t})\n\t\tw.Send(paint.Event{External: true})\n\t}\n\twindow.SetFramebufferSizeCallback(framebufferSizeCallback)\n\twindow.SetCursorPosCallback(func(_ *glfw.Window, x, y float64) {\n\t\tconst scale = 2 // TODO(dmitshur): compute dynamically\n\t\tw.Send(mouse.Event{X: float32(x * scale), Y: float32(y * scale)})\n\t})\n\twindow.SetMouseButtonCallback(func(_ *glfw.Window, b glfw.MouseButton, a glfw.Action, mods glfw.ModifierKey) {\n\t\tbtn := glfwMouseButton(b)\n\t\tif btn == mouse.ButtonNone {\n\t\t\treturn\n\t\t}\n\t\tconst scale = 2 // TODO(dmitshur): compute dynamically\n\t\tx, y := window.GetCursorPos()\n\t\tw.Send(mouse.Event{\n\t\t\tX: float32(x * scale), Y: float32(y * scale),\n\t\t\tButton:    btn,\n\t\t\tDirection: glfwMouseDirection(a),\n\t\t\t// TODO(dmitshur): set Modifiers\n\t\t})\n\t})\n\twindow.SetKeyCallback(func(_ *glfw.Window, k glfw.Key, _ int, a glfw.Action, mods glfw.ModifierKey) {\n\t\tcode := glfwKeyCode(k)\n\t\tif code == key.CodeUnknown {\n\t\t\treturn\n\t\t}\n\t\tw.Send(key.Event{\n\t\t\tCode:      code,\n\t\t\tDirection: glfwKeyDirection(a),\n\t\t\t// TODO(dmitshur): set Modifiers\n\t\t})\n\t})\n\t// TODO(dmitshur): set CharModsCallback to catch text (runes) that are typed,\n\t//                 and perhaps try to unify key pressed + character typed into single event\n\twindow.SetCloseCallback(func(*glfw.Window) {\n\t\tw.lifecycler.SetDead(true)\n\t\tw.lifecycler.SendEvent(w, nil)\n\t})\n\n\t// TODO(dmitshur): more fine-grained tracking of whether window is visible and/or focused\n\tw.lifecycler.SetDead(false)\n\tw.lifecycler.SetVisible(true)\n\tw.lifecycler.SetFocused(true)\n\tw.lifecycler.SendEvent(w, nil)\n\n\t// Send the initial size and paint events.\n\twidth, height = window.GetFramebufferSize()\n\tframebufferSizeCallback(window, width, height)\n\n\treturn w, nil\n}\n\nfunc optsSize(opts *screen.NewWindowOptions) (width, height int) {\n\twidth, height = 1024/2, 768/2\n\tif opts != nil {\n\t\tif opts.Width \u003e 0 {\n\t\t\twidth = opts.Width\n\t\t}\n\t\tif opts.Height \u003e 0 {\n\t\t\theight = opts.Height\n\t\t}\n\t}\n\treturn width, height\n}\n\nfunc glfwMouseButton(button glfw.MouseButton) mouse.Button {\n\tswitch button {\n\tcase glfw.MouseButtonLeft:\n\t\treturn mouse.ButtonLeft\n\tcase glfw.MouseButtonRight:\n\t\treturn mouse.ButtonRight\n\tcase glfw.MouseButtonMiddle:\n\t\treturn mouse.ButtonMiddle\n\tdefault:\n\t\treturn mouse.ButtonNone\n\t}\n}\n\nfunc glfwMouseDirection(action glfw.Action) mouse.Direction {\n\tswitch action {\n\tcase glfw.Press:\n\t\treturn mouse.DirPress\n\tcase glfw.Release:\n\t\treturn mouse.DirRelease\n\tdefault:\n\t\tpanic(\"unreachable\")\n\t}\n}\n\nfunc glfwKeyCode(k glfw.Key) key.Code {\n\t// TODO(dmitshur): support more keys\n\tswitch k {\n\tcase glfw.KeyEnter:\n\t\treturn key.CodeReturnEnter\n\tcase glfw.KeyEscape:\n\t\treturn key.CodeEscape\n\tdefault:\n\t\treturn key.CodeUnknown\n\t}\n}\n\nfunc glfwKeyDirection(action glfw.Action) key.Direction {\n\tswitch action {\n\tcase glfw.Press:\n\t\treturn key.DirPress\n\tcase glfw.Release:\n\t\treturn key.DirRelease\n\tcase glfw.Repeat:\n\t\treturn key.DirNone\n\tdefault:\n\t\tpanic(\"unreachable\")\n\t}\n}\n"},"lineMatches":[{"preview":"func Main(f func(screen.Screen)) {","lineNumber":40,"offsetAndLengths":[[0,10]]},{"preview":"func main(f func(screen.Screen)) error {","lineNumber":46,"offsetAndLengths":[[0,10]]}]}]}}}}'
    headers:
      Content-Type:
      - application/json
    status: 200 OK
    code: 200
    duration: 1.391930625s
- id: 3
  request:
    proto: HTTP/1.1
    proto_major: 1
    proto_minor: 1
    content_length: 48618
    host: ""
    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. **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). When reading, 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, decide, act. Complete the ENTIRE task before stopping. Never stop mid-task. Never refuse work based on scope or complexity - break it down and do it.\\n3. **TEST AFTER CHANGES**: Run tests immediately after each modification\\n4. **BE CONCISE**: Under 4 lines unless user asks for detail\\n5. **USE EXACT MATCHES**: When editing, match text exactly including whitespace, indentation, and line breaks\\n6. **NEVER COMMIT**: Unless user explicitly says \\\"commit\\\"\\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. When adding comments, 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. Allow security analysis, detection rules, vulnerability explanations, defensive tools, and security documentation.\\n10. **NO URL GUESSING**: Never generate or guess URLs unless you are confident they are for helping with programming. 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 by the user.\\n12. **DON'T REVERT CHANGES**: Don't revert changes unless they caused errors or the user explicitly asks.\\n13. **COMPLETE THE TASK**: Never stop mid-task with \\\"Next:\\\" or \\\"Will do:\\\" statements. If you describe what needs to be done, DO IT immediately. Only stop when everything is finished.\\n14. **NEVER REFUSE BASED ON SCOPE**: Never refuse tasks because they seem large or complex. Break them into steps and complete them. Only stop if you encounter actual blocking errors (missing dependencies, compile failures, etc.), not perceived difficulty.\\n</critical_rules>\\n\\n<communication_style>\\nKeep responses minimal:\\n- Under 4 lines of text (tool use doesn't count)\\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\\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- 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\\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**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<task_scope>\\n**No task is too large**:\\n- Break complex tasks into logical steps\\n- Complete each step fully before moving to next\\n- If a task has 10 parts, do all 10 parts\\n- Don't estimate effort or refuse based on scope\\n- Only stop if you hit actual errors (compile failures, missing files, etc.)\\n\\n**For large refactors or implementations**:\\n- Start with core functionality\\n- Build incrementally\\n- Test at each step\\n- Keep going until fully complete\\n\\nThere are no \\\"session limits\\\" - continue until the task is done or you hit a real blocker.\\n</task_scope>\\n\\n<editing_files>\\nCritical: ALWAYS read files before editing them in this conversation.\\n\\nWhen using edit tools:\\n1. Read the file 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<error_handling>\\nWhen errors occur:\\n1. Read complete error message\\n2. Understand root cause\\n3. Try different approach (don't repeat same action)\\n4. Search for similar code that works\\n5. Make targeted fix\\n6. Test to verify\\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- 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\\n<bash_commands>\\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 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\\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/openai-gpt-5/sourcegraph_tool\\nIs directory a git repo: no\\nPlatform: linux\\nToday's date: 1/1/2025\\n\\n</env>\\n\\n\\n\\n\\n\",\"role\":\"system\"},{\"content\":\"use sourcegraph to search for 'func main' in Go repositories\",\"role\":\"user\"},{\"tool_calls\":[{\"id\":\"call_aJVDFP0W6iLFKxt3YI1ufrYh\",\"function\":{\"arguments\":\"{\\\"query\\\":\\\"lang:go file:\\\\\\\\.go$ content:\\\\\\\"func main(\\\\\\\" -file:test -file:_test.go count:10\\\",\\\"count\\\":10,\\\"context_window\\\":5,\\\"timeout\\\":60}\",\"name\":\"sourcegraph\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"# Sourcegraph Search Results\\n\\nFound 10 matches across 10 results\\n(Result limit reached, try a more specific query)\\n\\n## Result 1: github.com/yinchengtsinghua/go-ethereum-chinese/cmd/wnode/main.go\\n\\nURL: /github.com/yinchengtsinghua/go-ethereum-chinese/-/blob/cmd/wnode/main.go\\n\\n```\\n111| \\targIDFile  = flag.String(\\\"idfile\\\", \\\"\\\", \\\"file name with node id (private key)\\\")\\n112| argEnode   = flag.String(\\\"boot\\\", \\\"\\\", \\\"bootstrap node you want to connect to (e.g. enode://E454……08D50@52.176.211.200:16428）”）\\n113| \\targTopic   = flag.String(\\\"topic\\\", \\\"\\\", \\\"topic in hexadecimal format (e.g. 70a4beef)\\\")\\n114| \\targSaveDir = flag.String(\\\"savedir\\\", \\\"\\\", \\\"directory where all incoming messages will be saved as files\\\")\\n115| )\\n116|  func main() {\\n117| func main() {\\n118| \\tprocessArgs()\\n119| \\tinitialize()\\n120| \\trun()\\n121| \\tshutdown()\\n```\\n\\n## Result 2: github.com/sergev/vak-opensource/languages/go/lisp-light.go\\n\\nURL: /github.com/sergev/vak-opensource/-/blob/languages/go/lisp-light.go\\n\\n```\\n1525| \\t}\\n1526| }\\n1527| \\n1528| // Main runs each element of args as a name of Lisp script file.\\n1529| // It ignores args[0].\\n1530|  func Main(args []string) int {\\n1531| func Main(args []string) int {\\n1532| \\tinterp := NewInterp()\\n1533| \\tss := strings.NewReader(Prelude)\\n1534| \\tif !Run(interp, ss) {\\n1535| \\t\\treturn 1\\n```\\n\\n```\\n1555| \\t\\t\\t}\\n1556| \\t\\t}\\n1557| \\t}\\n1558| \\treturn 0\\n1559| }\\n1560|  func main() {\\n1561| func main() {\\n1562| \\tos.Exit(Main(os.Args))\\n1563| }\\n1564| \\n1565| // Prelude is an initialization script of Lisp.\\n```\\n\\n## Result 3: github.com/devspace-sh/devspace/vendor/github.com/google/gnostic-models/extensions/extensions.go\\n\\nURL: /github.com/devspace-sh/devspace/-/blob/vendor/github.com/google/gnostic-models/extensions/extensions.go\\n\\n```\\n23| \\t\\\"github.com/golang/protobuf/ptypes\\\"\\n24| )\\n25| \\n26| type extensionHandler func(name string, yamlInput string) (bool, proto.Message, error)\\n27| \\n28|  func Main(handler extensionHandler) {\\n29| func Main(handler extensionHandler) {\\n30| \\t// unpack the request\\n31| \\tdata, err := ioutil.ReadAll(os.Stdin)\\n32| \\tif err != nil {\\n33| \\t\\tlog.Println(\\\"File error:\\\", err.Error())\\n```\\n\\n## Result 4: github.com/cubefs/cubefs/blobstore/cmd/cmd.go\\n\\nURL: /github.com/cubefs/cubefs/-/blob/blobstore/cmd/cmd.go\\n\\n```\\n107| \\t\\tMaxBackups: maxbackups,\\n108| \\t\\tLocalTime:  true,\\n109| \\t\\tCompress:   cfg.Compress,\\n110| \\t}\\n111| }\\n112|  func Main(args []string) {\\n113| func Main(args []string) {\\n114| \\tcfg, err := mod.InitConfig(args)\\n115| \\tif err != nil {\\n116| \\t\\tlog.Fatalf(\\\"init config error: %v\\\", err)\\n117| \\t}\\n```\\n\\n## Result 5: github.com/aarzilli/gdlv/vendor/golang.org/x/exp/shiny/driver/driver.go\\n\\nURL: /github.com/aarzilli/gdlv/-/blob/vendor/golang.org/x/exp/shiny/driver/driver.go\\n\\n```\\n17| // Main is called by the program's main function to run the graphical\\n18| // application.\\n19| //\\n20| // It calls f on the Screen, possibly in a separate goroutine, as some OS-\\n21| // specific libraries require being on 'the main thread'. It returns when f\\n22|  func Main(f func(screen.Screen)) {\\n23| func Main(f func(screen.Screen)) {\\n24| \\tmain(f)\\n25| }\\n26| \\n```\\n\\n## Result 6: github.com/aarzilli/gdlv/vendor/golang.org/x/exp/shiny/driver/windriver/other.go\\n\\nURL: /github.com/aarzilli/gdlv/-/blob/vendor/golang.org/x/exp/shiny/driver/windriver/other.go\\n\\n```\\n17| // Main is called by the program's main function to run the graphical\\n18| // application.\\n19| //\\n20| // It calls f on the Screen, possibly in a separate goroutine, as some OS-\\n21| // specific libraries require being on 'the main thread'. It returns when f\\n22|  func Main(f func(screen.Screen)) {\\n23| func Main(f func(screen.Screen)) {\\n24| \\tf(errscreen.Stub(fmt.Errorf(\\n25| \\t\\t\\\"windriver: unsupported GOOS/GOARCH %s/%s\\\", runtime.GOOS, runtime.GOARCH)))\\n26| }\\n27| \\n```\\n\\n## Result 7: github.com/aarzilli/gdlv/vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go\\n\\nURL: /github.com/aarzilli/gdlv/-/blob/vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go\\n\\n```\\n19| // Main is called by the program's main function to run the graphical\\n20| // application.\\n21| //\\n22| // It calls f on the Screen, possibly in a separate goroutine, as some OS-\\n23| // specific libraries require being on 'the main thread'. It returns when f\\n24|  func Main(f func(screen.Screen)) {\\n25| func Main(f func(screen.Screen)) {\\n26| \\tif err := main(f); err != nil {\\n27| \\t\\tf(errscreen.Stub(err))\\n28| \\t}\\n29| }\\n```\\n\\n## Result 8: github.com/aarzilli/gdlv/vendor/golang.org/x/exp/shiny/driver/mtldriver/mtldriver.go\\n\\nURL: /github.com/aarzilli/gdlv/-/blob/vendor/golang.org/x/exp/shiny/driver/mtldriver/mtldriver.go\\n\\n```\\n35| // Main is called by the program's main function to run the graphical\\n36| // application.\\n37| //\\n38| // It calls f on the Screen, possibly in a separate goroutine, as some OS-\\n39| // specific libraries require being on 'the main thread'. It returns when f\\n40|  func Main(f func(screen.Screen)) {\\n41| func Main(f func(screen.Screen)) {\\n42| \\tif err := main(f); err != nil {\\n43| \\t\\tf(errscreen.Stub(err))\\n44| \\t}\\n45| }\\n```\\n\\n```\\n41| func Main(f func(screen.Screen)) {\\n42| \\tif err := main(f); err != nil {\\n43| \\t\\tf(errscreen.Stub(err))\\n44| \\t}\\n45| }\\n46|  func main(f func(screen.Screen)) error {\\n47| func main(f func(screen.Screen)) error {\\n48| \\tdevice, err := mtl.CreateSystemDefaultDevice()\\n49| \\tif err != nil {\\n50| \\t\\treturn err\\n51| \\t}\\n```\\n\\n\",\"tool_call_id\":\"call_aJVDFP0W6iLFKxt3YI1ufrYh\",\"role\":\"tool\"}],\"model\":\"gpt-5\",\"max_completion_tokens\":10000,\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"bash\",\"strict\":false,\"description\":\"Executes bash commands in persistent shell session with timeout and security measures.\\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. Output Processing: Truncate if exceeds 30000 characters\\n5. Return Result: Include errors, metadata with <cwd></cwd> tags\\n</execution_steps>\\n\\n<usage_notes>\\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 '&&', 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</usage_notes>\\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 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 &lt;&lt;'EOF'\\n   Commit message here.\\n\\n   \U0001F498 Generated with Crush\\n\\n\\n   Co-Authored-By: Crush <crush@charm.land>\\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</git_commits>\\n\\n<pull_requests>\\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 <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   - 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 &lt;&lt;'EOF'\\n\\n   ## Summary\\n\\n   &lt;1-3 bullet points>\\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</pull_requests>\\n\\n<examples>\\nGood: pytest /foo/bar/tests\\nBad: cd /foo/bar && pytest tests\\n</examples>\\n\",\"parameters\":{\"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\"}},\"type\":\"function\"},{\"function\":{\"name\":\"download\",\"strict\":false,\"description\":\"Downloads binary data from URL and saves to local file.\\n\\n<usage>\\n- Provide URL to download from\\n- Specify local file path where content should be saved\\n- Optional timeout for request\\n</usage>\\n\\n<features>\\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</features>\\n\\n<limitations>\\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</limitations>\\n\\n<tips>\\n- Use absolute paths or paths relative to working directory\\n- Set appropriate timeouts for large files or slow connections\\n</tips>\\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\":\"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<prerequisites>\\n1. Use View tool to understand file contents and context\\n2. For new files: Use LS tool to verify parent directory exists\\n3. **CRITICAL**: Note exact whitespace, indentation, and formatting from View output\\n</prerequisites>\\n\\n<parameters>\\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</parameters>\\n\\n<special_cases>\\n\\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  </special_cases>\\n\\n<critical_requirements>\\nEXACT MATCHING: The tool is extremely literal. Text must match **EXACTLY**\\n\\n- Every space and tab character\\n- Every blank line\\n- Every newline character\\n- Indentation level (count the spaces/tabs)\\n- Comment spacing (`// comment` vs `//comment`)\\n- Brace positioning (`func() {` vs `func(){`)\\n\\nCommon failures:\\n\\n```\\nExpected: \\\"    func foo() {\\\"     (4 spaces)\\nProvided: \\\"  func foo() {\\\"       (2 spaces) ❌ FAILS\\n\\nExpected: \\\"}\\\\n\\\\nfunc bar() {\\\"    (2 newlines)\\nProvided: \\\"}\\\\nfunc bar() {\\\"      (1 newline) ❌ FAILS\\n\\nExpected: \\\"// Comment\\\"           (space after //)\\nProvided: \\\"//Comment\\\"            (no space) ❌ FAILS\\n```\\n\\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- If text appears multiple times, add more context to make it unique\\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: Before every edit\\n\\n1. View the file and locate exact target location\\n2. Check how many instances of target text exist\\n3. Copy the EXACT text including all whitespace\\n4. Verify you have enough context for unique identification\\n5. Double-check indentation matches (count spaces/tabs)\\n6. Plan separate calls or use replace_all for multiple changes\\n   </critical_requirements>\\n\\n<warnings>\\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- Indentation is off by even one space\\n- Missing or extra blank lines\\n- Wrong tabs vs spaces\\n</warnings>\\n\\n<recovery_steps>\\nIf you get \\\"old_string not found in file\\\":\\n\\n1. **View the file again** at the specific location\\n2. **Copy more context** - include entire function if needed\\n3. **Check whitespace**:\\n   - Count indentation spaces/tabs\\n   - Look for blank lines\\n   - Check for trailing spaces\\n4. **Verify character-by-character** that your old_string matches\\n5. **Never guess** - always View the file to get exact text\\n   </recovery_steps>\\n\\n<best_practices>\\n\\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- **When in doubt, include MORE context rather than less**\\n- Match the existing code style exactly (spaces, tabs, blank lines)\\n  </best_practices>\\n\\n<whitespace_checklist>\\nBefore submitting an edit, verify:\\n\\n- [ ] Viewed the file first\\n- [ ] Counted indentation spaces/tabs\\n- [ ] Included blank lines if they exist\\n- [ ] Matched brace/bracket positioning\\n- [ ] Included 3-5 lines of surrounding context\\n- [ ] Verified text appears exactly once (or using replace_all)\\n- [ ] Copied text character-for-character, not approximated\\n      </whitespace_checklist>\\n\\n<examples>\\n✅ Correct: Exact match with context\\n\\n```\\nold_string: \\\"func ProcessData(input string) error {\\\\n    if input == \\\\\\\"\\\\\\\" {\\\\n        return errors.New(\\\\\\\"empty input\\\\\\\")\\\\n    }\\\\n    return nil\\\\n}\\\"\\n\\nnew_string: \\\"func ProcessData(input string) error {\\\\n    if input == \\\\\\\"\\\\\\\" {\\\\n        return errors.New(\\\\\\\"empty input\\\\\\\")\\\\n    }\\\\n    // New validation\\\\n    if len(input) > 1000 {\\\\n        return errors.New(\\\\\\\"input too long\\\\\\\")\\\\n    }\\\\n    return nil\\\\n}\\\"\\n```\\n\\n❌ Incorrect: Not enough context\\n\\n```\\nold_string: \\\"return nil\\\"  // Appears many times!\\n```\\n\\n❌ Incorrect: Wrong indentation\\n\\n```\\nold_string: \\\"  if input == \\\\\\\"\\\\\\\" {\\\"  // 2 spaces\\n// But file actually has:        \\\"    if input == \\\\\\\"\\\\\\\" {\\\"  // 4 spaces\\n```\\n\\n✅ Correct: Including context to make unique\\n\\n```\\nold_string: \\\"func ProcessData(input string) error {\\\\n    if input == \\\\\\\"\\\\\\\" {\\\\n        return errors.New(\\\\\\\"empty input\\\\\\\")\\\\n    }\\\\n    return nil\\\"\\n```\\n\\n</examples>\\n\\n<windows_notes>\\n\\n- Forward slashes work throughout (C:/path/file)\\n- File permissions handled automatically\\n- Line endings converted automatically (\\\\n ↔ \\\\r\\\\n)\\n  </windows_notes>\\n\",\"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\":\"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<prerequisites>\\n1. Use View tool to understand file contents and context\\n2. Verify directory path is correct\\n3. CRITICAL: Note exact whitespace, indentation, and formatting from View output\\n</prerequisites>\\n\\n<parameters>\\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</parameters>\\n\\n<operation>\\n- Edits applied sequentially in provided order.\\n- Each edit operates on result of previous edit.\\n- ATOMIC: If any single edit fails, the entire operation fails and no changes are applied.\\n- Ideal for several changes to different parts of same file.\\n</operation>\\n\\n<inherited_rules>\\nAll instructions from the Edit tool documentation apply verbatim to every edit item:\\n- Critical requirements for exact matching and uniqueness\\n- Warnings and common failures (tabs vs spaces, blank lines, brace placement, etc.)\\n- Verification steps before using, recovery steps, best practices, and whitespace checklist\\nUse the same level of precision as Edit. Multiedit often fails due to formatting mismatches—double-check whitespace for every edit.\\n</inherited_rules>\\n\\n<critical_requirements>\\n1. Apply Edit tool rules to EACH edit (see edit.md).\\n2. Edits are atomic—either all succeed or none are applied.\\n3. Plan sequence carefully: earlier edits change the file content that later edits must match.\\n4. Ensure each old_string is unique at its application time (after prior edits).\\n</critical_requirements>\\n\\n<verification_before_using>\\n1. View the file and copy exact text (including whitespace) for each target.\\n2. Check how many instances each old_string has BEFORE the sequence starts.\\n3. Dry-run mentally: after applying edit #N, will edit #N+1 still match? Adjust old_string/new_string accordingly.\\n4. Prefer fewer, larger context blocks over many tiny fragments that are easy to misalign.\\n5. If edits are independent, consider separate multiedit batches per logical region.\\n</verification_before_using>\\n\\n<warnings>\\n- Operation fails if any old_string doesn’t match exactly (including whitespace) or equals new_string.\\n- Earlier edits can invalidate later matches (added/removed spaces, lines, or reordered text).\\n- Mixed tabs/spaces, trailing spaces, or missing blank lines commonly cause failures.\\n- replace_all may affect unintended regions—use carefully or provide more context.\\n</warnings>\\n\\n<recovery_steps>\\nIf the operation fails:\\n1. Identify the first failing edit (start from top; test subsets to isolate).\\n2. View the file again and copy more surrounding context for that edit.\\n3. Recalculate later old_string values based on the file state AFTER preceding edits.\\n4. Reduce the batch (apply earlier stable edits first), then follow up with the rest.\\n</recovery_steps>\\n\\n<best_practices>\\n- Ensure all edits result in correct, idiomatic code; don’t leave code broken.\\n- Use absolute file paths (starting with /).\\n- Use replace_all only when you’re certain; otherwise provide unique context.\\n- Match existing style exactly (spaces, tabs, blank lines).\\n- Test after the operation; if it fails, fix and retry in smaller chunks.\\n</best_practices>\\n\\n<whitespace_checklist>\\nFor EACH edit, verify:\\n- [ ] Viewed the file first\\n- [ ] Counted indentation spaces/tabs\\n- [ ] Included blank lines if present\\n- [ ] Matched brace/bracket positioning\\n- [ ] Included 3–5 lines of surrounding context\\n- [ ] Verified text appears exactly once (or using replace_all deliberately)\\n- [ ] Copied text character-for-character, not approximated\\n</whitespace_checklist>\\n\\n<examples>\\n✅ Correct: Sequential edits where the second match accounts for the first change\\n\\n```\\nedits: [\\n  {\\n    old_string: \\\"func A() {\\\\n    doOld()\\\\n}\\\",\\n    new_string: \\\"func A() {\\\\n    doNew()\\\\n}\\\",\\n  },\\n  {\\n    // Uses context that still exists AFTER the first replacement\\n    old_string: \\\"func B() {\\\\n    callA()\\\\n}\\\",\\n    new_string: \\\"func B() {\\\\n    callA()\\\\n    logChange()\\\\n}\\\",\\n  },\\n]\\n```\\n\\n❌ Incorrect: Second old_string no longer matches due to whitespace change introduced by the first edit\\n\\n```\\nedits: [\\n  {\\n    old_string: \\\"func A() {\\\\n    doOld()\\\\n}\\\",\\n    new_string: \\\"func A() {\\\\n\\\\n    doNew()\\\\n}\\\", // Added extra blank line\\n  },\\n  {\\n    old_string: \\\"func A() {\\\\n    doNew()\\\\n}\\\", // Missing the new blank line, will FAIL\\n    new_string: \\\"func A() {\\\\n    doNew()\\\\n    logChange()\\\\n}\\\",\\n  },\\n]\\n```\\n</examples>\\n\",\"parameters\":{\"properties\":{\"edits\":{\"description\":\"Array of edit operations to perform sequentially on the file\",\"items\":{},\"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\":\"glob\",\"strict\":false,\"description\":\"Fast file pattern matching tool that finds files by name/pattern, returning paths sorted by modification time (newest first).\\n\\n<usage>\\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</usage>\\n\\n<pattern_syntax>\\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</pattern_syntax>\\n\\n<examples>\\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</examples>\\n\\n<limitations>\\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</limitations>\\n\\n<cross_platform>\\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</cross_platform>\\n\\n<tips>\\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</tips>\\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\":\"Fast content search tool that finds files containing specific text/patterns, returning matching paths sorted by modification time (newest first).\\n\\n<usage>\\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</usage>\\n\\n<regex_syntax>\\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</regex_syntax>\\n\\n<include_patterns>\\n- '\\\\*.js' - Only search JavaScript files\\n- '\\\\*.{ts,tsx}' - Only search TypeScript files\\n- '\\\\*.go' - Only search Go files\\n</include_patterns>\\n\\n<limitations>\\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</limitations>\\n\\n<ignore_support>\\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</ignore_support>\\n\\n<cross_platform>\\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</cross_platform>\\n\\n<tips>\\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</tips>\\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\":\"Shows files and subdirectories in tree structure for exploring project organization.\\n\\n<usage>\\n- Provide path to list (defaults to current working directory)\\n- Optional glob patterns to ignore\\n- Results displayed in tree structure\\n</usage>\\n\\n<features>\\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</features>\\n\\n<limitations>\\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</limitations>\\n\\n<cross_platform>\\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</cross_platform>\\n\\n<tips>\\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</tips>\\n\",\"parameters\":{\"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\":[],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"sourcegraph\",\"strict\":false,\"description\":\"Search code across public repositories using Sourcegraph's GraphQL API.\\n\\n<usage>\\n- Provide search query using Sourcegraph syntax\\n- Optional result count (default: 10, max: 20)\\n- Optional timeout for request\\n</usage>\\n\\n<basic_syntax>\\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</basic_syntax>\\n\\n<key_filters>\\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</key_filters>\\n\\n<examples>\\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</examples>\\n\\n<boolean_operators>\\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</boolean_operators>\\n\\n<limitations>\\n- Only searches public repositories\\n- Rate limits may apply\\n- Complex queries take longer\\n- Max 20 results per query\\n</limitations>\\n\\n<tips>\\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</tips>\\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\":\"Reads and displays file contents with line numbers for examining code, logs, or text data.\\n\\n<usage>\\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</usage>\\n\\n<features>\\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</features>\\n\\n<limitations>\\n- Max file size: 250KB\\n- Default limit: 2000 lines\\n- Lines >2000 chars truncated\\n- Cannot display binary files/images (identifies them)\\n</limitations>\\n\\n<cross_platform>\\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</cross_platform>\\n\\n<tips>\\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</tips>\\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 2000)\",\"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\":\"Creates or updates files in filesystem for saving/modifying text content.\\n\\n<usage>\\n- Provide file path to write\\n- Include content to write to file\\n- Tool creates necessary parent directories automatically\\n</usage>\\n\\n<features>\\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</features>\\n\\n<limitations>\\n- Read file before writing to avoid conflicts\\n- Cannot append (rewrites entire file)\\n</limitations>\\n\\n<cross_platform>\\n- Use forward slashes (/) for compatibility\\n</cross_platform>\\n\\n<tips>\\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</tips>\\n\",\"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}"
    headers:
      Accept:
      - application/json
      Content-Type:
      - application/json
      User-Agent:
      - OpenAI/Go 2.7.1
    url: https://api.openai.com/v1/chat/completions
    method: POST
  response:
    proto: HTTP/2.0
    proto_major: 2
    proto_minor: 0
    content_length: -1
    body: |+
      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"vLQSWcBgMy"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"Found"},"finish_reason":null}],"usage":null,"obfuscation":"hhoF2vR"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" "},"finish_reason":null}],"usage":null,"obfuscation":"Y5fNHBhW1lE"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"10"},"finish_reason":null}],"usage":null,"obfuscation":"KlflKAD0Pl"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" matches"},"finish_reason":null}],"usage":null,"obfuscation":"w2IF"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}],"usage":null,"obfuscation":"aXj30qklZ10"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" Examples"},"finish_reason":null}],"usage":null,"obfuscation":"R6U"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":":\n"},"finish_reason":null}],"usage":null,"obfuscation":"jzlJQk7hk"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"-"},"finish_reason":null}],"usage":null,"obfuscation":"oULllVlGxrU"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" github"},"finish_reason":null}],"usage":null,"obfuscation":"GAqul"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".com"},"finish_reason":null}],"usage":null,"obfuscation":"w73hVZ4W"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/y"},"finish_reason":null}],"usage":null,"obfuscation":"SbRgZe17Ww"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"inch"},"finish_reason":null}],"usage":null,"obfuscation":"9xC1PH4d"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"eng"},"finish_reason":null}],"usage":null,"obfuscation":"MdPgWHNTr"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ts"},"finish_reason":null}],"usage":null,"obfuscation":"HVJFOQfBrZ"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ing"},"finish_reason":null}],"usage":null,"obfuscation":"EJi1uO9PQ"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"hua"},"finish_reason":null}],"usage":null,"obfuscation":"yuJrSwYYa"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/go"},"finish_reason":null}],"usage":null,"obfuscation":"yrNyCZemG"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"-"},"finish_reason":null}],"usage":null,"obfuscation":"UezMniCAZfB"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ethereum"},"finish_reason":null}],"usage":null,"obfuscation":"wS2E"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"-ch"},"finish_reason":null}],"usage":null,"obfuscation":"eRMHTbIsU"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"inese"},"finish_reason":null}],"usage":null,"obfuscation":"ipyfqvH"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/c"},"finish_reason":null}],"usage":null,"obfuscation":"2qyWpwcJhZ"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"md"},"finish_reason":null}],"usage":null,"obfuscation":"SMbQCJiLlz"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/"},"finish_reason":null}],"usage":null,"obfuscation":"E5kT4r76fPZ"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"wn"},"finish_reason":null}],"usage":null,"obfuscation":"wvsGKAanpJ"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ode"},"finish_reason":null}],"usage":null,"obfuscation":"owvFjlrw9"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/main"},"finish_reason":null}],"usage":null,"obfuscation":"mnrLF4e"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".go"},"finish_reason":null}],"usage":null,"obfuscation":"1dJrD1OfV"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":":"},"finish_reason":null}],"usage":null,"obfuscation":"1qFNT70FSat"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"116"},"finish_reason":null}],"usage":null,"obfuscation":"nidC1oA6w"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"\n"},"finish_reason":null}],"usage":null,"obfuscation":"NP8KCWhhS1"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"-"},"finish_reason":null}],"usage":null,"obfuscation":"XaGWGBEY8XK"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" github"},"finish_reason":null}],"usage":null,"obfuscation":"U32mQ"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".com"},"finish_reason":null}],"usage":null,"obfuscation":"3cCYSER2"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/"},"finish_reason":null}],"usage":null,"obfuscation":"2DAFbNK05Sc"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ser"},"finish_reason":null}],"usage":null,"obfuscation":"jaGn8JHSz"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"gev"},"finish_reason":null}],"usage":null,"obfuscation":"xDXf6Db8o"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/v"},"finish_reason":null}],"usage":null,"obfuscation":"CMIZd5z8ma"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ak"},"finish_reason":null}],"usage":null,"obfuscation":"NKkLNwqE8z"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"-op"},"finish_reason":null}],"usage":null,"obfuscation":"vt5ytaryA"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ens"},"finish_reason":null}],"usage":null,"obfuscation":"pJNhUAJBr"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ource"},"finish_reason":null}],"usage":null,"obfuscation":"Yd5J9By"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/l"},"finish_reason":null}],"usage":null,"obfuscation":"zrwABmKCKB"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"anguages"},"finish_reason":null}],"usage":null,"obfuscation":"3arf"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/go"},"finish_reason":null}],"usage":null,"obfuscation":"i2XIPHlsb"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/l"},"finish_reason":null}],"usage":null,"obfuscation":"N5sdp3P2rX"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"isp"},"finish_reason":null}],"usage":null,"obfuscation":"7YKoxxKOf"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"-light"},"finish_reason":null}],"usage":null,"obfuscation":"EAUAdg"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".go"},"finish_reason":null}],"usage":null,"obfuscation":"SqhlkiUuO"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":":"},"finish_reason":null}],"usage":null,"obfuscation":"myJ7vjCSL7a"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"156"},"finish_reason":null}],"usage":null,"obfuscation":"UmHlK8sac"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"0"},"finish_reason":null}],"usage":null,"obfuscation":"jxENnYUP1fZ"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"\n"},"finish_reason":null}],"usage":null,"obfuscation":"ZV9X1WiqmM"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"-"},"finish_reason":null}],"usage":null,"obfuscation":"idUIBz2rRav"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" github"},"finish_reason":null}],"usage":null,"obfuscation":"cXu8g"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".com"},"finish_reason":null}],"usage":null,"obfuscation":"cFm9XQhZ"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/"},"finish_reason":null}],"usage":null,"obfuscation":"JUzLgl0By6E"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"aar"},"finish_reason":null}],"usage":null,"obfuscation":"GDW84ATUt"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"z"},"finish_reason":null}],"usage":null,"obfuscation":"IpZTzw44eWy"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"illi"},"finish_reason":null}],"usage":null,"obfuscation":"ZPLWRc4j"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/g"},"finish_reason":null}],"usage":null,"obfuscation":"YrdZ6nqk5l"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"dl"},"finish_reason":null}],"usage":null,"obfuscation":"5r8YBKfjyD"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"v"},"finish_reason":null}],"usage":null,"obfuscation":"34C7OiFTj43"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/vendor"},"finish_reason":null}],"usage":null,"obfuscation":"HAMtf"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/g"},"finish_reason":null}],"usage":null,"obfuscation":"46sw9pJ3ta"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"olang"},"finish_reason":null}],"usage":null,"obfuscation":"Rma1YE0"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".org"},"finish_reason":null}],"usage":null,"obfuscation":"Jr7U9GIJ"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/x"},"finish_reason":null}],"usage":null,"obfuscation":"bNpkeaEBBu"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/"},"finish_reason":null}],"usage":null,"obfuscation":"kBNsKUhMXcK"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"exp"},"finish_reason":null}],"usage":null,"obfuscation":"2bQgVlVMF"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/sh"},"finish_reason":null}],"usage":null,"obfuscation":"9I09Dmyvc"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"iny"},"finish_reason":null}],"usage":null,"obfuscation":"dH2PmeRk3"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/"},"finish_reason":null}],"usage":null,"obfuscation":"y555CEwokZi"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"driver"},"finish_reason":null}],"usage":null,"obfuscation":"Ebv4px"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/"},"finish_reason":null}],"usage":null,"obfuscation":"1XoHh3e0rC2"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"mt"},"finish_reason":null}],"usage":null,"obfuscation":"YiRAj0dEiD"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ld"},"finish_reason":null}],"usage":null,"obfuscation":"yaSox1T9F1"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"river"},"finish_reason":null}],"usage":null,"obfuscation":"N7iRoku"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"/"},"finish_reason":null}],"usage":null,"obfuscation":"elVyUJrLkOp"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"mt"},"finish_reason":null}],"usage":null,"obfuscation":"UeTJiVTGYl"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ld"},"finish_reason":null}],"usage":null,"obfuscation":"cCOEGOKHwf"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"river"},"finish_reason":null}],"usage":null,"obfuscation":"7swXicj"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".go"},"finish_reason":null}],"usage":null,"obfuscation":"UmJEojQEi"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":":"},"finish_reason":null}],"usage":null,"obfuscation":"uZIKP3dYQxt"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"46"},"finish_reason":null}],"usage":null,"obfuscation":"jNSsIb1yVu"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":null,"obfuscation":"EN1DeW"}

      data: {"id":"chatcmpl-CVxhkemB3WTdZW6gxehoYt7nQSL9d","object":"chat.completion.chunk","created":1761733708,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":11187,"completion_tokens":1310,"total_tokens":12497,"prompt_tokens_details":{"cached_tokens":2688,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":1216,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"91YjK9ggIVFeM"}

      data: [DONE]

    headers:
      Content-Type:
      - text/event-stream; charset=utf-8
    status: 200 OK
    code: 200
    duration: 25.884567375s
