From 97dfc147af8b3b86c3bdf15d37464e64ccffa5ac Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Mon, 29 Sep 2025 23:16:37 +0530 Subject: [PATCH] feat: support GitHub Copilot --- README.md | 4 +- cmd/server/server.go | 2 + cmd/server/server_test.go | 10 ++ lib/msgfmt/msgfmt.go | 27 ++-- lib/msgfmt/msgfmt_test.go | 2 +- .../copilot/confirmation_box/expected.txt | 21 +++ .../format/copilot/confirmation_box/msg.txt | 43 ++++++ .../format/copilot/confirmation_box/user.txt | 19 +++ .../format/copilot/first_message/expected.txt | 11 ++ .../format/copilot/first_message/msg.txt | 15 ++ .../format/copilot/first_message/user.txt | 0 .../copilot/multi-line-input/expected.txt | 109 +++++++++++++++ .../format/copilot/multi-line-input/msg.txt | 131 ++++++++++++++++++ .../format/copilot/multi-line-input/user.txt | 19 +++ .../format/copilot/thinking/expected.txt | 9 ++ .../testdata/format/copilot/thinking/msg.txt | 35 +++++ .../testdata/format/copilot/thinking/user.txt | 19 +++ 17 files changed, 461 insertions(+), 15 deletions(-) create mode 100644 lib/msgfmt/testdata/format/copilot/confirmation_box/expected.txt create mode 100644 lib/msgfmt/testdata/format/copilot/confirmation_box/msg.txt create mode 100644 lib/msgfmt/testdata/format/copilot/confirmation_box/user.txt create mode 100644 lib/msgfmt/testdata/format/copilot/first_message/expected.txt create mode 100644 lib/msgfmt/testdata/format/copilot/first_message/msg.txt create mode 100644 lib/msgfmt/testdata/format/copilot/first_message/user.txt create mode 100644 lib/msgfmt/testdata/format/copilot/multi-line-input/expected.txt create mode 100644 lib/msgfmt/testdata/format/copilot/multi-line-input/msg.txt create mode 100644 lib/msgfmt/testdata/format/copilot/multi-line-input/user.txt create mode 100644 lib/msgfmt/testdata/format/copilot/thinking/expected.txt create mode 100644 lib/msgfmt/testdata/format/copilot/thinking/msg.txt create mode 100644 lib/msgfmt/testdata/format/copilot/thinking/user.txt diff --git a/README.md b/README.md index 792813a..d9cee97 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # AgentAPI -Control [Claude Code](https://github.com/anthropics/claude-code), [AmazonQ](https://aws.amazon.com/developer/learning/q-developer-cli/), [Opencode](https://opencode.ai/), [Goose](https://github.com/block/goose), [Aider](https://github.com/Aider-AI/aider), [Gemini](https://github.com/google-gemini/gemini-cli), [Sourcegraph Amp](https://github.com/sourcegraph/amp-cli), [Codex](https://github.com/openai/codex), [Auggie](https://docs.augmentcode.com/cli/overview), and [Cursor CLI](https://cursor.com/en/cli) with an HTTP API. +Control [Claude Code](https://github.com/anthropics/claude-code), [AmazonQ](https://aws.amazon.com/developer/learning/q-developer-cli/), [Opencode](https://opencode.ai/), [Goose](https://github.com/block/goose), [Aider](https://github.com/Aider-AI/aider), [Gemini](https://github.com/google-gemini/gemini-cli), [GitHub Copilot](https://github.com/github/copilot-cli), [Sourcegraph Amp](https://github.com/sourcegraph/amp-cli), [Codex](https://github.com/openai/codex), [Auggie](https://docs.augmentcode.com/cli/overview), and [Cursor CLI](https://cursor.com/en/cli) with an HTTP API. ![agentapi-chat](https://github.com/user-attachments/assets/57032c9f-4146-4b66-b219-09e38ab7690d) @@ -65,7 +65,7 @@ agentapi server -- goose ``` > [!NOTE] -> When using Codex, Opencode, Gemini, Amp or CursorCLI, always specify the agent type explicitly (eg: `agentapi server --type=codex -- codex`), or message formatting may break. +> When using Codex, Opencode, Copilot, Gemini, Amp or CursorCLI, always specify the agent type explicitly (eg: `agentapi server --type=codex -- codex`), or message formatting may break. An OpenAPI schema is available in [openapi.json](openapi.json). diff --git a/cmd/server/server.go b/cmd/server/server.go index 6581e37..56b07ea 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -28,6 +28,7 @@ const ( AgentTypeAider AgentType = msgfmt.AgentTypeAider AgentTypeCodex AgentType = msgfmt.AgentTypeCodex AgentTypeGemini AgentType = msgfmt.AgentTypeGemini + AgentTypeCopilot AgentType = msgfmt.AgentTypeCopilot AgentTypeAmp AgentType = msgfmt.AgentTypeAmp AgentTypeCursor AgentType = msgfmt.AgentTypeCursor AgentTypeAuggie AgentType = msgfmt.AgentTypeAuggie @@ -43,6 +44,7 @@ var agentTypeAliases = map[string]AgentType{ "aider": AgentTypeAider, "codex": AgentTypeCodex, "gemini": AgentTypeGemini, + "copilot": AgentTypeCopilot, "amp": AgentTypeAmp, "auggie": AgentTypeAuggie, "cursor": AgentTypeCursor, diff --git a/cmd/server/server_test.go b/cmd/server/server_test.go index 03c52ff..bd07fc6 100644 --- a/cmd/server/server_test.go +++ b/cmd/server/server_test.go @@ -47,6 +47,11 @@ func TestParseAgentType(t *testing.T) { agentTypeVar: "", want: AgentTypeGemini, }, + { + firstArg: "copilot", + agentTypeVar: "", + want: AgentTypeCopilot, + }, { firstArg: "cursor-agent", agentTypeVar: "", @@ -102,6 +107,11 @@ func TestParseAgentType(t *testing.T) { agentTypeVar: "goose", want: AgentTypeGoose, }, + { + firstArg: "claude", + agentTypeVar: "copilot", + want: AgentTypeCopilot, + }, { firstArg: "goose", agentTypeVar: "claude", diff --git a/lib/msgfmt/msgfmt.go b/lib/msgfmt/msgfmt.go index 4844b3f..dbe2e65 100644 --- a/lib/msgfmt/msgfmt.go +++ b/lib/msgfmt/msgfmt.go @@ -188,7 +188,7 @@ func RemoveUserInput(msgRaw string, userInputRaw string, agentType AgentType) st lastUserInputLineIdx := msgRuneLineLocations[userInputEndIdx] // Skip Gemini/Cursor trailing input box line - if agentType == AgentTypeGemini { + if agentType == AgentTypeGemini || agentType == AgentTypeCopilot { if idx, found := skipTrailingInputBoxLine(msgLines, lastUserInputLineIdx, "╯", "╰"); found { lastUserInputLineIdx = idx } @@ -232,17 +232,18 @@ func trimEmptyLines(message string) string { type AgentType string const ( - AgentTypeClaude AgentType = "claude" - AgentTypeGoose AgentType = "goose" - AgentTypeAider AgentType = "aider" - AgentTypeCodex AgentType = "codex" - AgentTypeGemini AgentType = "gemini" - AgentTypeAmp AgentType = "amp" - AgentTypeCursor AgentType = "cursor" - AgentTypeAuggie AgentType = "auggie" - AgentTypeAmazonQ AgentType = "amazonq" - AgentTypeOpencode AgentType = "opencode" - AgentTypeCustom AgentType = "custom" + AgentTypeClaude AgentType = "claude" + AgentTypeGoose AgentType = "goose" + AgentTypeAider AgentType = "aider" + AgentTypeCodex AgentType = "codex" + AgentTypeGemini AgentType = "gemini" + AgentTypeCopilot AgentType = "copilot" + AgentTypeAmp AgentType = "amp" + AgentTypeCursor AgentType = "cursor" + AgentTypeAuggie AgentType = "auggie" + AgentTypeAmazonQ AgentType = "amazonq" + AgentTypeOpencode AgentType = "opencode" + AgentTypeCustom AgentType = "custom" ) func formatGenericMessage(message string, userInput string, agentType AgentType) string { @@ -278,6 +279,8 @@ func FormatAgentMessage(agentType AgentType, message string, userInput string) s return formatCodexMessage(message, userInput) case AgentTypeGemini: return formatGenericMessage(message, userInput, agentType) + case AgentTypeCopilot: + return formatGenericMessage(message, userInput, agentType) case AgentTypeAmp: return formatGenericMessage(message, userInput, agentType) case AgentTypeCursor: diff --git a/lib/msgfmt/msgfmt_test.go b/lib/msgfmt/msgfmt_test.go index 9cbb5ca..780a395 100644 --- a/lib/msgfmt/msgfmt_test.go +++ b/lib/msgfmt/msgfmt_test.go @@ -218,7 +218,7 @@ func TestTrimEmptyLines(t *testing.T) { func TestFormatAgentMessage(t *testing.T) { dir := "testdata/format" - agentTypes := []AgentType{AgentTypeClaude, AgentTypeGoose, AgentTypeAider, AgentTypeGemini, AgentTypeAmp, AgentTypeCodex, AgentTypeCursor, AgentTypeAuggie, AgentTypeAmazonQ, AgentTypeOpencode, AgentTypeCustom} + agentTypes := []AgentType{AgentTypeClaude, AgentTypeGoose, AgentTypeAider, AgentTypeGemini, AgentTypeCopilot, AgentTypeAmp, AgentTypeCodex, AgentTypeCursor, AgentTypeAuggie, AgentTypeAmazonQ, AgentTypeOpencode, AgentTypeCustom} for _, agentType := range agentTypes { t.Run(string(agentType), func(t *testing.T) { cases, err := testdataDir.ReadDir(path.Join(dir, string(agentType))) diff --git a/lib/msgfmt/testdata/format/copilot/confirmation_box/expected.txt b/lib/msgfmt/testdata/format/copilot/confirmation_box/expected.txt new file mode 100644 index 0000000..7205c94 --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/confirmation_box/expected.txt @@ -0,0 +1,21 @@ + ● I'll search for this code in the repository to find which file it belongs to. + + ○ Search for files containing the useEffect code with polling setup + $ find . -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | xargs grep -l "useEffect.*checkServerStatus\|Set up polling for messages and server status" 2>/dev/null + ↪ 1 line... + + ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Search for files containing the useEffect code with polling setup: │ + │ │ + │ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ + │ │ find . -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | xargs grep -l "useEffect.*checkServerStatus\|Set up polling for messages and server status" 2>/dev/null │ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ Do you want to run this command? │ + │ │ + │ ❯ 1. Yes │ + │ 2. Yes, and approve `xargs` for the rest of the running session │ + │ 3. No, and tell Copilot what to do differently (Esc) │ + │ │ + │ Confirm with number keys or ↑↓ keys and Enter, Cancel with Esc │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ \ No newline at end of file diff --git a/lib/msgfmt/testdata/format/copilot/confirmation_box/msg.txt b/lib/msgfmt/testdata/format/copilot/confirmation_box/msg.txt new file mode 100644 index 0000000..9711057 --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/confirmation_box/msg.txt @@ -0,0 +1,43 @@ + ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Which file is this code from? │ + │ │ + │ ```ts │ + │ // Set up polling for messages and server status │ + │ useEffect(() => { │ + │ // Check server status initially │ + │ checkServerStatus(); │ + │ │ + │ // Set up polling intervals │ + │ const messageInterval = setInterval(fetchMessages, 1000); │ + │ const statusInterval = setInterval(checkServerStatus, 250); │ + │ │ + │ // Clean up intervals on component unmount │ + │ return () => { │ + │ clearInterval(messageInterval); │ + │ clearInterval(statusInterval); │ + │ }; │ + │ }, []); │ + │ ``` │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + ● I'll search for this code in the repository to find which file it belongs to. + + ○ Search for files containing the useEffect code with polling setup + $ find . -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | xargs grep -l "useEffect.*checkServerStatus\|Set up polling for messages and server status" 2>/dev/null + ↪ 1 line... + + ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Search for files containing the useEffect code with polling setup: │ + │ │ + │ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ + │ │ find . -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | xargs grep -l "useEffect.*checkServerStatus\|Set up polling for messages and server status" 2>/dev/null │ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ Do you want to run this command? │ + │ │ + │ ❯ 1. Yes │ + │ 2. Yes, and approve `xargs` for the rest of the running session │ + │ 3. No, and tell Copilot what to do differently (Esc) │ + │ │ + │ Confirm with number keys or ↑↓ keys and Enter, Cancel with Esc │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/lib/msgfmt/testdata/format/copilot/confirmation_box/user.txt b/lib/msgfmt/testdata/format/copilot/confirmation_box/user.txt new file mode 100644 index 0000000..4e1a288 --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/confirmation_box/user.txt @@ -0,0 +1,19 @@ +Which file is this code from? + +```ts +// Set up polling for messages and server status +useEffect(() => { + // Check server status initially + checkServerStatus(); + + // Set up polling intervals + const messageInterval = setInterval(fetchMessages, 1000); + const statusInterval = setInterval(checkServerStatus, 250); + + // Clean up intervals on component unmount + return () => { + clearInterval(messageInterval); + clearInterval(statusInterval); + }; +}, []); +``` diff --git a/lib/msgfmt/testdata/format/copilot/first_message/expected.txt b/lib/msgfmt/testdata/format/copilot/first_message/expected.txt new file mode 100644 index 0000000..db1217c --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/first_message/expected.txt @@ -0,0 +1,11 @@ + Welcome to GitHub Copilot CLI + Version 0.0.328 · Commit 3755a93 + + Copilot can write, test and debug code right from your terminal. Describe a + task to get started or enter ? for help. Copilot uses AI, check for mistakes. + + ● Logged in with gh as user: 35C4n0r + + ● Connected to GitHub MCP Server + + ~/Documents/work/agentapi [⎇ feat-github-cli*] \ No newline at end of file diff --git a/lib/msgfmt/testdata/format/copilot/first_message/msg.txt b/lib/msgfmt/testdata/format/copilot/first_message/msg.txt new file mode 100644 index 0000000..dee0c4d --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/first_message/msg.txt @@ -0,0 +1,15 @@ + Welcome to GitHub Copilot CLI + Version 0.0.328 · Commit 3755a93 + + Copilot can write, test and debug code right from your terminal. Describe a + task to get started or enter ? for help. Copilot uses AI, check for mistakes. + + ● Logged in with gh as user: 35C4n0r + + ● Connected to GitHub MCP Server + + ~/Documents/work/agentapi [⎇ feat-github-cli*] + ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Enter @ to mention files or / for commands │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + Ctrl+c Exit · Ctrl+r Expand all \ No newline at end of file diff --git a/lib/msgfmt/testdata/format/copilot/first_message/user.txt b/lib/msgfmt/testdata/format/copilot/first_message/user.txt new file mode 100644 index 0000000..e69de29 diff --git a/lib/msgfmt/testdata/format/copilot/multi-line-input/expected.txt b/lib/msgfmt/testdata/format/copilot/multi-line-input/expected.txt new file mode 100644 index 0000000..28865b1 --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/multi-line-input/expected.txt @@ -0,0 +1,109 @@ + ● I'll search for this code in the repository to find which file it belongs to. + + ✓ Search for files containing the useEffect code with polling setup + $ find . -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | xargs grep -l "useEffect.*checkServerStatus\|Set up polling for messages and server status" 2>/dev/null + ↪ 1 line... + + ● Let me try a broader search for the specific code patterns in the snippet: + + ✓ Search for files containing checkServerStatus function calls + $ find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) -exec grep -l "checkServerStatus" {} \; + ↪ 1 line... + + ✓ stop_bash + ↪ 1 line... + + ● Let me try a more specific search within the chat directory: + + ✓ Search for checkServerStatus in chat directory + $ grep -r "checkServerStatus" chat/ 2>/dev/null || echo "Not found in chat/" + ↪ 2 lines... + + ● Let me search for the specific interval patterns: + + ✓ Search for setInterval with fetchMessages + $ grep -r "setInterval.*fetchMessages" . 2>/dev/null || echo "Not found" + ↪ 67 lines... + + ● I can see this code appears in test data files. Let me look for the actual + source file by checking the full useEffect code pattern: + + ✓ Search for the complete useEffect pattern with Set up polling comment + $ grep -r "Set up polling for messages and server status" . --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null || echo "Not found with exact comment" + ↪ 2 lines... + + ● Let me look at one of the test files to see the context: + + ✓ View user.txt + ~/Documents/work/agentapi/lib/msgfmt/testdata/remove-user-input/claude/user.txt + ↪ 24 lines... + + ● Now I understand! This code snippet is actually from a user question that was + used as test data in the message formatting system. Let me search for this + specific code in the actual source files by looking at the chat directory more + thoroughly: + + ✓ List directory ~/Documents/work/agentapi/chat + ↪ 27 items... + + ✓ Search for polling setup in chat src directory + $ find chat/src -name "*.ts" -o -name "*.tsx" | xargs grep -l "messageInterval\|statusInterval" 2>/dev/null || echo "Not found in src" + ↪ 2 lines... + + ✓ Search for fetchMessages function in chat directory + $ find chat -name "*.ts" -o -name "*.tsx" | xargs grep -l "fetchMessages" 2>/dev/null || echo "Not found" + ↪ 2 lines... + + ● Let me check the chat/src directory structure: + + ✓ List directory ~/Documents/work/agentapi/chat/src + ↪ 11 items... + + ✓ Search for useEffect with intervals in all chat TypeScript files + $ find chat -name "*.ts" -o -name "*.tsx" | xargs grep -l "useEffect.*setInterval\|setInterval.*useEffect" 2>/dev/null || echo "Not found" + ↪ 2 lines... + + ● Let me check the main chat page or component files: + + ✓ List directory ~/Documents/work/agentapi/chat/src/app + ↪ 12 items... + + ✓ View page.tsx + ~/Documents/work/agentapi/chat/src/app/page.tsx + ↪ 26 lines... + + ● Let me check the Chat component and ChatProvider: + + ✓ List directory ~/Documents/work/agentapi/chat/src/components + ↪ 13 items... + + ✓ View chat-provider.tsx + ~/Documents/work/agentapi/chat/src/components/chat-provider.tsx + ↪ 296 lines... + + ● Based on my search through the repository, I can now provide you with the + answer: + + The code snippet you provided is not from an actual source file in this + repository. Instead, it appears to be test data that represents a user question + about polling code that was used in the message formatting system's test suite. + + Specifically, this code appears in multiple test data files under + lib/msgfmt/testdata/ directories, such as: + + * lib/msgfmt/testdata/remove-user-input/claude/user.txt + * lib/msgfmt/testdata/remove-user-input/aider/user.txt + * lib/msgfmt/testdata/remove-user-input/goose/user.txt + * And several others in various test scenarios + + The test data shows this TypeScript code as an example of a user question that + was being processed by different agent message formatters (Claude, Aider, Goose, + etc.) to test how they handle and format multi-line code snippets in user input. + + The actual chat functionality in this repository uses a different approach - it + uses Server-Sent Events (SSE) for real-time communication instead of polling, as + seen in the chat/src/components/chat-provider.tsx file where an EventSource + connection is established to listen for message updates and status changes from + the server. + + ~/Documents/work/agentapi [⎇ feat-github-cli*] \ No newline at end of file diff --git a/lib/msgfmt/testdata/format/copilot/multi-line-input/msg.txt b/lib/msgfmt/testdata/format/copilot/multi-line-input/msg.txt new file mode 100644 index 0000000..5593618 --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/multi-line-input/msg.txt @@ -0,0 +1,131 @@ + ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Which file is this code from? │ + │ │ + │ ```ts │ + │ // Set up polling for messages and server status │ + │ useEffect(() => { │ + │ // Check server status initially │ + │ checkServerStatus(); │ + │ │ + │ // Set up polling intervals │ + │ const messageInterval = setInterval(fetchMessages, 1000); │ + │ const statusInterval = setInterval(checkServerStatus, 250); │ + │ │ + │ // Clean up intervals on component unmount │ + │ return () => { │ + │ clearInterval(messageInterval); │ + │ clearInterval(statusInterval); │ + │ }; │ + │ }, []); │ + │ ``` │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + ● I'll search for this code in the repository to find which file it belongs to. + + ✓ Search for files containing the useEffect code with polling setup + $ find . -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | xargs grep -l "useEffect.*checkServerStatus\|Set up polling for messages and server status" 2>/dev/null + ↪ 1 line... + + ● Let me try a broader search for the specific code patterns in the snippet: + + ✓ Search for files containing checkServerStatus function calls + $ find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) -exec grep -l "checkServerStatus" {} \; + ↪ 1 line... + + ✓ stop_bash + ↪ 1 line... + + ● Let me try a more specific search within the chat directory: + + ✓ Search for checkServerStatus in chat directory + $ grep -r "checkServerStatus" chat/ 2>/dev/null || echo "Not found in chat/" + ↪ 2 lines... + + ● Let me search for the specific interval patterns: + + ✓ Search for setInterval with fetchMessages + $ grep -r "setInterval.*fetchMessages" . 2>/dev/null || echo "Not found" + ↪ 67 lines... + + ● I can see this code appears in test data files. Let me look for the actual + source file by checking the full useEffect code pattern: + + ✓ Search for the complete useEffect pattern with Set up polling comment + $ grep -r "Set up polling for messages and server status" . --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null || echo "Not found with exact comment" + ↪ 2 lines... + + ● Let me look at one of the test files to see the context: + + ✓ View user.txt + ~/Documents/work/agentapi/lib/msgfmt/testdata/remove-user-input/claude/user.txt + ↪ 24 lines... + + ● Now I understand! This code snippet is actually from a user question that was + used as test data in the message formatting system. Let me search for this + specific code in the actual source files by looking at the chat directory more + thoroughly: + + ✓ List directory ~/Documents/work/agentapi/chat + ↪ 27 items... + + ✓ Search for polling setup in chat src directory + $ find chat/src -name "*.ts" -o -name "*.tsx" | xargs grep -l "messageInterval\|statusInterval" 2>/dev/null || echo "Not found in src" + ↪ 2 lines... + + ✓ Search for fetchMessages function in chat directory + $ find chat -name "*.ts" -o -name "*.tsx" | xargs grep -l "fetchMessages" 2>/dev/null || echo "Not found" + ↪ 2 lines... + + ● Let me check the chat/src directory structure: + + ✓ List directory ~/Documents/work/agentapi/chat/src + ↪ 11 items... + + ✓ Search for useEffect with intervals in all chat TypeScript files + $ find chat -name "*.ts" -o -name "*.tsx" | xargs grep -l "useEffect.*setInterval\|setInterval.*useEffect" 2>/dev/null || echo "Not found" + ↪ 2 lines... + + ● Let me check the main chat page or component files: + + ✓ List directory ~/Documents/work/agentapi/chat/src/app + ↪ 12 items... + + ✓ View page.tsx + ~/Documents/work/agentapi/chat/src/app/page.tsx + ↪ 26 lines... + + ● Let me check the Chat component and ChatProvider: + + ✓ List directory ~/Documents/work/agentapi/chat/src/components + ↪ 13 items... + + ✓ View chat-provider.tsx + ~/Documents/work/agentapi/chat/src/components/chat-provider.tsx + ↪ 296 lines... + + ● Based on my search through the repository, I can now provide you with the + answer: + + The code snippet you provided is not from an actual source file in this + repository. Instead, it appears to be test data that represents a user question + about polling code that was used in the message formatting system's test suite. + + Specifically, this code appears in multiple test data files under + lib/msgfmt/testdata/ directories, such as: + + * lib/msgfmt/testdata/remove-user-input/claude/user.txt + * lib/msgfmt/testdata/remove-user-input/aider/user.txt + * lib/msgfmt/testdata/remove-user-input/goose/user.txt + * And several others in various test scenarios + + The test data shows this TypeScript code as an example of a user question that + was being processed by different agent message formatters (Claude, Aider, Goose, + etc.) to test how they handle and format multi-line code snippets in user input. + + The actual chat functionality in this repository uses a different approach - it + uses Server-Sent Events (SSE) for real-time communication instead of polling, as + seen in the chat/src/components/chat-provider.tsx file where an EventSource + connection is established to listen for message updates and status changes from + the server. + + ~/Documents/work/agentapi [⎇ feat-github-cli*] \ No newline at end of file diff --git a/lib/msgfmt/testdata/format/copilot/multi-line-input/user.txt b/lib/msgfmt/testdata/format/copilot/multi-line-input/user.txt new file mode 100644 index 0000000..c3b14b0 --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/multi-line-input/user.txt @@ -0,0 +1,19 @@ +Which file is this code from? + +```ts +// Set up polling for messages and server status +useEffect(() => { + // Check server status initially + checkServerStatus(); + + // Set up polling intervals + const messageInterval = setInterval(fetchMessages, 1000); + const statusInterval = setInterval(checkServerStatus, 250); + + // Clean up intervals on component unmount + return () => { + clearInterval(messageInterval); + clearInterval(statusInterval); + }; +}, []); +``` diff --git a/lib/msgfmt/testdata/format/copilot/thinking/expected.txt b/lib/msgfmt/testdata/format/copilot/thinking/expected.txt new file mode 100644 index 0000000..05930b5 --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/thinking/expected.txt @@ -0,0 +1,9 @@ + ● I'll search for this code in the repository to find which file it belongs to. + + ✓ Search for files containing the useEffect code with polling setup + $ find . -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | xargs grep -l "useEffect.*checkServerStatus\|Set up polling for messages and server status" 2>/dev/null + ↪ 1 line... + + ◉ Thinking (Esc to cancel) + + ~/Documents/work/agentapi [⎇ feat-github-cli*] \ No newline at end of file diff --git a/lib/msgfmt/testdata/format/copilot/thinking/msg.txt b/lib/msgfmt/testdata/format/copilot/thinking/msg.txt new file mode 100644 index 0000000..3a87826 --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/thinking/msg.txt @@ -0,0 +1,35 @@ + ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Which file is this code from? │ + │ │ + │ ```ts │ + │ // Set up polling for messages and server status │ + │ useEffect(() => { │ + │ // Check server status initially │ + │ checkServerStatus(); │ + │ │ + │ // Set up polling intervals │ + │ const messageInterval = setInterval(fetchMessages, 1000); │ + │ const statusInterval = setInterval(checkServerStatus, 250); │ + │ │ + │ // Clean up intervals on component unmount │ + │ return () => { │ + │ clearInterval(messageInterval); │ + │ clearInterval(statusInterval); │ + │ }; │ + │ }, []); │ + │ ``` │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + ● I'll search for this code in the repository to find which file it belongs to. + + ✓ Search for files containing the useEffect code with polling setup + $ find . -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" | xargs grep -l "useEffect.*checkServerStatus\|Set up polling for messages and server status" 2>/dev/null + ↪ 1 line... + + ◉ Thinking (Esc to cancel) + + ~/Documents/work/agentapi [⎇ feat-github-cli*] + ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Enter @ to mention files or / for commands │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + Ctrl+c Exit · Ctrl+r Expand all Remaining requests: 0% diff --git a/lib/msgfmt/testdata/format/copilot/thinking/user.txt b/lib/msgfmt/testdata/format/copilot/thinking/user.txt new file mode 100644 index 0000000..c3b14b0 --- /dev/null +++ b/lib/msgfmt/testdata/format/copilot/thinking/user.txt @@ -0,0 +1,19 @@ +Which file is this code from? + +```ts +// Set up polling for messages and server status +useEffect(() => { + // Check server status initially + checkServerStatus(); + + // Set up polling intervals + const messageInterval = setInterval(fetchMessages, 1000); + const statusInterval = setInterval(checkServerStatus, 250); + + // Clean up intervals on component unmount + return () => { + clearInterval(messageInterval); + clearInterval(statusInterval); + }; +}, []); +```