From efae7867050302344819ddf66f8a9b0736af41f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93lafur=20P=C3=A1ll=20Geirsson?= Date: Wed, 14 Aug 2024 09:21:35 +0200 Subject: [PATCH] fix/CLI: fail fast if the provided --context-file is too large (#5191) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the CLI didn't give any hint when `--context-file` was too large to fit into the context window. The VS Code chat UI refuses to add these files as explicit context. This PR fixes the problem so that the CLI also fails fast in the same scenario. Users can pass the `--ignore-context-window-error` to skip this check. ## Test plan Manually tested with ``` > pnpm -C agent build:agent && node agent/dist/index.js chat --context-file agent/src/cli/scip-codegen/scip.ts --context-file agent/src/agent.ts -m 'list all the methods here' ✖ The provided context is too large to fit into the context window. To fix this problem, either remove the files from --context-file or edit these files so they become small enough to fit into the context window. Alternatively, set the flag --ignore-context-window-errors to skip this check. File Reason ----------------------------------------------------------------------- -------------------------------------------------------------------------- /Users/olafurpg/dev/sourcegraph/cody/agent/src/cli/scip-codegen/scip.ts user context tokens exceeded remaining user context tokens (49538 > 29970) ``` To skip the check ``` pnpm -C agent build:agent && node agent/dist/index.js chat --context-file agent/src/cli/scip-codegen/scip.ts --context-file agent/src/agent.ts -m 'list all the methods here' --ignore-context-window-errors ``` ## Changelog --- agent/CHANGELOG.md | 9 + agent/package.json | 3 +- .../cody-chat_103640681/recording.har.yaml | 609 ++++-------------- agent/src/TestClient.ts | 2 +- .../__snapshots__/command-chat.test.ts.snap | 25 +- agent/src/cli/command-chat.ts | 111 +++- vscode/src/jsonrpc/jsonrpc.ts | 11 +- 7 files changed, 238 insertions(+), 532 deletions(-) diff --git a/agent/CHANGELOG.md b/agent/CHANGELOG.md index f1930f7ca5df..268d906e30b1 100644 --- a/agent/CHANGELOG.md +++ b/agent/CHANGELOG.md @@ -10,6 +10,15 @@ This is a log of all notable changes to the Cody command-line tool. [Unreleased] ### Changed +## 5.5.12 + +### Fixed + +- `cody chat --context-file` will now fail fast if the provided file is too + large to fit into the context window. Previously, `cody chat` silently ignored + this error and the LLM would respond with a confusing message about missing + context. To bypass this check, use `--ignore-context-window-errors`. + ## 5.5.11 ### Fixed diff --git a/agent/package.json b/agent/package.json index bb1172413c4b..1698a1168fd3 100644 --- a/agent/package.json +++ b/agent/package.json @@ -1,6 +1,6 @@ { "name": "@sourcegraph/cody", - "version": "5.5.11", + "version": "5.5.12", "description": "Cody CLI is the same technology that powers Cody in the IDE but available from the command-line.", "license": "Apache-2.0", "repository": { @@ -13,6 +13,7 @@ "scripts": { "build:root": "pnpm -C .. run -s build", "build:agent": "node src/esbuild.mjs", + "build:for-tests": "pnpm run -s build:root && pnpm run -s build:agent", "build:webviews": "pnpm -C ../vscode _build:webviews --mode production --outDir ../../agent/dist/webviews", "build": "pnpm run -s build:root && pnpm run -s build:webviews && pnpm run -s build:agent", "build-minify": "pnpm run build --minify", diff --git a/agent/recordings/cody-chat_103640681/recording.har.yaml b/agent/recordings/cody-chat_103640681/recording.har.yaml index 443772c18fd7..310c1f5a26e1 100644 --- a/agent/recordings/cody-chat_103640681/recording.har.yaml +++ b/agent/recordings/cody-chat_103640681/recording.har.yaml @@ -36,26 +36,24 @@ log: queryString: [] url: https://sourcegraph.sourcegraph.com/.api/client-config response: - bodySize: 191 + bodySize: 183 content: encoding: base64 mimeType: text/plain; charset=utf-8 - size: 191 - text: "[\"H4sIAAAAAAAAA2zMsQpCMQyF4b1PEe7sE7hJcXBzc861EQtNI80pKnLf3UVwyfz953wSE\ - dFytfI+dl6blGVPGFN2P7gzQuAJy6aPJpB4OR2m2VS5F48/gFHXiWo9dFceyNYhL1xq\ - L/YMM7UizQ/n019v3FzSlr4AAAD//w==\",\"AwCYZZ0K3wAAAA==\"]" + size: 183 + text: "[\"H4sIAAAAAAAAA2zMsQoCMRCE4T5PEa6+J7CTYGF3nfWeu2AguyvJBBXx3W1shK2/f+adc\ + s55uTq/TkZ7E14OGX3K+oMbIQSa\",\"8OJ6bwKJl3PAtbgqGY/4A+h1n6huoQ+ljuI\ + GeeJSjf0RZuosbRy387+mT/oCAAD//wMAc0i0Et4AAAA=\"]" cookies: [] headers: - name: date - value: Tue, 16 Jul 2024 15:14:58 GMT + value: Tue, 13 Aug 2024 19:01:28 GMT - name: content-type value: text/plain; charset=utf-8 - name: transfer-encoding value: chunked - name: connection value: keep-alive - - name: retry-after - value: "523" - name: access-control-allow-credentials value: "true" - name: access-control-allow-origin @@ -75,12 +73,12 @@ log: value: max-age=31536000; includeSubDomains; preload - name: content-encoding value: gzip - headersSize: 1365 + headersSize: 1258 httpVersion: HTTP/1.1 redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-16T15:14:57.806Z + startedDateTime: 2024-08-13T19:01:28.077Z time: 0 timings: blocked: -1 @@ -90,11 +88,11 @@ log: send: 0 ssl: -1 wait: 0 - - _id: 67bca6fe77aa075277907719042acf02 + - _id: b5ceae943af989c36c626faa496b3c02 _order: 0 cache: {} request: - bodySize: 278 + bodySize: 259 cookies: [] headers: - name: content-type @@ -123,7 +121,7 @@ log: text: You are Cody, an AI coding assistant from Sourcegraph. - speaker: human text: respond with "hello" and nothing else - model: anthropic/claude-3-5-sonnet-20240620 + model: claude-3.5-sonnet temperature: 0.2 topK: -1 topP: -1 @@ -150,15 +148,13 @@ log: cookies: [] headers: - name: date - value: Tue, 16 Jul 2024 15:14:59 GMT + value: Tue, 13 Aug 2024 19:01:31 GMT - name: content-type value: text/event-stream - name: transfer-encoding value: chunked - name: connection value: keep-alive - - name: retry-after - value: "522" - name: access-control-allow-credentials value: "true" - name: access-control-allow-origin @@ -176,12 +172,12 @@ log: value: 1; mode=block - name: strict-transport-security value: max-age=31536000; includeSubDomains; preload - headersSize: 1322 + headersSize: 1215 httpVersion: HTTP/1.1 redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-16T15:14:58.201Z + startedDateTime: 2024-08-13T19:01:29.569Z time: 0 timings: blocked: -1 @@ -191,11 +187,11 @@ log: send: 0 ssl: -1 wait: 0 - - _id: 7e06b3087ccb0cbc2c410b6309126d40 + - _id: b33f9ea19dd116f2ef31b76450455f55 _order: 0 cache: {} request: - bodySize: 403 + bodySize: 532 cookies: [] headers: - name: content-type @@ -222,14 +218,23 @@ log: messages: - speaker: system text: You are Cody, an AI coding assistant from Sourcegraph. + - speaker: human + text: |- + Codebase context from file animal.ts: + ```typescript + interface StrangeAnimal { + makesSound(): 'coo' | 'moo' + } + ``` + - speaker: assistant + text: Ok. - speaker: human text: >- - You have access to the provided codebase context. Answer - positively without apologizing. + You have access to the provided codebase context. Question: implement a cow. Only print the code without any explanation. - model: anthropic/claude-3-5-sonnet-20240620 + model: claude-3.5-sonnet temperature: 0.2 topK: -1 topP: -1 @@ -242,14 +247,14 @@ log: value: 6.0.0-SNAPSHOT url: https://sourcegraph.sourcegraph.com/.api/completions/stream?api-version=1&client-name=jetbrains&client-version=6.0.0-SNAPSHOT response: - bodySize: 17000 + bodySize: 1297 content: mimeType: text/event-stream - size: 17000 + size: 1297 text: >+ event: completion - data: {"completion":"Here's a simple implementation of a cow in Python:\n\n```python\nclass Cow:\n def __init__(self, name):\n self.name = name\n self.milk = 0\n\n def moo(self):\n return f\"{self.name} says: Moo!\"\n\n def produce_milk(self, amount):\n self.milk += amount\n return f\"{self.name} produced {amount} liters of milk.\"\n\n def get_milk(self):\n milk_produced = self.milk\n self.milk = 0\n return f\"Collected {milk_produced} liters of milk from {self.name}.\"\n```","stopReason":"end_turn"} + data: {"completion":"```typescript\nclass Cow implements StrangeAnimal {\n makesSound(): 'coo' | 'moo' {\n return 'moo';\n }\n}\n```","stopReason":"end_turn"} event: done @@ -259,7 +264,7 @@ log: cookies: [] headers: - name: date - value: Fri, 19 Jul 2024 04:09:33 GMT + value: Tue, 13 Aug 2024 19:01:34 GMT - name: content-type value: text/event-stream - name: transfer-encoding @@ -288,121 +293,7 @@ log: redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-19T04:09:31.538Z - time: 0 - timings: - blocked: -1 - connect: -1 - dns: -1 - receive: 0 - send: 0 - ssl: -1 - wait: 0 - - _id: 6d68e70caae8b436c57cef420e5762cc - _order: 0 - cache: {} - request: - bodySize: 916 - cookies: [] - headers: - - name: content-type - value: application/json - - name: accept-encoding - value: gzip;q=0 - - name: authorization - value: token - REDACTED_964f5256e709a8c5c151a63d8696d5c7ac81604d179405864d88ff48a9232364 - - name: user-agent - value: jetbrains / 6.0.0-SNAPSHOT - - name: connection - value: keep-alive - - name: host - value: sourcegraph.sourcegraph.com - headersSize: 371 - httpVersion: HTTP/1.1 - method: POST - postData: - mimeType: application/json - params: [] - textJSON: - fast: true - maxTokensToSample: 400 - messages: - - speaker: human - text: You are Cody, an AI coding assistant from Sourcegraph. - - speaker: assistant - text: I am Cody, an AI coding assistant from Sourcegraph. - - speaker: human - text: "You are helping the user search over a codebase. List some filename - fragments that would match files relevant to read to answer - the user's query. Present your results in a *single* XML list - in the following format: a single - keyworda space separated list of synonyms - and variants of the keyword, including acronyms, - abbreviations, and expansionsa numerical - weight between 0.0 and 1.0 that indicates the importance of - the keyword. Here is the user - query: what is squirrel? Explain as briefly as - possible." - - speaker: assistant - temperature: 0 - topK: 1 - queryString: - - name: client-name - value: jetbrains - - name: client-version - value: 6.0.0-SNAPSHOT - url: https://sourcegraph.sourcegraph.com/.api/completions/stream?client-name=jetbrains&client-version=6.0.0-SNAPSHOT - response: - bodySize: 8530 - content: - mimeType: text/event-stream - size: 8530 - text: >+ - event: completion - - data: {"completion":"\u003ckeywords\u003e\n\u003ckeyword\u003e\n\u003cvalue\u003esquirrel\u003c/value\u003e\n\u003cvariants\u003esquirrels sciuridae rodent\u003c/variants\u003e\n\u003cweight\u003e1.0\u003c/weight\u003e\n\u003c/keyword\u003e\n\u003ckeyword\u003e\n\u003cvalue\u003eoverview\u003c/value\u003e\n\u003cvariants\u003esummary brief explanation\u003c/variants\u003e\n\u003cweight\u003e0.8\u003c/weight\u003e\n\u003c/keyword\u003e\n\u003c/keywords\u003e","stopReason":"end_turn"} - - - event: done - - data: {} - - cookies: [] - headers: - - name: date - value: Tue, 16 Jul 2024 15:15:01 GMT - - name: content-type - value: text/event-stream - - name: transfer-encoding - value: chunked - - name: connection - value: keep-alive - - name: retry-after - value: "520" - - name: access-control-allow-credentials - value: "true" - - name: access-control-allow-origin - value: "" - - name: cache-control - value: no-cache - - name: vary - value: Accept-Encoding, Authorization, Cookie, Authorization, X-Requested-With, - Cookie - - name: x-content-type-options - value: nosniff - - name: x-frame-options - value: DENY - - name: x-xss-protection - value: 1; mode=block - - name: strict-transport-security - value: max-age=31536000; includeSubDomains; preload - headersSize: 1322 - httpVersion: HTTP/1.1 - redirectURL: "" - status: 200 - statusText: OK - startedDateTime: 2024-07-16T15:15:00.436Z + startedDateTime: 2024-08-13T19:01:33.443Z time: 0 timings: blocked: -1 @@ -462,26 +353,28 @@ log: value: null url: https://sourcegraph.sourcegraph.com/.api/graphql?ContextFilters response: - bodySize: 163 + bodySize: 104 content: encoding: base64 mimeType: application/json - size: 163 - text: "[\"H4sIAAAAAAAAAxTIQQqAIBBG4bvMMqgDuA1aRvtoMehPBJOKTmSIdw/f5oNXybEymUr5U\ - nRtcN8cvKLocoki5X4Tvx0UK48Dmb1SQgwr39hYFcmToWkQ9ueIwncUTAO1o/V+AAAA\ - //8=\",\"AwBK/4wNZQAAAA==\"]" + size: 104 + text: "[\"H4sIAAAAAAAAA6pWSkksSVSyqlYqzixJBdHJ+SmVzvl5JakVJW6ZOSWpRcUg0aLEciWrv\ + NKcnNra2loAAAAA//8DADYuyGU1AAAA\"]" + textDecoded: + data: + site: + codyContextFilters: + raw: null cookies: [] headers: - name: date - value: Tue, 16 Jul 2024 15:14:58 GMT + value: Tue, 13 Aug 2024 19:01:28 GMT - name: content-type value: application/json - name: transfer-encoding value: chunked - name: connection value: keep-alive - - name: retry-after - value: "523" - name: access-control-allow-credentials value: "true" - name: access-control-allow-origin @@ -501,12 +394,12 @@ log: value: max-age=31536000; includeSubDomains; preload - name: content-encoding value: gzip - headersSize: 1356 + headersSize: 1249 httpVersion: HTTP/1.1 redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-16T15:14:57.815Z + startedDateTime: 2024-08-13T19:01:28.603Z time: 0 timings: blocked: -1 @@ -571,37 +464,25 @@ log: value: null url: https://sourcegraph.sourcegraph.com/.api/graphql?CurrentSiteCodyLlmConfiguration response: - bodySize: 248 + bodySize: 227 content: encoding: base64 mimeType: application/json - size: 248 - text: "[\"H4sIAAAAAAAAA3zOTQrCMBAF4LvMuqFj6g9222278wJDktrQmilJikrJ3aWKKBZcDTze+\ - 5gZNEWCcoZgo1muYn2v66Zi19rz5Clads+8o9iwNgOUQC52nkercjXQpI0oxE4Eds5E\ - IVFucS8Rss+koduJe+MClBuJiBm0FGL1X+zI9tOLK/AAP5s1qfgyDmZ594221psr+z7\ - kIZJXrI2HVe8LOiJiSik9AAAA//8DABY6yDgVAQAA\"]" - textDecoded: - data: - site: - codyLLMConfiguration: - chatModel: anthropic/claude-3-5-sonnet-20240620 - chatModelMaxTokens: 12000 - completionModel: fireworks/starcoder - completionModelMaxTokens: 9000 - fastChatModel: anthropic/claude-3-haiku-20240307 - fastChatModelMaxTokens: 12000 + size: 227 + text: "[\"H4sIAAAAAAAAA4TOwQrCMAzG8XfJedPiFKTXXbfbXiC02VaczWhTUEbfXeZlygRPgY8/P\ + 7KARUHQC0QntF7D9tk0bc2+d0MKKI79ex9RWrY0\",\"gYbIKRgaAs7j0UyYLJXV4VJ\ + G9p4Eiq1t8dHxjXwEXSmlVAE9Rqn/UBv0Ve8xw/d5ovXDX1wUDIYtBdiVH9RJna855/\ + wCAAD//wMALGYOWAoBAAA=\"]" cookies: [] headers: - name: date - value: Tue, 16 Jul 2024 15:14:57 GMT + value: Tue, 13 Aug 2024 19:01:27 GMT - name: content-type value: application/json - name: transfer-encoding value: chunked - name: connection value: keep-alive - - name: retry-after - value: "523" - name: access-control-allow-credentials value: "true" - name: access-control-allow-origin @@ -621,12 +502,12 @@ log: value: max-age=31536000; includeSubDomains; preload - name: content-encoding value: gzip - headersSize: 1356 + headersSize: 1249 httpVersion: HTTP/1.1 redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-16T15:14:57.338Z + startedDateTime: 2024-08-13T19:01:27.603Z time: 0 timings: blocked: -1 @@ -692,20 +573,18 @@ log: mimeType: application/json size: 139 text: "[\"H4sIAAAAAAAAA6pWSkksSVSyqlYqzixJBdHJ+SmVPj6+zvl5aZnppUWJJZn5eWD53MSiE\ - uf8vJLUipLwzLyU/HIlK6XUvMSknNQUpdra2loAAAAA//8=\",\"AwDoCDSlSwAAAA==\ + uf8vJLUipLwzLyU/HIlK6WUzOLEpJzUFKXa2tpa\",\"AAAAAP//AwArMNn0TAAAAA==\ \"]" cookies: [] headers: - name: date - value: Tue, 16 Jul 2024 15:14:57 GMT + value: Tue, 13 Aug 2024 19:01:27 GMT - name: content-type value: application/json - name: transfer-encoding value: chunked - name: connection value: keep-alive - - name: retry-after - value: "523" - name: access-control-allow-credentials value: "true" - name: access-control-allow-origin @@ -725,12 +604,12 @@ log: value: max-age=31536000; includeSubDomains; preload - name: content-encoding value: gzip - headersSize: 1356 + headersSize: 1249 httpVersion: HTTP/1.1 redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-16T15:14:57.377Z + startedDateTime: 2024-08-13T19:01:27.641Z time: 0 timings: blocked: -1 @@ -790,30 +669,23 @@ log: value: null url: https://sourcegraph.sourcegraph.com/.api/graphql?CurrentSiteCodyLlmProvider response: - bodySize: 128 + bodySize: 131 content: encoding: base64 mimeType: application/json - size: 128 + size: 131 text: "[\"H4sIAAAAAAAAA6pWSkksSVSyqlYqzixJBdHJ+SmVPj6+zvl5aZnppUWJJZn5eSDxgqL8s\ - syU1CIlK6Xi/NKi5NT0osSCDKXa2tpaAAAAAP//AwAfFAXARQAAAA==\"]" - textDecoded: - data: - site: - codyLLMConfiguration: - provider: sourcegraph + syU1CIlK6Xi/NKi5NT0osSCDKXa2tpaAAAAAP//\",\"AwAfFAXARQAAAA==\"]" cookies: [] headers: - name: date - value: Tue, 16 Jul 2024 15:14:57 GMT + value: Tue, 13 Aug 2024 19:01:27 GMT - name: content-type value: application/json - name: transfer-encoding value: chunked - name: connection value: keep-alive - - name: retry-after - value: "523" - name: access-control-allow-credentials value: "true" - name: access-control-allow-origin @@ -833,12 +705,12 @@ log: value: max-age=31536000; includeSubDomains; preload - name: content-encoding value: gzip - headersSize: 1356 + headersSize: 1249 httpVersion: HTTP/1.1 redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-16T15:14:57.357Z + startedDateTime: 2024-08-13T19:01:27.622Z time: 0 timings: blocked: -1 @@ -909,38 +781,25 @@ log: value: null url: https://sourcegraph.sourcegraph.com/.api/graphql?CurrentUser response: - bodySize: 228 + bodySize: 231 content: encoding: base64 mimeType: application/json - size: 228 + size: 231 text: "[\"H4sIAAAAAAAAAzSOuwrCQBBF/2XqLawXLO0kgpggiMWQncTRzWyY2Qgx7L9LfJTncricB\ - QJmBL9AO6mS5NpIV+QAHppzFdt72hxOjy04uKE1pNwxhd2AHMF3GI0cBLYx4lzhQOBl\ - itHBZKTyYWhTmDNZZunBAT4xo9bH/d8clQfU+ff43ZL2KPzCzElszZEUyMBfrqWU8gY\ - AAP//AwAAXh5NtQAAAA==\"]" - textDecoded: - data: - currentUser: - avatarURL: null - displayName: null - hasVerifiedEmail: false - id: VXNlcjo0OTk= - organizations: - nodes: [] - primaryEmail: null - username: codytesting + QJmBL9AO6mS5NpIV+QAHppzFdt72hxOjy04uKE1\",\"pNwxhd2AHMF3GI0cBLYx4lz\ + hQOBlitHBZKTyYWhTmDNZZunBAT4xo9bH/d8clQfU+ff43ZL2KPzCzElszZEUyMBfrq\ + WU8gYAAP//AwAAXh5NtQAAAA==\"]" cookies: [] headers: - name: date - value: Tue, 16 Jul 2024 15:14:57 GMT + value: Tue, 13 Aug 2024 19:01:27 GMT - name: content-type value: application/json - name: transfer-encoding value: chunked - name: connection value: keep-alive - - name: retry-after - value: "523" - name: access-control-allow-credentials value: "true" - name: access-control-allow-origin @@ -960,12 +819,12 @@ log: value: max-age=31536000; includeSubDomains; preload - name: content-encoding value: gzip - headersSize: 1356 + headersSize: 1249 httpVersion: HTTP/1.1 redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-16T15:14:57.396Z + startedDateTime: 2024-08-13T19:01:27.661Z time: 0 timings: blocked: -1 @@ -975,11 +834,11 @@ log: send: 0 ssl: -1 wait: 0 - - _id: 26ecc9d2f361f4c40e9a9bf4b2f8bea8 + - _id: e83b435a530574a277932bc0a0cad82a _order: 0 cache: {} request: - bodySize: 735 + bodySize: 101 cookies: [] headers: - _fromType: array @@ -997,258 +856,50 @@ log: value: "*/*" - _fromType: array name: content-length - value: "735" + value: "101" - _fromType: array name: accept-encoding value: gzip,deflate - name: host value: sourcegraph.sourcegraph.com - headersSize: 352 + headersSize: 356 httpVersion: HTTP/1.1 method: POST postData: mimeType: application/json; charset=utf-8 params: [] textJSON: - query: >- + query: |- - query GetCodyContext($repos: [ID!]!, $query: String!, $codeResultsCount: Int!, $textResultsCount: Int!) { - getCodyContext(repos: $repos, query: $query, codeResultsCount: $codeResultsCount, textResultsCount: $textResultsCount) { - ...on FileChunkContext { - blob { - path - repository { - id - name - } - commit { - oid - } - url - } - startLine - endLine - chunkContent - } + query SiteProductVersion { + site { + productVersion } } - variables: - codeResultsCount: 15 - query: overview squirrel - repos: - - UmVwb3NpdG9yeTozOTk= - textResultsCount: 5 - queryString: - - name: GetCodyContext - value: null - url: https://sourcegraph.sourcegraph.com/.api/graphql?GetCodyContext - response: - bodySize: 5426 - content: - encoding: base64 - mimeType: application/json - size: 5426 - text: "[\"H4sIAAAAAAAA/+w7gXLbuI6/gtXOzTk5W9o0bd+udzKzbZru5l7a9CXuu3tXZVRKgmS+S\ - KSWpJykTf79BiRly46dJu3ezd1sPJ2pDQIgCIAACDKfg5wZFow/ByWafZlf7Uth8NIE\ - 4w+fg7SSKQ01zEyDcZDVeaSv6lRWOuLCoBKsivTvLVcKq+jk4MWrNwdhnQfDQGEjNTd\ - SXRE5z4Nx8L7++0W6+7bJf/3pCify0/HkfC8YBoLVGIyDkptpm4aZrCMtW5VhqVgz7X\ - 8PboZBJuuaG2IpLU98nuY/PsOn6V+eZc+znR8xYz/uPNn96Qf2Y8qePn/2Y7aLu5gWR\ - NuqKhgH0Zcn+uW+XKNRRAqK7quWm2GgDVPmiAsMxj8MAxS5+/5kGGTTVpxb3QsTjIPv\ - 4dQziEUsgpvhLWPkMotynEUpy85LJVuRj7gopKqZ4VJE+vcq4iLHyz+hQR6ims1G2fl\ - hnVX+dkQG+bXlORMZAhM55DJraxTGcgeWytbAheKGixJoc6VMI1jHYBmhaLjgZsoFmC\ - nC6WKdwJqm4pllE9IsI/jwhpeKOSI5QzXjeHE2qOfApAOGdb61QtDH64Z/4+V01KCyy\ - iD5y5bnqGMBMIIPL5nJpiAbnHNICZIsII6PRX7DDCrOKv4Jc8hYNsWzQd2DJRY2l+tI\ - ZuekkBSnbMalOhtUDpJ0EIe6ztVD5yPRu/dHR8nJwd/eH5xOksnBm3dHLyYHZGmsSMS\ - EC83LqdF/Qpf/GhXdEY+e3XL9uP3hh93su9EIXqHOFE/Rum/TqkZqBFnYn+9OQEswU2\ - aAF3AlW6ikPMccCGCAC3gOtRRmqsHwGgl2IdsqhxQhq5ApKJSsLavOs+FiegVmyjVcM\ - A2ZQmYwh9HICoSx+P57OPaosTgUGpWB3IrY2P04RYVhaPfTYg0eL8VCKreJWWFQgc4U\ - otBTaQZ6y62jZueoSVBk+gqMBJ6jMLy4slJmUyZK1FCzHJeFOp2z0rG4hpcHr49PDqD\ - /uQZ48XpycALXsRiPNn3G13eMxaJbCq9ZiXaxcL0GBnb9PQ28b3JmnA153VS4CGDaYK\ - Pd2vV0bhxJSKR50kBHYMkLZKZVGKVtCQW/jAxmU8gxNdaiom2W9fJOyVKh1jYqwBkcL\ - s/e+GGoeYXaSDGPTnAGbzoY/CcBO/CE6XPYuQV5so7wH+uA/7UOaJ3GAV8tRXgqj6KF\ - p2horS5zGPACFFY4Y8JsdbT71kMqWS6htRrVqGAZF+Uc80XTKDnDHNIrYLQRaO/lgKL\ - kAlFZOiPbbEpxdD6cyRw3sKD8t5lDN3oHgxw1L4Un5MbRorZmf3+4IVpT5s2qVlMqEO\ - WftyzcqIc74u7TNSXHBC8N7M8Z0TaeUDjMucKMdAmZFIZxoeHdlZlKYS1K+9TPbh3WV\ - iLQarK8RuKeIWCdYp5zUWobA//6BpnQsBDaRs2lAEtzI3z0KGFz9RFcqAXj4qQABpPT\ - v0PBK7R1DjA3f8GxyodQoqBiAvVaKZx8ti7yoxPFhKZyBZWGiqeKqathJ6LzxB69ndA\ - tY2iXJFvTtEbfEqpTDdPk4bS3dditrpSsAq5Jg1Q9NqB5zSvm9agFbxo0NFyimaKi0k\ - 4Cg0ZhjgUXmINo6xQVJcVO0E6T7zUrkb4fCN0qF38VUqmPOTRUr6IGpqhe1IZVFeZjw\ - v748WMsGt50YBipjszJbi6Nx3Jr8EZhWYaNcWoqZFXJC9IvU6UNZ9ryvoYX/vc8L73q\ - 5c97fYikYG1lWVwTz+VEBauAL3+WSBzPj6MRF01rPnaTvg==\",\"Y2ZqExJBFxa+S8\ - 7kxGs7mfMksybWPT/CNbxltStn5k4LvlQ3eub4G+mLZAQp4BrigJDjAPzqv+K4JlONa\ - sZSXnFz9Xhwe5CSluPpk/4R7qfbdawPnksZnWsopPKxyZ5ehpShM6ZxxEohteEZ+CLa\ - bhRZ9A9u/6phSbQwFv1jHdZNJa+QQp6rp1ilJSgsKDRL61ofpkzkqZTnq6xAoz0zng2\ - mxjR6HEUdZthTtDVCl+Up2Szx2LKL60k00g1mvKA19dWwqJER3h5PDsbwWiqYyguScr\ - vVuH3Xol0VLRZ1uyxAtmoFyReLeriy/hUsqUBzg8DymguujWJGqhWrnQ3CMHL/LNoG9\ - 9hal8SOlyU3S8dwLrKqzbGLjsvh8BoOLhmVrNrGj/FodN2PWvMfNrhsb7+RgjYvF+X2\ - NlxbZdKp6FzIC0gupigS0LJGYysyOuMoKUqakulpKpnKNZBFnjyHGo3iGaW1CpXhohz\ - CFFlFuWyK2bkTB7a3X2HaluXqhDlBaUZmkv48E2Vr0CFU0hIRF6utfSls6vB9iL5+6v\ - maoOFVxZT+Fu+MFuwSz25DYXl3n41Y8gwTg9qEpfyzhc6HKWdzCfp091bIpLKEDpK61\ - 5HkdSOVgUEsYhMHmesZx4H7KXX3jSwXUc6kLx1QVzzDOYqWak5I4lGJG9hIZOK+RQpm\ - +DTKZCVVh94bLaUsK4xKOcrqJsrqZh2OYgUTLFJY4mWzdpIN1uhpFJnKpmuY35MyUqj\ - bynwNA3PVOK1tkeBFKzLggpvBFnwmZryAZAjyHMZ7IHV4JOV52xyI2SAO3h4n+8dHxy\ - dxsPUzfCfPHUFsrDLDt3Kf/oc9KFilqTg1N7G4mU8yQW3eSnEkM1a9ogKXUyAcGNj25\ - gonXgTacK+40kNApbwcJ8jyV1wNnHETuyfjgJZgCmZYdVgcKCXVEUuxGhhLOYQ4UMhy\ - exRYIRKxYUJI43ui4z34cLYAfL5xKET9miq18R7QGgaZuQTvpKG/4BhCY6tH0mp4go3\ - ct/uaSsotGHw4S68MWnGk2uoUptC0SnTLohkGnXOH/y65WFmlm8Iy918t9y2vYvrPYN\ - 10nX6S9i1eDDrphyB4ZZFZVZ26ve1W7JwodLBu0ZQ0E8qr1giEqJgosQPobhG8gO88L\ - DzUZJv5+mJjwtdklWIQB63AywYzg7mrev/FrqijpDJ54JbiF/PVIfsxWm/Wy+ZAvfv8\ - 2wN1Ua+J2aoVhtc4j89GZVLMej/ppH2/EK25oUP2cpyrWXaOikK1UYgjh9Px80qZ0K6\ - Ee8XHtaqcx8qvDrL3JKx4GtkYsYjMUQS/uZqZNjIwu3vCWBBr6Pb2a4qsLjSthqV7RS\ - Q/URc6Tp3H0KFFQ0+ttiinAttrCLxrkXRMsOrqk+t+G8VmqDRaWW3no+Ait1N4ym4Bq\ - zNqo9rMdPHfh93ep7/ghYFPbTLscPpGD91Qh54SfabaOtVzli8XMEJpmNKols/52275\ - 4Ts7RlhZJTVLaXGLz4czawEbxKxaj4UleM141SqEVEraQybHxkxXOglcGJ8ko4iitr+\ - Z0MBA4MWqmkKfS/vhfUk1Q1hSzAaNbMH2qv694m1ecieFFYzPXxOZ949fHbw9nhy+/s\ - djZN6gl82R+fa98fY2/DJjqhUlE/mUj7TKHmAV1nB7rqpQJVkpH9PlRrUs22Sn3wra/\ - cvtVtADc0OpmiyyPFyCaJQ08n5JauFJfhWzHcejGzD3T3h/ZK6yQYnSOyrTxQ1bj0/k\ - r6rJ7NcBFfO+Dt7WhplWh6f2v/nBw3END/XAlu/ddgnfC4WZLAX/hDbSHVwaFJpLcbC\ - urA==\",\"9rwpRmYyRx0eihmreN61p23uC51MiyL67vl121D9g/kRE2XLSrzfzO/F/\ - I4T8w3zelrBq0UisIekfZnjoTBYgUPRUBHYXcuQ9aqKl/bmg0p2ys4ln6FwVTazN3K0\ - Cb11Bhq2yfN8ON9amWOg8PcWtYFt647h8uiJGxyC1uDG/TnCc0uW0QmKasvp0+lIr+S\ - b8d5CvaQvHS6nse7Iktv23gp1uF9JjYPuIKdKe57xKwh/RbNc9Qy2wok89O7eUdFRjo\ - TQXcXk8nfDrirJ8vnRc3XmFa1l5nIIJMDWwoXguz0SH74qYy7OfVFjb+Ei3aYRul7hb\ - thcPcbsh6nrYa/lAGbQXIVzBgXkWMQixwKKwdb4Gy1KglRMnUfppyrxl5Bh+ql6tOlD\ - FfZgqy4+0OO1sG4P+O12/iebsZ1Iq8x646n1pSchQR8t/XCVbbb1Ha2LNv3Z51Jrfdj\ - fdbbOKqY1/frs3vk4BPBYhceyp0nDDM8o0UKx+/MftfP/4/jkr6fvXuwfPHrC/VV1x+\ - Patbt9w2c22xQGFBn9jzHwy/eHR68ejXs/Nf2/M2yYsk/4mK8fpKz/q0aeyhmqx3veL\ - 6vmjgR8u0f14MuD/k3AF+5u/9daGRPU5jfSwbrrSSpK6Gj4cV5NOPhM8hzqxS1YFIGQ\ - Bpg9h6MwUHGBflU02AfDznrwE3/XJgxcwh48+3lxrfrRsSplxUTp5bHC14yLToo7ZFg\ - rwdr5Z0zB5bxT7efN9JSpxs9LG0I3LEN4LWVXWjnlvGSqA/SqKqurl+zTgFbW9C4O71\ - TaRrVtVFwnfKc633NZ0iDZ11+I9m8hYmMvdp3Q/sWsvey2nq6XgBfMv3pcAG88k8/Op\ - W0pGwdDoP+HEAcry4jFivixiIOb4TKPUhIHZ/Gv5ZHZ61dnvYfx+B++FPf3ziTk4tLZ\ - 2eZbOynztKTtueLxyP1AXT3wj9u+NoVXkuWDOIii8cpxnzw2DnpA+4jjTvSs1UbWSX+\ - OvTU8YjHvDkDC66ZadATsT9sLINEbpnWHvm5Vntquo99LsNA9N/pV79Fud7h8c+rJYz\ - PwQap6kBP7isXTA9PAduZ1jIfGwv6RWYfjB/d3hrC/YymeeIxQt+m8pdjhFRZld8mnZ\ - rb5uL/j3GjtRroHygPQHoi6QO81SL/9iLXc+9Ft+sQ3gHYfe2bforc7PP72g/Ze54z8\ - dbmBRjEO/EQ2tc8HvEt07uOdm5js71gGvkR+CnhpUOSaUHu9N6J9GhY7i76bbbg5Wsu\ - 8V1V3E3Zz9yZeHVr1WTfJl1GXqVZJSDZKJPs7xO3f7N+Tum+6bVCFVm5CvOnE708ym0\ - H97FaD0S3w2eBQGCxRAd+Cz0T/8C312KG4h2LueAl3ux0xLzFynI1LmeRY6EVBUkp7R\ - O4XI79wmdh5EtVWqJNSRlEpxzkWS2TLJcgCMHCeQQax5cr8EB0Mvc+oTMMefFi4ZBz0\ - 3ja5E0J/0J7kb4PpBJFQkNgw5PLnhsGuRFw/3LIS1whi766TTOaY2Lvr2xiL54orA63\ - hS+hn/n/7B3tzjcwnHxW8whF2bwR0+E8tRRx0VC5E2fPJ3jc8DbxlGsNKK8jkxa/Ju6\ - MXk9fHJ2+S04MXJ/u/dVPPuOb+b0WsxFGf9ThJdJv6MKyTZCFxjs0to0d3PlgcLqP23\ - 7psHiQ1ZZuHuyfrd4/PH6ZvQlsvYb8RszT0SybrxNkose9CE/suNIrG/n3oRmz/TD9x\ - z/SjaNy9199I4Z+UJrSvFWLiHv9F0Xj1jemQovPZzc1/BwAA//84ilWu9UYAAA==\"]" - cookies: [] - headers: - - name: date - value: Tue, 16 Jul 2024 15:15:02 GMT - - name: content-type - value: application/json - - name: transfer-encoding - value: chunked - - name: connection - value: keep-alive - - name: retry-after - value: "519" - - name: access-control-allow-credentials - value: "true" - - name: access-control-allow-origin - value: "" - - name: cache-control - value: no-cache, max-age=0 - - name: content-encoding - value: gzip - - name: vary - value: Accept-Encoding, Authorization, Cookie, Authorization, X-Requested-With, - Cookie - - name: x-content-type-options - value: nosniff - - name: x-frame-options - value: DENY - - name: x-xss-protection - value: 1; mode=block - - name: strict-transport-security - value: max-age=31536000; includeSubDomains; preload - headersSize: 1356 - httpVersion: HTTP/1.1 - redirectURL: "" - status: 200 - statusText: OK - startedDateTime: 2024-07-16T15:15:01.805Z - time: 0 - timings: - blocked: -1 - connect: -1 - dns: -1 - receive: 0 - send: 0 - ssl: -1 - wait: 0 - - _id: b4499992cdf92807c09248d1e216cbdb - _order: 0 - cache: {} - request: - bodySize: 253 - cookies: [] - headers: - - _fromType: array - name: authorization - value: token - REDACTED_964f5256e709a8c5c151a63d8696d5c7ac81604d179405864d88ff48a9232364 - - _fromType: array - name: content-type - value: application/json; charset=utf-8 - - _fromType: array - name: user-agent - value: jetbrains / 6.0.0-SNAPSHOT - - _fromType: array - name: accept - value: "*/*" - - _fromType: array - name: content-length - value: "253" - - _fromType: array - name: accept-encoding - value: gzip,deflate - - name: host - value: sourcegraph.sourcegraph.com - headersSize: 350 - httpVersion: HTTP/1.1 - method: POST - postData: - mimeType: application/json; charset=utf-8 - params: [] - textJSON: - query: | - - query Repositories($names: [String!]!, $first: Int!) { - repositories(names: $names, first: $first) { - nodes { - name - id - } - } - } - variables: - first: 1 - names: - - github.com/sourcegraph/sourcegraph + variables: {} queryString: - - name: Repositories + - name: SiteProductVersion value: null - url: https://sourcegraph.sourcegraph.com/.api/graphql?Repositories + url: https://sourcegraph.sourcegraph.com/.api/graphql?SiteProductVersion response: - bodySize: 175 + bodySize: 139 content: encoding: base64 mimeType: application/json - size: 175 - text: "[\"H4sIAAAAAAAAA6pWSkksSVSyqlYqSi3IL84syS/KTC0G8fPyU0CM6GqlvMTcVCUrpfTMk\ - ozSJL3k/Fz94vzSouTU9KLEggxktpKOUmaKkpVSaG5YeZKxX0GKu2Vlakh+lX9Itq1S\ - bWxtbS0AAAD//w==\",\"AwARSH8wbwAAAA==\"]" + size: 139 + text: "[\"H4sIAAAAAAAAA6pWSkksSVSyqlYqzixJBdEFRfkppcklYalFxZn5eUpWSkYW5iYmRvFGB\ + kYmugYWuobG8aZ6ZrrGpkZGKclpJolpKclKtbW1\",\"AAAAAP//AwD5OZ82SQAAAA==\ + \"]" cookies: [] headers: - name: date - value: Tue, 16 Jul 2024 15:15:00 GMT + value: Tue, 13 Aug 2024 19:01:27 GMT - name: content-type value: application/json - name: transfer-encoding value: chunked - name: connection value: keep-alive - - name: retry-after - value: "520" - name: access-control-allow-credentials value: "true" - name: access-control-allow-origin @@ -1268,12 +919,12 @@ log: value: max-age=31536000; includeSubDomains; preload - name: content-encoding value: gzip - headersSize: 1356 + headersSize: 1249 httpVersion: HTTP/1.1 redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-16T15:15:00.245Z + startedDateTime: 2024-08-13T19:01:27.565Z time: 0 timings: blocked: -1 @@ -1283,83 +934,73 @@ log: send: 0 ssl: -1 wait: 0 - - _id: e83b435a530574a277932bc0a0cad82a + - _id: 277d6b682e1c0a9e7bf94342d2ae2090 _order: 0 cache: {} request: - bodySize: 101 + bodySize: 0 cookies: [] headers: - _fromType: array name: authorization value: token REDACTED_964f5256e709a8c5c151a63d8696d5c7ac81604d179405864d88ff48a9232364 - - _fromType: array - name: content-type - value: application/json; charset=utf-8 - _fromType: array name: user-agent value: jetbrains / 6.0.0-SNAPSHOT - _fromType: array name: accept value: "*/*" - - _fromType: array - name: content-length - value: "101" - _fromType: array name: accept-encoding value: gzip,deflate - name: host value: sourcegraph.sourcegraph.com - headersSize: 356 + headersSize: 294 httpVersion: HTTP/1.1 - method: POST - postData: - mimeType: application/json; charset=utf-8 - params: [] - textJSON: - query: |- - - query SiteProductVersion { - site { - productVersion - } - } - variables: {} - queryString: - - name: SiteProductVersion - value: null - url: https://sourcegraph.sourcegraph.com/.api/graphql?SiteProductVersion + method: GET + queryString: [] + url: https://sourcegraph.sourcegraph.com/.api/modelconfig/supported-models.json response: - bodySize: 136 + bodySize: 769 content: encoding: base64 - mimeType: application/json - size: 136 - text: "[\"H4sIAAAAAAAAA6pWSkksSVSyqlYqzixJBdEFRfkppcklYalFxZn5eUpWSkYWRqbGxvFGB\ - kYmugbmuoZm8aZ6prqJBomGFolmBqmWBiZKtbW1AAAAAP//AwBtpsiNSQAAAA==\"]" - textDecoded: - data: - site: - productVersion: 282533_2024-07-16_5.5-a0a18a60e904 + mimeType: text/plain; charset=utf-8 + size: 769 + text: "[\"H4sIAAAAAAAA/+yZT1OjPhjH730VDNefYBqK9cfN7YyuB1dndXYPOx7S8LTNCAmThFrH8\ + b3vQFoUSgutTl2tnpB8n28SPk/+9rFjWZZlKzqBmPw=\",\"AqmY4HZg2V0X2QemTMK\ + ULV4jF7novxCmi8JEiikLQSo7sP7kr7K/x+IpF7EwiyVcT6RIGJ3HFsUhU0lEHn6QGD\ + LdSaErZE8H661HTMK9kHeqwfq00LW2HgsxjqDB98yIWpuKBDhhDaaXCfCT8/amMVNak\ + qjB9WKuerbNn27nPGMRQrQWZq74CaMS0iDACHsOOnJQNwhoRNIQHM9RgnPQDS0a5GrL\ + s65r1Xl9C23F2cEI9xDG/1eDKEnIkEVMMyh3plCQVAsq4iQCXaVrHCZE26XXt0t1aBg\ + L+ZC1a0giwimE1XYoTXSatSB7Gi7nkWYg8wSWsFRGBdcw078ZD8W9HVQ4mG9DZuc8Sf\ + WNuAOeVeMhhFBNb2Iyu0z1S2UPIVTSPbVItA3Yu/5m9F1/I/5+KQOOMHrvDCCUppLQh\ + 20zIJHicyWAI5K0aT4uhv5ljbYefOb6zwz7L+hV6BPC7tK21L/Xieux576Gu4f6781d\ + JbD9XP9G0Ps7Y17sroJg2g0CpYmkIgTZgPlaEzmo05UIr3TbkOmHYodR77gVO+wfvQq\ + d2b0abmOIGWdO1/WdRAonIhpU0+p8lsdYXde3rpa7XgLZyv5rgq4K33qwriA+ioiabM\ + z8NItqS31dFfs4Qe8Q+vzoZ6jHbJb94xzP+kOHcaVlSpuYX5gY63jW/7aWN6FUpFyrw\ + 2JRODRHxsNW1e5jHuxuoV6RBhhvkQcYvz4R1lW8pyvB7pLB3DHl2/Seg3C+TR8n2ukt\ + 9aM6/1/d1IjKs36tz54i3eE8v5Kpo1M5bAXWuqlTLtOtd/xo92qfZtR6rt+asef6LSm\ + vdP1ap1/qNoDcedFTO4QRSSN9sbhTf26F+Tzb3aLaI6L0oF18TXR22B4YcPMfdVae7z\ + umS0+dvwEAAP//+9VDaCYaAAA=\"]" cookies: [] headers: - name: date - value: Tue, 16 Jul 2024 15:14:57 GMT + value: Tue, 13 Aug 2024 19:01:28 GMT - name: content-type - value: application/json - - name: transfer-encoding - value: chunked + value: text/plain; charset=utf-8 + - name: content-length + value: "769" - name: connection value: keep-alive - - name: retry-after - value: "523" - name: access-control-allow-credentials value: "true" - name: access-control-allow-origin value: "" - name: cache-control value: no-cache, max-age=0 + - name: content-encoding + value: gzip - name: vary value: Accept-Encoding, Authorization, Cookie, Authorization, X-Requested-With, Cookie @@ -1371,14 +1012,12 @@ log: value: 1; mode=block - name: strict-transport-security value: max-age=31536000; includeSubDomains; preload - - name: content-encoding - value: gzip - headersSize: 1356 + headersSize: 1251 httpVersion: HTTP/1.1 redirectURL: "" status: 200 statusText: OK - startedDateTime: 2024-07-16T15:14:57.299Z + startedDateTime: 2024-08-13T19:01:28.257Z time: 0 timings: blocked: -1 diff --git a/agent/src/TestClient.ts b/agent/src/TestClient.ts index f13d024d0637..e134035fc83a 100644 --- a/agent/src/TestClient.ts +++ b/agent/src/TestClient.ts @@ -102,7 +102,7 @@ export function buildAgentBinary(): void { // To see the full error, run this file in isolation: // // pnpm test agent/src/index.test.ts - execSync('pnpm run build ', { + execSync('pnpm run build:for-tests ', { cwd: getAgentDir(), stdio: 'inherit', }) diff --git a/agent/src/cli/__snapshots__/command-chat.test.ts.snap b/agent/src/cli/__snapshots__/command-chat.test.ts.snap index d2c683878102..3520aec046ea 100644 --- a/agent/src/cli/__snapshots__/command-chat.test.ts.snap +++ b/agent/src/cli/__snapshots__/command-chat.test.ts.snap @@ -11,25 +11,12 @@ stdout: |+ - Here's a simple implementation of a cow in Python: - - \`\`\`python - class Cow: - def __init__(self, name): - self.name = name - self.milk = 0 - - def moo(self): - return f"{self.name} says: Moo!" - - def produce_milk(self, amount): - self.milk += amount - return f"{self.name} produced {amount} liters of milk." - - def get_milk(self): - milk_produced = self.milk - self.milk = 0 - return f"Collected {milk_produced} liters of milk from {self.name}." + \`\`\`typescript + class Cow implements StrangeAnimal { + makesSound(): 'coo' | 'moo' { + return 'moo'; + } + } \`\`\` stderr: "" diff --git a/agent/src/cli/command-chat.ts b/agent/src/cli/command-chat.ts index aa15ac7761ec..8bebd7f12752 100644 --- a/agent/src/cli/command-chat.ts +++ b/agent/src/cli/command-chat.ts @@ -1,4 +1,4 @@ -import ora, { spinners } from 'ora' +import ora, { type Ora, spinners } from 'ora' import path from 'node:path' @@ -6,7 +6,9 @@ import type { Polly } from '@pollyjs/core' import { type ContextItem, ModelUsage, TokenCounter } from '@sourcegraph/cody-shared' import { Command } from 'commander' +import Table from 'easy-table' import * as vscode from 'vscode' +import type { ExtensionTranscriptMessage } from '../../../vscode/src/chat/protocol' import { activate } from '../../../vscode/src/extension.node' import { startPollyRecording } from '../../../vscode/src/testutils/polly' import packageJson from '../../package.json' @@ -33,6 +35,7 @@ export interface ChatOptions { debug: boolean silent: boolean isTesting?: boolean + ignoreContextWindowErrors: boolean streams?: Streams } @@ -74,6 +77,11 @@ Enterprise Only: ) .option('--context-file ', 'Local files to include in the context') .option('--show-context', 'Show context items in reply', false) + .option( + '--ignore-context-window-errors', + 'If true, does not fail fast when a context file is too large to fit into the LLMs context window', + false + ) .option('--silent', 'Disable streaming reply', false) .option('--debug', 'Enable debug logging', false) .action(async (options: ChatOptions, cmd) => { @@ -149,8 +157,19 @@ export async function chatAction(options: ChatOptions): Promise { }) } + if (!serverInfo.authStatus?.isLoggedIn) { + notLoggedIn(spinner) + return 1 + } + + const endpoint = serverInfo.authStatus.endpoint ?? options.endpoint + const tokenSource = new vscode.CancellationTokenSource() + const token = tokenSource.token + + let isFirstMessageCheck = true + messageHandler.registerNotification('webview/postMessage', message => { - if (message.message.type === 'transcript') { + if (message.message.type === 'transcript' && !token.isCancellationRequested) { const lastMessage = message.message.messages.at(-1) if (lastMessage?.model && !spinner.text.startsWith('Model')) { const modelName = @@ -159,14 +178,18 @@ export async function chatAction(options: ChatOptions): Promise { spinner.spinner = spinners.dots } spinner.prefixText = (lastMessage?.text ?? '') + '\n' + + if (isFirstMessageCheck && !options.ignoreContextWindowErrors) { + const contextFiles = message.message.messages.at(0)?.contextFiles + if (contextFiles && contextFiles.length > 0) { + isFirstMessageCheck = false + } + + validateContext(message.message, spinner, endpoint, tokenSource) + } } }) - if (!serverInfo.authStatus?.isLoggedIn) { - notLoggedIn(spinner) - return 1 - } - spinner.text = 'Asking Cody...' const id = await client.request('chat/new', null) @@ -239,16 +262,24 @@ export async function chatAction(options: ChatOptions): Promise { return 1 } const addEnhancedContext = isNonEmptyArray(options.contextRepo) - const response = await client.request('chat/submitMessage', { - id, - message: { - command: 'submit', - submitType: 'user', - text: messageText, - contextFiles, - addEnhancedContext, + const response = await client.request( + 'chat/submitMessage', + { + id, + message: { + command: 'submit', + submitType: 'user', + text: messageText, + contextFiles, + addEnhancedContext, + }, }, - }) + { token: tokenSource.token } + ) + + if (token.isCancellationRequested) { + return 1 + } if (response.type !== 'transcript') { spinner.fail( @@ -281,15 +312,10 @@ export async function chatAction(options: ChatOptions): Promise { spinner.clear() if (options.showContext) { - const reponseContextFiles = response.messages.flatMap(m => m.contextFiles ?? []) + const responseContextFiles = response.messages.flatMap(m => m.contextFiles ?? []) streams.log('> Context items:\n') - for (const [i, item] of reponseContextFiles.entries()) { - const uri = vscode.Uri.from(item.uri as any) - const endpoint = serverInfo.authStatus.endpoint ?? options.endpoint - // Workaround for strange URI authority resopnse, reported in - // https://sourcegraph.slack.com/archives/C05AGQYD528/p1721382757890889 - const remoteURL = new URL(uri.path, endpoint).toString() - const displayText = uri.scheme === 'file' ? uri.fsPath : remoteURL + for (const [i, item] of responseContextFiles.entries()) { + const displayText = uriDisplayText(item, endpoint) streams.log(`> ${i + 1}. ${displayText}\n`) } streams.log('\n') @@ -300,6 +326,14 @@ export async function chatAction(options: ChatOptions): Promise { return 0 } +function uriDisplayText(item: ContextItem, endpoint: string): string { + const uri = vscode.Uri.from(item.uri as any) + // Workaround for strange URI authority resopnse, reported in + // https://sourcegraph.slack.com/archives/C05AGQYD528/p1721382757890889 + const remoteURL = new URL(uri.path, endpoint).toString() + return uri.scheme === 'file' ? uri.fsPath : remoteURL +} + function toUri(dir: string, relativeOrAbsolutePath: string): vscode.Uri { const absolutePath = path.isAbsolute(relativeOrAbsolutePath) ? relativeOrAbsolutePath @@ -346,3 +380,32 @@ async function readStdin(): Promise { process.stdin.on('error', reject) }) } + +function validateContext( + message: ExtensionTranscriptMessage, + spinner: Ora, + endpoint: string, + tokenSource: vscode.CancellationTokenSource +): void { + const tooLargeItems = message.messages.flatMap(messages => + (messages.contextFiles ?? []).filter(item => item.isTooLarge) + ) + if (tooLargeItems.length > 0) { + const t = new Table() + for (const item of tooLargeItems) { + t.cell('File', uriDisplayText(item, endpoint)) + t.cell('Reason', item.isTooLargeReason) + t.newRow() + } + spinner.text = '' + spinner.prefixText = '' + spinner.fail( + 'The provided context is too large to fit into the context window. \n' + + 'To fix this problem, either remove the files from --context-file or\n' + + 'edit these files so they become small enough to fit into the context window.\n' + + 'Alternatively, set the flag --ignore-context-window-errors to skip this check.\n\n' + + t.toString() + ) + tokenSource.cancel() + } +} diff --git a/vscode/src/jsonrpc/jsonrpc.ts b/vscode/src/jsonrpc/jsonrpc.ts index c28e1a78da14..e7468f05b643 100644 --- a/vscode/src/jsonrpc/jsonrpc.ts +++ b/vscode/src/jsonrpc/jsonrpc.ts @@ -109,8 +109,14 @@ export class MessageHandler { public async request( method: M, - params: ParamsOf + params: ParamsOf, + extra?: { token?: vscode.CancellationToken } ): Promise> { + if (extra?.token !== undefined) { + return await this.conn.sendRequest(method, params, extra.token) + } + // Strangely enough: the tests will fail with a cryptic error if we pass + // an undefined `token` variable as the third parameter to `sendRequest`. return await this.conn.sendRequest(method, params) } @@ -133,10 +139,11 @@ export class MessageHandler { request: async ( method: M, params: ParamsOf, - cancelToken: vscode.CancellationToken = new vscode.CancellationTokenSource().token + extra?: { token?: vscode.CancellationToken } ) => { const handler = this.requestHandlers.get(method) if (handler) { + const cancelToken = extra?.token ?? new vscode.CancellationTokenSource().token return await handler(params, cancelToken) } throw new Error(`No such request handler: ${method}`)