= ({ navigator }) => {\n return (\n \n {/* Code navigation UI components */}\n
\n )\n}\n```\n\nThe name \"Squirrel\" is just a codename - it's focused on code navigation functionality rather than anything related to the animal. If you're looking to work with actual animal-related code, you might want to use the `Animal` interface from the codebase instead, which has proper animal-related properties like `makeAnimalSound()` and `isMammal`.","stopReason":"end_turn"}
+ data: {"deltaText":"The Squirrel interface in the codebase is used for precise code navigation in Sourcegraph, rather than representing actual squirrels. While it's currently an empty interface, I can show you how it could be implemented along with the existing Animal interface for a fun example:\n\n```typescript:src/squirrel-example.ts\nimport { Animal } from './animal'\nimport { Squirrel } from './squirrel'\n\nclass TreeSquirrel implements Animal, Squirrel {\n name: string\n isMammal: boolean = true\n \n constructor(name: string) {\n this.name = name\n }\n\n makeAnimalSound(): string {\n return \"Chitter chitter!\"\n }\n \n // Squirrel-specific behaviors\n collectNuts(): number {\n return Math.floor(Math.random() * 10)\n }\n}\n\n// Usage example\nconst rocky = new TreeSquirrel(\"Rocky\")\nconsole.log(rocky.makeAnimalSound()) // \"Chitter chitter!\"\nconsole.log(rocky.collectNuts()) // Returns random number of nuts collected\n```\n\nThe interesting part is that while this interface is named Squirrel, according to the code comments it's actually used for implementing precise code navigation features in Sourcegraph, making it a clever naming choice that has nothing to do with actual squirrels. \n\nIf you want to actually use it for code navigation purposes, you would implement it differently based on Sourcegraph's navigation requirements rather than animal behaviors.","stopReason":"end_turn"}
event: done
@@ -673,7 +659,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:29 GMT
+ value: Fri, 27 Dec 2024 20:51:34 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -686,10 +672,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -701,13 +683,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:23.690Z
- time: 8303
+ startedDateTime: 2024-12-27T20:51:31.170Z
+ time: 6206
timings:
blocked: -1
connect: -1
@@ -715,7 +697,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 8303
+ wait: 6206
- _id: f8077b99cfdf098868b18e9fc6fa0d2f
_order: 0
cache: {}
@@ -733,7 +715,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-680c71ba138070f8daf1d942967f28be-e90ce1fae9a25fdd-01
+ value: 00-08eabf9fc881da370682a58d75430b76-6cd427a136379898-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -773,14 +755,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 650
+ bodySize: 616
content:
mimeType: text/event-stream
- size: 650
+ size: 616
text: >+
event: completion
- data: {"completion":"The color of the sky is most often blue, due to Rayleigh scattering of sunlight in the atmosphere. However, it can also appear other colors, such as red, orange, or yellow, at sunrise and sunset.\n","stopReason":"STOP"}
+ data: {"completion":"The color of the sky is typically blue, due to Rayleigh scattering of sunlight. However, it can appear other colors, such as red or orange at sunrise and sunset.\n","stopReason":"STOP"}
event: done
@@ -790,7 +772,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:32 GMT
+ value: Fri, 27 Dec 2024 20:51:38 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -803,10 +785,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -818,13 +796,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:32.016Z
- time: 920
+ startedDateTime: 2024-12-27T20:51:37.415Z
+ time: 864
timings:
blocked: -1
connect: -1
@@ -832,7 +810,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 920
+ wait: 864
- _id: 29c983c5199325c822425ef1c36ee77a
_order: 0
cache: {}
@@ -850,7 +828,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-414c1b055e9331ffc93c95adc479baa7-9f86606ad88f2fef-01
+ value: 00-76e7a37fd2ca70937df155b30de5c145-7d4263dda2d548c9-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -905,7 +883,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:33 GMT
+ value: Fri, 27 Dec 2024 20:51:38 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -918,10 +896,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -933,13 +907,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:32.963Z
- time: 544
+ startedDateTime: 2024-12-27T20:51:38.312Z
+ time: 535
timings:
blocked: -1
connect: -1
@@ -947,7 +921,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 544
+ wait: 535
- _id: 1304ba73f8175936050d1ffe20a05d88
_order: 0
cache: {}
@@ -965,7 +939,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-bb5188553f446c94d629f6a4e596a619-cc6eee71bddfe9f5-01
+ value: 00-197b4d40378055c4685d1a8d92fdc79a-8dacf6a01d2b1656-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -1024,7 +998,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:34 GMT
+ value: Fri, 27 Dec 2024 20:51:39 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -1037,10 +1011,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -1052,13 +1022,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:33.528Z
- time: 490
+ startedDateTime: 2024-12-27T20:51:38.872Z
+ time: 504
timings:
blocked: -1
connect: -1
@@ -1066,7 +1036,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 490
+ wait: 504
- _id: 8a4643f5397eb4fbf5528fdaa1edd627
_order: 0
cache: {}
@@ -1084,7 +1054,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-65c7bb7ba899cca92569c1d0937e943d-8ae4bc63435c3331-01
+ value: 00-c245d2d098c42ae15944e207e6f5ce4e-35044a07d3f7eea5-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -1124,14 +1094,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 4811
+ bodySize: 7933
content:
mimeType: text/event-stream
- size: 4811
+ size: 7933
text: >+
event: completion
- data: {"completion":"I am Cody, an AI coding assistant from Sourcegraph. How can I assist you with Kramer? Kramer usually refers to a character from the TV show Seinfeld, or it can be a surname. If you're referring to some programming-related context, could you please provide more details?\n# For example, if you have a Python script named \"kramer.py\":\n```python:kramer.py\ndef kramer_function():\n # Your code here\n```\nRegarding the file, provide the relevant file path (e.g., \"kramer.py\") for me to assist you better.","stopReason":"stop"}
+ data: {"completion":"Hello! How can I assist you with your coding needs today, Kramer? If you have any questions or issues related to programming, I'm here to help.\n\nJust let me know what you need, and I'll do my best to provide you with accurate, helpful, and positive responses. If your question involves a specific piece of code, please include the relevant file path in the code block so I can better understand the context.\n\nFor instance, you can format your code like this:\n```python:path/to/your/code.py\ndef hello_world():\n return \"Hello, world!\"\n```\nThis way, I can provide you with a more precise solution tailored to your particular situation.\n\nRemember, whenever you need any programming help, feel free to reach out to your trusty AI sidekick, Cody! 😊","stopReason":"stop"}
event: done
@@ -1141,7 +1111,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:34 GMT
+ value: Fri, 27 Dec 2024 20:51:40 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -1154,10 +1124,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -1169,13 +1135,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:34.031Z
- time: 1202
+ startedDateTime: 2024-12-27T20:51:39.402Z
+ time: 1253
timings:
blocked: -1
connect: -1
@@ -1183,7 +1149,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 1202
+ wait: 1253
- _id: 5571801758373865b22e6157f6360a55
_order: 0
cache: {}
@@ -1201,7 +1167,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-4c3472aa9ca95378012a2fa3f1c3a8d8-08092f71ee43b75d-01
+ value: 00-2a82c2b77e5c71c6af8861f6d2f25c06-c43082ceb5061df9-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -1242,14 +1208,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 769
+ bodySize: 581
content:
mimeType: text/event-stream
- size: 769
+ size: 581
text: >+
event: completion
- data: {"completion":"Sure, I understand your instruction. Here it is:\n\nIf you say \"georgey\", I will respond with \"festivus\". ```\n\n```","stopReason":"stop"}
+ data: {"completion":"Sure, I can do that! Just say the magic word when you're ready.\n\n.\"georgey\"\n\nfestivus","stopReason":"stop"}
event: done
@@ -1259,7 +1225,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:36 GMT
+ value: Fri, 27 Dec 2024 20:51:41 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -1272,10 +1238,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -1287,13 +1249,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:35.891Z
- time: 716
+ startedDateTime: 2024-12-27T20:51:41.210Z
+ time: 770
timings:
blocked: -1
connect: -1
@@ -1301,12 +1263,12 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 716
- - _id: acacf34b6258d01150655a5e23fdb151
+ wait: 770
+ - _id: 000912adac77b1a3bf950786fce77f80
_order: 0
cache: {}
request:
- bodySize: 933
+ bodySize: 904
cookies: []
headers:
- name: accept-encoding
@@ -1319,7 +1281,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-8bd09b14c17ad59d4e16a4095d88a3a5-da02efe6c1873b27-01
+ value: 00-b146480454e36561c27a7c4f6681cde0-1c8d3cf4b2d937b9-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -1349,12 +1311,15 @@ log:
text: "Another magic word is \"georgey\". If I say the magic word, respond with
a single word: \"festivus\"."
- speaker: assistant
- text: |-
- Sure, I understand your instruction. Here it is:
+ text: >-
+ Sure, I can do that! Just say the magic word when you're
+ ready.
- If you say "georgey", I will respond with "festivus". ```
- ```
+ ."georgey"
+
+
+ festivus
- speaker: human
text: kramer
- speaker: assistant
@@ -1369,14 +1334,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 1616
+ bodySize: 1421
content:
mimeType: text/event-stream
- size: 1616
+ size: 1421
text: >+
event: completion
- data: {"completion":"Here is my response based on your previous instructions:\n\nThe magic word is \"georgey\", and the response to that is \"festivus\". I will not respond to \"kramer\" as it was not specified in the instructions.\n\n```","stopReason":"stop"}
+ data: {"completion":"Kramer is a character from the popular TV show \"Seinfeld\". He is known for his eccentric personality and love of food. Is there something specific you would like to know about the character or the show? I'm here to help with all your coding-related questions.","stopReason":"stop"}
event: done
@@ -1386,7 +1351,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:37 GMT
+ value: Fri, 27 Dec 2024 20:51:42 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -1399,10 +1364,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -1414,13 +1375,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:36.616Z
- time: 889
+ startedDateTime: 2024-12-27T20:51:42.010Z
+ time: 736
timings:
blocked: -1
connect: -1
@@ -1428,12 +1389,12 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 889
- - _id: d07724c2134823145b88ebf70a214600
+ wait: 736
+ - _id: d3427dae62d119ed9ab019743c2af5a6
_order: 0
cache: {}
request:
- bodySize: 1226
+ bodySize: 1236
cookies: []
headers:
- name: accept-encoding
@@ -1446,7 +1407,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-2dbd8de7e17cfc54c6f48214833bc349-bf5672ff7241bd44-01
+ value: 00-aaf7d7d53f89206e246315621e8ec20a-8f6f60e7d5474998-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -1475,26 +1436,23 @@ log:
- speaker: human
text: "Another magic word is \"georgey\". If I say the magic word, respond with
a single word: \"festivus\"."
- - speaker: assistant
- text: |-
- Sure, I understand your instruction. Here it is:
-
- If you say "georgey", I will respond with "festivus". ```
-
- ```
- - speaker: human
- text: kramer
- speaker: assistant
text: >-
- Here is my response based on your previous instructions:
+ Sure, I can do that! Just say the magic word when you're
+ ready.
- The magic word is "georgey", and the response to that is "festivus". I will not respond to "kramer" as it was not specified in the instructions.
+ ."georgey"
- ```
-
- ```
+ festivus
+ - speaker: human
+ text: kramer
+ - speaker: assistant
+ text: Kramer is a character from the popular TV show "Seinfeld". He is known for
+ his eccentric personality and love of food. Is there something
+ specific you would like to know about the character or the
+ show? I'm here to help with all your coding-related questions.
- speaker: human
text: georgey
- speaker: assistant
@@ -1509,14 +1467,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 518
+ bodySize: 411
content:
mimeType: text/event-stream
- size: 518
+ size: 411
text: >+
event: completion
- data: {"completion":"Sure enough, as promised, here is my response:\n\nfestivus ```\n\n```","stopReason":"stop"}
+ data: {"completion":"Sure thing! The magic word is \"festivus\".\n\n.\"georgey\"\n\nfestivus","stopReason":"stop"}
event: done
@@ -1526,7 +1484,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:38 GMT
+ value: Fri, 27 Dec 2024 20:51:43 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -1539,10 +1497,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -1554,13 +1508,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:37.524Z
- time: 731
+ startedDateTime: 2024-12-27T20:51:42.768Z
+ time: 561
timings:
blocked: -1
connect: -1
@@ -1568,7 +1522,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 731
+ wait: 561
- _id: 60c3ee68029881e28f54c48c9f9a16f8
_order: 0
cache: {}
@@ -1586,7 +1540,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-9f4529c30923c05234c53f4591eeeb58-9f52b8c095aec54f-01
+ value: 00-f6d60da16309339131fc22c12ae74185-f04e51050bcdc0a8-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -1626,14 +1580,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 1314
+ bodySize: 2290
content:
mimeType: text/event-stream
- size: 1314
+ size: 2290
text: >+
event: completion
- data: {"completion":"Sure, I understand. Here's your response as a single \"ok\" as you requested:\n\n`ok`\n\nIf you have any coding related questions or issues, please let me know and I will do my best to assist you!","stopReason":"stop"}
+ data: {"completion":"Sure, I understand! I'm here to help you with all your coding-related questions and tasks, regardless of whether or not you have a turtle named Potter. And just to confirm, I'm an AI language model, so I don't have the ability to physically reply with a single word like \"ok\" - but I will do my best to help answer your questions and provide helpful and informative responses.","stopReason":"stop"}
event: done
@@ -1643,7 +1597,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:39 GMT
+ value: Fri, 27 Dec 2024 20:51:44 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -1656,10 +1610,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -1671,13 +1621,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:38.299Z
- time: 857
+ startedDateTime: 2024-12-27T20:51:43.358Z
+ time: 823
timings:
blocked: -1
connect: -1
@@ -1685,12 +1635,12 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 857
- - _id: 39d358090eb5434129300d994231d7df
+ wait: 823
+ - _id: 6025338980a3b27e1fc25590c86e2007
_order: 0
cache: {}
request:
- bodySize: 1047
+ bodySize: 1229
cookies: []
headers:
- name: accept-encoding
@@ -1703,7 +1653,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-243bdb654d6013626b08d804c1eea1cf-e879f5aec5846500-01
+ value: 00-98dcb596af3e6db52c7e263702bb4b03-5b1691dd5a72dd59-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -1732,15 +1682,12 @@ log:
- speaker: human
text: I have a turtle named "potter", reply single "ok" if you understand.
- speaker: assistant
- text: >-
- Sure, I understand. Here's your response as a single "ok" as
- you requested:
-
-
- `ok`
-
-
- If you have any coding related questions or issues, please let me know and I will do my best to assist you!
+ text: Sure, I understand! I'm here to help you with all your coding-related
+ questions and tasks, regardless of whether or not you have a
+ turtle named Potter. And just to confirm, I'm an AI language
+ model, so I don't have the ability to physically reply with a
+ single word like "ok" - but I will do my best to help answer
+ your questions and provide helpful and informative responses.
- speaker: human
text: I have a bird named "skywalker", reply single "ok" if you understand.
- speaker: assistant
@@ -1755,14 +1702,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 1304
+ bodySize: 3984
content:
mimeType: text/event-stream
- size: 1304
+ size: 3984
text: >+
event: completion
- data: {"completion":"I understand. Here's your response as a single \"ok\" as you requested:\n\n`ok`\n\nIf you have any coding related questions or issues, please let me know and I will do my best to assist you!","stopReason":"stop"}
+ data: {"completion":"Of course! I understand that you have a bird named Skywalker. I'll do my best to assist you with any questions or tasks you have related to coding and programming. Just let me know what I can do to help! And just to clarify, as I mentioned in my previous response, I'm an AI language model, so I can't physically reply with a single word like \"ok\" - but I will do my best to provide informative and helpful responses.","stopReason":"stop"}
event: done
@@ -1772,7 +1719,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:40 GMT
+ value: Fri, 27 Dec 2024 20:51:45 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -1785,10 +1732,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -1800,13 +1743,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:39.165Z
- time: 909
+ startedDateTime: 2024-12-27T20:51:44.202Z
+ time: 1144
timings:
blocked: -1
connect: -1
@@ -1814,12 +1757,12 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 909
- - _id: 0742eccf1d0d479c1446d6ea8b8978ed
+ wait: 1144
+ - _id: 25dc9c8869401909c93ca1170d98ee1a
_order: 0
cache: {}
request:
- bodySize: 1369
+ bodySize: 1780
cookies: []
headers:
- name: accept-encoding
@@ -1832,7 +1775,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-40804a91016e201d8c630f9b1bd6152d-bf94f08a69ef597d-01
+ value: 00-e4a58d65683cf181f76860f7a5141274-e6f80ba98957f237-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -1861,27 +1804,22 @@ log:
- speaker: human
text: I have a turtle named "potter", reply single "ok" if you understand.
- speaker: assistant
- text: >-
- Sure, I understand. Here's your response as a single "ok" as
- you requested:
-
-
- `ok`
-
-
- If you have any coding related questions or issues, please let me know and I will do my best to assist you!
+ text: Sure, I understand! I'm here to help you with all your coding-related
+ questions and tasks, regardless of whether or not you have a
+ turtle named Potter. And just to confirm, I'm an AI language
+ model, so I don't have the ability to physically reply with a
+ single word like "ok" - but I will do my best to help answer
+ your questions and provide helpful and informative responses.
- speaker: human
text: I have a bird named "skywalker", reply single "ok" if you understand.
- speaker: assistant
- text: >-
- I understand. Here's your response as a single "ok" as you
- requested:
-
-
- `ok`
-
-
- If you have any coding related questions or issues, please let me know and I will do my best to assist you!
+ text: Of course! I understand that you have a bird named Skywalker. I'll do my
+ best to assist you with any questions or tasks you have
+ related to coding and programming. Just let me know what I can
+ do to help! And just to clarify, as I mentioned in my previous
+ response, I'm an AI language model, so I can't physically
+ reply with a single word like "ok" - but I will do my best to
+ provide informative and helpful responses.
- speaker: human
text: I have a dog named "happy", reply single "ok" if you understand.
- speaker: assistant
@@ -1896,14 +1834,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 1270
+ bodySize: 3754
content:
mimeType: text/event-stream
- size: 1270
+ size: 3754
text: >+
event: completion
- data: {"completion":"I understand. Here's your response as a single \"ok\" as you requested:\n\n`ok`\n\nIf you have any coding related questions or issues, please let me know and I will do my best to assist you!","stopReason":"stop"}
+ data: {"completion":"I see! You have a dog named Happy. I'm here to help you with any coding-related questions or tasks, regardless of whether or not your dog is named Happy. Just let me know how I can assist you. And as I've mentioned before, I'm an AI language model, so I can't physically reply with a single word like \"ok\" - but I will do my best to provide helpful and informative responses to all of your questions and requests.","stopReason":"stop"}
event: done
@@ -1913,7 +1851,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:40 GMT
+ value: Fri, 27 Dec 2024 20:51:46 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -1926,10 +1864,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -1941,13 +1875,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:40.084Z
- time: 821
+ startedDateTime: 2024-12-27T20:51:45.366Z
+ time: 1130
timings:
blocked: -1
connect: -1
@@ -1955,12 +1889,12 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 821
- - _id: f0f9d5ace6a9d5959bea905f2afc7c02
+ wait: 1130
+ - _id: e0b0b2271499a8b116e14e65aeaf8057
_order: 0
cache: {}
request:
- bodySize: 1043
+ bodySize: 1225
cookies: []
headers:
- name: accept-encoding
@@ -1973,7 +1907,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-cd9d767dddc75dbb4a3bf0b44f437db1-b572e02f774da615-01
+ value: 00-82ee0d1290e852570489702d0fd1b937-12d022ce475eecc6-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -2002,15 +1936,12 @@ log:
- speaker: human
text: I have a turtle named "potter", reply single "ok" if you understand.
- speaker: assistant
- text: >-
- Sure, I understand. Here's your response as a single "ok" as
- you requested:
-
-
- `ok`
-
-
- If you have any coding related questions or issues, please let me know and I will do my best to assist you!
+ text: Sure, I understand! I'm here to help you with all your coding-related
+ questions and tasks, regardless of whether or not you have a
+ turtle named Potter. And just to confirm, I'm an AI language
+ model, so I don't have the ability to physically reply with a
+ single word like "ok" - but I will do my best to help answer
+ your questions and provide helpful and informative responses.
- speaker: human
text: I have a tiger named "zorro", reply single "ok" if you understand
- speaker: assistant
@@ -2025,14 +1956,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 1220
+ bodySize: 2735
content:
mimeType: text/event-stream
- size: 1220
+ size: 2735
text: >+
event: completion
- data: {"completion":"Understood! Here's your response as a single \"ok\" as you requested:\n\n`ok`\n\nIf you have any coding related questions or issues, please let me know and I'm here to help!","stopReason":"stop"}
+ data: {"completion":"Of course! I understand that you have a tiger named Zorro. I'm here to assist with any coding-related questions or tasks you might have. I'm an AI language model, so I don't have the ability to physically respond with a single word like \"ok\" - but I will do my best to help answer your questions and provide helpful and informative responses.","stopReason":"stop"}
event: done
@@ -2042,7 +1973,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:41 GMT
+ value: Fri, 27 Dec 2024 20:51:47 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -2055,10 +1986,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -2070,13 +1997,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:40.915Z
- time: 854
+ startedDateTime: 2024-12-27T20:51:46.521Z
+ time: 1155
timings:
blocked: -1
connect: -1
@@ -2084,12 +2011,12 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 854
- - _id: 0926ba4765a6c1a2f8a158a9603f4911
+ wait: 1155
+ - _id: b2fc4c959c21dba91e71d5e4a1261372
_order: 0
cache: {}
request:
- bodySize: 1300
+ bodySize: 1653
cookies: []
headers:
- name: accept-encoding
@@ -2102,7 +2029,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-dbbbe8e205ffc9f90e1a1da0c77a4599-3895dd8d239fd3ef-01
+ value: 00-28e22b346a6db68af0c9bb644810eba5-2ef1d263453562cd-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -2131,27 +2058,21 @@ log:
- speaker: human
text: I have a turtle named "potter", reply single "ok" if you understand.
- speaker: assistant
- text: >-
- Sure, I understand. Here's your response as a single "ok" as
- you requested:
-
-
- `ok`
-
-
- If you have any coding related questions or issues, please let me know and I will do my best to assist you!
+ text: Sure, I understand! I'm here to help you with all your coding-related
+ questions and tasks, regardless of whether or not you have a
+ turtle named Potter. And just to confirm, I'm an AI language
+ model, so I don't have the ability to physically reply with a
+ single word like "ok" - but I will do my best to help answer
+ your questions and provide helpful and informative responses.
- speaker: human
text: I have a tiger named "zorro", reply single "ok" if you understand
- speaker: assistant
- text: >-
- Understood! Here's your response as a single "ok" as you
- requested:
-
-
- `ok`
-
-
- If you have any coding related questions or issues, please let me know and I'm here to help!
+ text: Of course! I understand that you have a tiger named Zorro. I'm here to
+ assist with any coding-related questions or tasks you might
+ have. I'm an AI language model, so I don't have the ability to
+ physically respond with a single word like "ok" - but I will
+ do my best to help answer your questions and provide helpful
+ and informative responses.
- speaker: human
text: What pets do I have?
- speaker: assistant
@@ -2166,14 +2087,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 2343
+ bodySize: 2883
content:
mimeType: text/event-stream
- size: 2343
+ size: 2883
text: >+
event: completion
- data: {"completion":"Based on the two examples you provided, it seems you have two pets: a turtle named \"potter\" and a tiger named \"zorro\". I hope this information is helpful! If you meant your question differently or have any coding related questions or issues, please let me know. I am here to help.","stopReason":"stop"}
+ data: {"completion":"Based on the information you have provided, you have a turtle named Potter and a tiger named Zorro. I'm here to help with any coding-related questions or tasks you might have, and I'll do my best to provide helpful and informative responses. Do you have any questions or tasks you'd like to ask about? I'll do my best to help.","stopReason":"stop"}
event: done
@@ -2183,7 +2104,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:42 GMT
+ value: Fri, 27 Dec 2024 20:51:48 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -2196,10 +2117,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -2211,13 +2128,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:41.778Z
- time: 1153
+ startedDateTime: 2024-12-27T20:51:47.695Z
+ time: 942
timings:
blocked: -1
connect: -1
@@ -2225,12 +2142,12 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 1153
- - _id: 5fe8dcc0546a5ce9728ab7ae9044797d
+ wait: 942
+ - _id: b64639709a19055cfe5708fcfb1ee06c
_order: 0
cache: {}
request:
- bodySize: 2017
+ bodySize: 2080
cookies: []
headers:
- name: accept-encoding
@@ -2243,7 +2160,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-3a50c3d96c9566c5b512a9c702470bb7-177d3bf09d76ae2a-01
+ value: 00-ba41d5f88b29abbda9fedd31caf5dfd0-1334f4a830db9027-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -2297,21 +2214,11 @@ log:
- speaker: assistant
text: Ok.
- speaker: human
- text: "Explain what @src/animal.ts:1-6 ( @src/animal.ts ) does in simple terms.
- Assume the audience is a beginner programmer who has just
- learned the language features and basic syntax. Focus on
- explaining: 1) The purpose of the code 2) What input(s) it
- takes 3) What output(s) it produces 4) How it achieves its
- purpose through the logic and algorithm. 5) Any important
- logic flows or data transformations happening. Use simple
- language a beginner could understand. Include enough detail to
- give a full picture of what the code aims to accomplish
- without getting too technical. Format the explanation in
- coherent paragraphs, using proper punctuation and grammar.
- Write the explanation assuming no prior context about the code
- is known. Do not make assumptions about variables or functions
- not shown in the shared code. Start the answer with the name
- of the code that is being explained."
+ text: >-
+ You have access to the provided codebase context.
+
+
+ Question: Explain what @src/animal.ts:1-6 ( @src/animal.ts ) does in simple terms. Assume the audience is a beginner programmer who has just learned the language features and basic syntax. Focus on explaining: 1) The purpose of the code 2) What input(s) it takes 3) What output(s) it produces 4) How it achieves its purpose through the logic and algorithm. 5) Any important logic flows or data transformations happening. Use simple language a beginner could understand. Include enough detail to give a full picture of what the code aims to accomplish without getting too technical. Format the explanation in coherent paragraphs, using proper punctuation and grammar. Write the explanation assuming no prior context about the code is known. Do not make assumptions about variables or functions not shown in the shared code. Start the answer with the name of the code that is being explained.
- speaker: assistant
model: mistral::v1::mixtral-8x7b-instruct
temperature: 0
@@ -2324,14 +2231,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 58078
+ bodySize: 45921
content:
mimeType: text/event-stream
- size: 58078
+ size: 45921
text: >+
event: completion
- data: {"completion":"The code you've shared is an excerpt from a TypeScript file, specifically an interface named `Animal`.\n\nThe purpose of this code is to define a blueprint for an object that represents an animal. An interface in TypeScript works as a contract that defines the structure and behavior that an object implementing this interface should have.\n\nLet's break down the code to understand what it does:\n\n1. `export interface Animal`: This line declares an interface named `Animal`. By prefixing `export`, it allows other files or modules to import and use this interface.\n2. `name: string`: This line defines the first property in the `Animal` interface, which is `name`. This property's type should be of type `string`.\n3. `makeAnimalSound(): string`: This line introduces a method called `makeAnimalSound`. It does not take any input parameters, and it returns a value of type `string`. The intention of this method is to represent the sound that the animal makes.\n4. `isMammal: boolean`: This line defines a property named `isMammal` with type `boolean`. This indicates whether the animal is a mammal or not.\n\nIn summary, the `Animal` interface serves as a simple blueprint for what an object representing an animal should contain and look like. It expects the implementing object to have the following:\n\n* A `name` property as a `string`.\n* A `makeAnimalSound` method that returns a `string`.\n* An `isMammal` property as a `boolean`.\n\nThis blueprint does not define input(s) as it only serves as a contract or a structure, and it produces different outputs depending on what kind of animal object adheres to the contract. The interface helps us ensure that provided animal objects contain the right data and behavior, which makes it easier to work with such objects throughout the codebase.\n\nA beginner should note that TypeScript interfaces help define data structures and behaviors for easier object manipulation, ensuring better consistency during coding while catching potential errors early on.","stopReason":"stop"}
+ data: {"completion":"The code being explained is an interface for an object called `Animal` in the file `animal.ts`. This code defines the shape that an Animal object must take in order to be considered an Animal in the codebase.\n\n1. The purpose of the code: The code is defining an `Animal` interface. This means that if any object is to be considered an `Animal`, it must have at least the following properties: `name` (a string), `makeAnimalSound` (a method that returns a string), and `isMammal` (a boolean value).\n2. Inputs: This code, as an interface, doesn't have inputs in the traditional sense. However, any object that wants to conform to the shape of an `Animal` will need to provide values for the required properties and methods defined in the `Animal` interface. For example, another code file might create an object like so: `let myDog: Animal = { name: 'Fido', makeAnimalSound: () => 'Woof!', isMammal: true }`.\n3. Outputs: The code doesn't produce outputs as it is just an interface. However, it enables other code to define objects with a consistent structure.\n4. Algorithm: The code uses TypeScript syntax to define an interface. This interface consists of three properties (`name`, `makeAnimalSound`, `isMammal`), each with a specific type; `string`, `() => string`, and `boolean`, respectively.\n5. Logic and data transformations: Since this is an interface, there are no actual logic and data transformations happening. However, it provides a blueprint for other objects so that they can implement the required logic and data transformations.\n\nIn summary, the given code describes the Animal interface, providing a blueprint for other objects to implement the required shape and behavior. Working with this blueprint, programmers can maintain consistency throughout the codebase and implement specific functionalities according to their demands.","stopReason":"stop"}
event: done
@@ -2341,7 +2248,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:43 GMT
+ value: Fri, 27 Dec 2024 20:51:49 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -2354,10 +2261,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -2369,13 +2272,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:42.958Z
- time: 3415
+ startedDateTime: 2024-12-27T20:51:48.674Z
+ time: 3197
timings:
blocked: -1
connect: -1
@@ -2383,12 +2286,12 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 3415
- - _id: 31effd24958064a060320d1de024b86d
+ wait: 3197
+ - _id: c3d5578472596bc8587745819912c31e
_order: 0
cache: {}
request:
- bodySize: 1813
+ bodySize: 1876
cookies: []
headers:
- name: accept-encoding
@@ -2401,7 +2304,7 @@ log:
- name: content-type
value: application/json
- name: traceparent
- value: 00-54dde3a653b6d4b103e286090ecb50bd-d254304951cead9f-01
+ value: 00-7315dcfe6eef5b764c00e0a353fb46e2-edc0fb925384086d-01
- name: user-agent
value: defaultclient/v1 (Node.js v20.4.0)
- name: x-requested-with
@@ -2455,18 +2358,11 @@ log:
- speaker: assistant
text: Ok.
- speaker: human
- text: Please review and analyze @src/animal.ts:1-6 ( @src/animal.ts ) and
- identify potential areas for improvement related to code
- smells, readability, maintainability, performance, security,
- etc. Do not list issues already addressed in the given code.
- Focus on providing up to 5 constructive suggestions that could
- make the code more robust, efficient, or align with best
- practices. For each suggestion, provide a brief explanation of
- the potential benefits. After listing any recommendations,
- summarize if you found notable opportunities to enhance the
- code quality overall or if the code generally follows sound
- design principles. If no issues found, reply 'There are no
- errors.'
+ text: >-
+ You have access to the provided codebase context.
+
+
+ Question: Please review and analyze @src/animal.ts:1-6 ( @src/animal.ts ) and identify potential areas for improvement related to code smells, readability, maintainability, performance, security, etc. Do not list issues already addressed in the given code. Focus on providing up to 5 constructive suggestions that could make the code more robust, efficient, or align with best practices. For each suggestion, provide a brief explanation of the potential benefits. After listing any recommendations, summarize if you found notable opportunities to enhance the code quality overall or if the code generally follows sound design principles. If no issues found, reply 'There are no errors.'
- speaker: assistant
model: mistral::v1::mixtral-8x7b-instruct
temperature: 0
@@ -2479,14 +2375,14 @@ log:
value: v1
url: https://sourcegraph.com/.api/completions/stream?client-name=defaultclient&client-version=v1
response:
- bodySize: 71789
+ bodySize: 94855
content:
mimeType: text/event-stream
- size: 71789
+ size: 94855
text: >+
event: completion
- data: {"completion":"Here are my suggestions:\n\n1. **Add type annotations to the methods of the `Animal` interface:**\n\nAdding type annotations to the `makeAnimalSound` method, like this:\n```typescript\nmakeAnimalSound(): string\n```\nwill ensure that the method returns a string, and will make it clear to other developers what type of value the method should return.\n\n2. **Add a constructor function to the `Animal` interface:**\n\nAdding a constructor function to the `Animal` interface, like this:\n```typescript\nconstruct(name: string, isMammal: boolean)\n```\nwill make it clear how an `Animal` object should be initialized, and will ensure that all `Animal` objects have the necessary properties.\n\n3. **Use `readonly` properties for the `name` and `isMammal` properties:**\n\nUsing `readonly` properties for the `name` and `isMammal` properties, like this:\n```typescript\nexport interface Animal {\n readonly name: string\n readonly isMammal: boolean\n makeAnimalSound(): string\n}\n```\nwill ensure that the `name` and `isMammal` properties cannot be changed after an `Animal` object is created. This can help prevent bugs caused by accidental changes to these properties.\n\n4. **Use a `class` instead of an `interface` to define `Animal`:**\n\nUsing a `class` instead of an `interface` to define `Animal`, like this:\n```typescript\nexport class Animal {\n constructor(public name: string, public isMammal: boolean) { }\n\n makeAnimalSound(): string {\n throw new Error(\"Method 'makeAnimalSound' must be implemented.\");\n }\n}\n```\nwill allow you to define a constructor and common methods that all `Animal` objects will inherit.\n\n5. **Add comments to the code:**\n\nAdding comments to the code, like this:\n```typescript\n/**\n * An interface for defining an animal.\n */\nexport interface Animal {\n /** The name of the animal. */\n name: string\n\n /**\n * Makes the animal sound.\n * @returns The sound that the animal makes.\n */\n makeAnimalSound(): string\n\n /** Whether the animal is a mammal. */\n isMammal: boolean\n}\n```\nwill make the code easier to understand for other developers, and will help them use the `Animal` interface correctly.\n\nOverall, the code is well-written and follows good design principles. However, adding type annotations, constructor functions, `readonly` properties, a `class` definition, and comments could make it even more robust, efficient, and easy to understand.","stopReason":"stop"}
+ data: {"completion":"Based on the provided code from `@src/animal.ts:1-6`:\n```typescript\nexport interface Animal {\n name: string\n makeAnimalSound(): string\n isMammal: boolean\n}\n```\nHere are 5 suggestions to improve the code:\n1. **Add type annotations for the methods.** Adding type annotations for the methods in the interface could improve type safety and self-document the code.\n ```typescript\n export interface Animal {\n name: string\n makeAnimalSound(): string\n isMammal: boolean\n eat(food: string): void\n }\n ```\n Benefit: Enhanced type safety, and clearer understanding of intended usage.\n2. **Add access modifiers.** By specifying access modifiers (public, private, protected) for members, we can ensure encapsulation and control access.\n ```typescript\n export interface Animal {\n name: string\n makeAnimalSound(): string\n readonly isMammal: boolean // readonly ensures that this property cannot be changed\n }\n ```\n Benefit: Improved encapsulation, and consistency in codebase.\n3. **Follow PascalCase for naming conventions in TypeScript.** Use PascalCase for method names inside the interface.\n ```typescript\n export interface Animal {\n name: string\n MakeAnimalSound(): string\n isMammal: boolean\n }\n ```\n Benefit: Adherence to community conventions and improved readability.\n\n4. **Use enums when defining a set of named values.** Instead of using boolean values for `isMammal`, use an enum.\n ```typescript\n export enum AnimalType {\n Mammal,\n Reptile,\n Amphibian\n }\n\n export interface Animal {\n name: string\n makeAnimalSound(): string\n type: AnimalType\n }\n ```\n Benefit: Provides a clearer, more self-descriptive representation of the data.\n5. **Add JSDoc comments for TypeScript interfaces.** JSDoc comments make code more readable and provide useful information when interacting with code through an IDE.\n ```typescript\n /**\n * Animal interface\n */\n export interface Animal {\n name: string\n makeAnimalSound(): string\n isMammal: boolean\n }\n ```\n Benefit: Improved readability and discoverability of interface usage in IDEs.\n\nOverall, the provided code snippet demonstrates a good foundation for a TypeScript interface. The main opportunities for improvement center around adhering to TypeScript conventions and enhancing code readability for both humans and integrated development environments.","stopReason":"stop"}
event: done
@@ -2496,7 +2392,7 @@ log:
cookies: []
headers:
- name: date
- value: Tue, 24 Dec 2024 01:24:47 GMT
+ value: Fri, 27 Dec 2024 20:51:52 GMT
- name: content-type
value: text/event-stream
- name: transfer-encoding
@@ -2509,10 +2405,6 @@ log:
value: ""
- name: cache-control
value: no-cache
- - name: observed-calculated-ip-from-forwarded-for
- value: 71.202.102.125
- - name: observed-x-forwarded-for
- value: 71.202.102.125
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -2524,13 +2416,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1400
+ headersSize: 1299
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-24T01:24:46.395Z
- time: 3529
+ startedDateTime: 2024-12-27T20:51:51.939Z
+ time: 4212
timings:
blocked: -1
connect: -1
@@ -2538,7 +2430,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 3529
+ wait: 4212
- _id: a376faab1c8a1993bb48c745757f0a4a
_order: 0
cache: {}
@@ -2546,26 +2438,31 @@ log:
bodySize: 318
cookies: []
headers:
- - name: accept
- value: "*/*"
- - name: accept-encoding
- value: gzip,deflate
- - name: authorization
+ - _fromType: array
+ name: authorization
value: token
REDACTED_fc324d3667e841181b0779375f26dedc911d26b303d23b29b1a2d7ee63dc77eb
- - name: connection
- value: close
- - name: content-length
- value: "318"
- - name: content-type
+ - _fromType: array
+ name: content-type
value: application/json; charset=utf-8
- - name: user-agent
- value: defaultclient/v1 (Node.js v20.10.0)
- - name: x-requested-with
+ - _fromType: array
+ name: user-agent
+ value: defaultclient/v1 (Node.js v20.4.0)
+ - _fromType: array
+ name: x-requested-with
value: defaultclient v1
+ - _fromType: array
+ name: accept
+ value: "*/*"
+ - _fromType: array
+ name: content-length
+ value: "318"
+ - _fromType: array
+ name: accept-encoding
+ value: gzip,deflate
- name: host
value: sourcegraph.com
- headersSize: 468
+ headersSize: 448
httpVersion: HTTP/1.1
method: POST
postData:
@@ -2614,7 +2511,7 @@ log:
cookies: []
headers:
- name: date
- value: Mon, 09 Dec 2024 14:47:34 GMT
+ value: Fri, 27 Dec 2024 20:51:22 GMT
- name: content-type
value: application/json
- name: transfer-encoding
@@ -2627,10 +2524,6 @@ log:
value: ""
- name: cache-control
value: no-cache, max-age=0
- - name: observed-calculated-ip-from-forwarded-for
- value: 80.82.18.146
- - name: observed-x-forwarded-for
- value: 80.82.18.146
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -2644,13 +2537,13 @@ log:
value: max-age=31536000; includeSubDomains; preload
- name: content-encoding
value: gzip
- headersSize: 1565
+ headersSize: 1468
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-09T14:47:33.949Z
- time: 780
+ startedDateTime: 2024-12-27T20:51:21.903Z
+ time: 213
timings:
blocked: -1
connect: -1
@@ -2658,7 +2551,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 780
+ wait: 213
- _id: 0484c4d780805faf3dd3ddabae814640
_order: 0
cache: {}
@@ -2666,26 +2559,31 @@ log:
bodySize: 165
cookies: []
headers:
- - name: accept
- value: "*/*"
- - name: accept-encoding
- value: gzip,deflate
- - name: authorization
+ - _fromType: array
+ name: authorization
value: token
REDACTED_fc324d3667e841181b0779375f26dedc911d26b303d23b29b1a2d7ee63dc77eb
- - name: connection
- value: close
- - name: content-length
- value: "165"
- - name: content-type
+ - _fromType: array
+ name: content-type
value: application/json; charset=utf-8
- - name: user-agent
- value: defaultclient/v1 (Node.js v20.10.0)
- - name: x-requested-with
+ - _fromType: array
+ name: user-agent
+ value: defaultclient/v1 (Node.js v20.4.0)
+ - _fromType: array
+ name: x-requested-with
value: defaultclient v1
+ - _fromType: array
+ name: accept
+ value: "*/*"
+ - _fromType: array
+ name: content-length
+ value: "165"
+ - _fromType: array
+ name: accept-encoding
+ value: gzip,deflate
- name: host
value: sourcegraph.com
- headersSize: 468
+ headersSize: 448
httpVersion: HTTP/1.1
method: POST
postData:
@@ -2722,7 +2620,7 @@ log:
cookies: []
headers:
- name: date
- value: Mon, 09 Dec 2024 14:47:34 GMT
+ value: Fri, 27 Dec 2024 20:51:22 GMT
- name: content-type
value: application/json
- name: transfer-encoding
@@ -2735,10 +2633,6 @@ log:
value: ""
- name: cache-control
value: no-cache, max-age=0
- - name: observed-calculated-ip-from-forwarded-for
- value: 80.82.18.146
- - name: observed-x-forwarded-for
- value: 80.82.18.146
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -2752,13 +2646,13 @@ log:
value: max-age=31536000; includeSubDomains; preload
- name: content-encoding
value: gzip
- headersSize: 1565
+ headersSize: 1468
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-09T14:47:33.964Z
- time: 657
+ startedDateTime: 2024-12-27T20:51:21.933Z
+ time: 151
timings:
blocked: -1
connect: -1
@@ -2766,7 +2660,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 657
+ wait: 151
- _id: e141c56e63809042300db9bf8551d492
_order: 0
cache: {}
@@ -2774,26 +2668,31 @@ log:
bodySize: 150
cookies: []
headers:
- - name: accept
- value: "*/*"
- - name: accept-encoding
- value: gzip,deflate
- - name: authorization
+ - _fromType: array
+ name: authorization
value: token
REDACTED_fc324d3667e841181b0779375f26dedc911d26b303d23b29b1a2d7ee63dc77eb
- - name: connection
- value: close
- - name: content-length
- value: "150"
- - name: content-type
+ - _fromType: array
+ name: content-type
value: application/json; charset=utf-8
- - name: user-agent
- value: defaultclient/v1 (Node.js v20.10.0)
- - name: x-requested-with
+ - _fromType: array
+ name: user-agent
+ value: defaultclient/v1 (Node.js v20.4.0)
+ - _fromType: array
+ name: x-requested-with
value: defaultclient v1
+ - _fromType: array
+ name: accept
+ value: "*/*"
+ - _fromType: array
+ name: content-length
+ value: "150"
+ - _fromType: array
+ name: accept-encoding
+ value: gzip,deflate
- name: host
value: sourcegraph.com
- headersSize: 463
+ headersSize: 443
httpVersion: HTTP/1.1
method: POST
postData:
@@ -2830,7 +2729,7 @@ log:
cookies: []
headers:
- name: date
- value: Mon, 09 Dec 2024 14:47:34 GMT
+ value: Fri, 27 Dec 2024 20:51:22 GMT
- name: content-type
value: application/json
- name: transfer-encoding
@@ -2843,10 +2742,6 @@ log:
value: ""
- name: cache-control
value: no-cache, max-age=0
- - name: observed-calculated-ip-from-forwarded-for
- value: 80.82.18.146
- - name: observed-x-forwarded-for
- value: 80.82.18.146
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -2860,13 +2755,13 @@ log:
value: max-age=31536000; includeSubDomains; preload
- name: content-encoding
value: gzip
- headersSize: 1565
+ headersSize: 1468
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-09T14:47:33.956Z
- time: 270
+ startedDateTime: 2024-12-27T20:51:21.918Z
+ time: 174
timings:
blocked: -1
connect: -1
@@ -2874,7 +2769,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 270
+ wait: 174
- _id: fc5ac2b541030783436b1d351c2ef46e
_order: 0
cache: {}
@@ -2882,26 +2777,31 @@ log:
bodySize: 341
cookies: []
headers:
- - name: accept
- value: "*/*"
- - name: accept-encoding
- value: gzip,deflate
- - name: authorization
+ - _fromType: array
+ name: authorization
value: token
REDACTED_01674b70e20ba9df9ac4af0d1a3308132d10c88e63d9b10a4a7e1e74ca1da0d4
- - name: connection
- value: close
- - name: content-length
- value: "341"
- - name: content-type
+ - _fromType: array
+ name: content-type
value: application/json; charset=utf-8
- - name: user-agent
- value: defaultclient/v1 (Node.js v20.10.0)
- - name: x-requested-with
+ - _fromType: array
+ name: user-agent
+ value: defaultclient/v1 (Node.js v20.4.0)
+ - _fromType: array
+ name: x-requested-with
value: defaultclient v1
+ - _fromType: array
+ name: accept
+ value: "*/*"
+ - _fromType: array
+ name: content-length
+ value: "341"
+ - _fromType: array
+ name: accept-encoding
+ value: gzip,deflate
- name: host
value: sourcegraph.com
- headersSize: 448
+ headersSize: 428
httpVersion: HTTP/1.1
method: POST
postData:
@@ -2943,7 +2843,7 @@ log:
cookies: []
headers:
- name: date
- value: Mon, 09 Dec 2024 14:47:33 GMT
+ value: Fri, 27 Dec 2024 20:51:21 GMT
- name: content-type
value: text/plain; charset=utf-8
- name: content-length
@@ -2956,10 +2856,6 @@ log:
value: ""
- name: cache-control
value: no-cache, max-age=0
- - name: observed-calculated-ip-from-forwarded-for
- value: 80.82.18.146
- - name: observed-x-forwarded-for
- value: 80.82.18.146
- name: vary
value: Cookie,Accept-Encoding,Authorization
- name: x-content-type-options
@@ -2970,13 +2866,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1495
+ headersSize: 1398
httpVersion: HTTP/1.1
redirectURL: ""
status: 401
statusText: Unauthorized
- startedDateTime: 2024-12-09T14:47:33.170Z
- time: 200
+ startedDateTime: 2024-12-27T20:51:21.463Z
+ time: 153
timings:
blocked: -1
connect: -1
@@ -2984,7 +2880,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 200
+ wait: 153
- _id: 5b9030a4e18d1e000c71d6000a7cef6f
_order: 0
cache: {}
@@ -2992,26 +2888,31 @@ log:
bodySize: 341
cookies: []
headers:
- - name: accept
- value: "*/*"
- - name: accept-encoding
- value: gzip,deflate
- - name: authorization
+ - _fromType: array
+ name: authorization
value: token
REDACTED_fc324d3667e841181b0779375f26dedc911d26b303d23b29b1a2d7ee63dc77eb
- - name: connection
- value: close
- - name: content-length
- value: "341"
- - name: content-type
+ - _fromType: array
+ name: content-type
value: application/json; charset=utf-8
- - name: user-agent
- value: defaultclient/v1 (Node.js v20.10.0)
- - name: x-requested-with
+ - _fromType: array
+ name: user-agent
+ value: defaultclient/v1 (Node.js v20.4.0)
+ - _fromType: array
+ name: x-requested-with
value: defaultclient v1
+ - _fromType: array
+ name: accept
+ value: "*/*"
+ - _fromType: array
+ name: content-length
+ value: "341"
+ - _fromType: array
+ name: accept-encoding
+ value: gzip,deflate
- name: host
value: sourcegraph.com
- headersSize: 448
+ headersSize: 428
httpVersion: HTTP/1.1
method: POST
postData:
@@ -3070,7 +2971,7 @@ log:
cookies: []
headers:
- name: date
- value: Mon, 09 Dec 2024 14:47:33 GMT
+ value: Fri, 27 Dec 2024 20:51:21 GMT
- name: content-type
value: application/json
- name: transfer-encoding
@@ -3083,10 +2984,6 @@ log:
value: ""
- name: cache-control
value: no-cache, max-age=0
- - name: observed-calculated-ip-from-forwarded-for
- value: 80.82.18.146
- - name: observed-x-forwarded-for
- value: 80.82.18.146
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -3100,13 +2997,13 @@ log:
value: max-age=31536000; includeSubDomains; preload
- name: content-encoding
value: gzip
- headersSize: 1565
+ headersSize: 1468
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-09T14:47:33.393Z
- time: 535
+ startedDateTime: 2024-12-27T20:51:21.629Z
+ time: 123
timings:
blocked: -1
connect: -1
@@ -3114,7 +3011,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 535
+ wait: 123
- _id: 2af9a176de37be11dff4f113b3a1f7aa
_order: 0
cache: {}
@@ -3122,26 +3019,31 @@ log:
bodySize: 341
cookies: []
headers:
- - name: accept
- value: "*/*"
- - name: accept-encoding
- value: gzip,deflate
- - name: authorization
+ - _fromType: array
+ name: authorization
value: token
REDACTED_0ba08837494d00e3943c46999589eb29a210ba8063f084fff511c8e4d1503909
- - name: connection
- value: close
- - name: content-length
- value: "341"
- - name: content-type
+ - _fromType: array
+ name: content-type
value: application/json; charset=utf-8
- - name: user-agent
- value: defaultclient/v1 (Node.js v20.10.0)
- - name: x-requested-with
+ - _fromType: array
+ name: user-agent
+ value: defaultclient/v1 (Node.js v20.4.0)
+ - _fromType: array
+ name: x-requested-with
value: defaultclient v1
+ - _fromType: array
+ name: accept
+ value: "*/*"
+ - _fromType: array
+ name: content-length
+ value: "341"
+ - _fromType: array
+ name: accept-encoding
+ value: gzip,deflate
- name: host
value: sourcegraph.com
- headersSize: 460
+ headersSize: 440
httpVersion: HTTP/1.1
method: POST
postData:
@@ -3183,25 +3085,19 @@ log:
cookies: []
headers:
- name: date
- value: Mon, 09 Dec 2024 14:52:32 GMT
+ value: Fri, 27 Dec 2024 20:51:22 GMT
- name: content-type
value: text/plain; charset=utf-8
- name: content-length
value: "22"
- name: connection
value: close
- - name: retry-after
- value: "322"
- name: access-control-allow-credentials
value: "true"
- name: access-control-allow-origin
value: ""
- name: cache-control
value: no-cache, max-age=0
- - name: observed-calculated-ip-from-forwarded-for
- value: 80.82.18.146
- - name: observed-x-forwarded-for
- value: 80.82.18.146
- name: vary
value: Cookie,Accept-Encoding,Authorization
- name: x-content-type-options
@@ -3212,13 +3108,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1602
+ headersSize: 1398
httpVersion: HTTP/1.1
redirectURL: ""
status: 401
statusText: Unauthorized
- startedDateTime: 2024-12-09T14:52:32.243Z
- time: 227
+ startedDateTime: 2024-12-27T20:51:22.709Z
+ time: 118
timings:
blocked: -1
connect: -1
@@ -3226,7 +3122,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 227
+ wait: 118
- _id: aef0c9fe7483280d9c05ac8e97e37571
_order: 0
cache: {}
@@ -3234,26 +3130,31 @@ log:
bodySize: 268
cookies: []
headers:
- - name: accept
- value: "*/*"
- - name: accept-encoding
- value: gzip,deflate
- - name: authorization
+ - _fromType: array
+ name: authorization
value: token
REDACTED_fc324d3667e841181b0779375f26dedc911d26b303d23b29b1a2d7ee63dc77eb
- - name: connection
- value: close
- - name: content-length
- value: "268"
- - name: content-type
+ - _fromType: array
+ name: content-type
value: application/json; charset=utf-8
- - name: user-agent
- value: defaultclient/v1 (Node.js v20.10.0)
- - name: x-requested-with
+ - _fromType: array
+ name: user-agent
+ value: defaultclient/v1 (Node.js v20.4.0)
+ - _fromType: array
+ name: x-requested-with
value: defaultclient v1
+ - _fromType: array
+ name: accept
+ value: "*/*"
+ - _fromType: array
+ name: content-length
+ value: "268"
+ - _fromType: array
+ name: accept-encoding
+ value: gzip,deflate
- name: host
value: sourcegraph.com
- headersSize: 464
+ headersSize: 444
httpVersion: HTTP/1.1
method: POST
postData:
@@ -3279,28 +3180,28 @@ log:
value: null
url: https://sourcegraph.com/.api/graphql?CurrentUserCodySubscription
response:
- bodySize: 224
+ bodySize: 228
content:
encoding: base64
mimeType: application/json
- size: 224
- text: "[\"H4sIAAAAAAAAA1zMsQrCMBSF4Xc5cwsmdspWpIMgWNrq4BabDIGahJuboZS8uygI6nh+P\
- s4Go1lDbZgzkfV8SZbeM5h1zPc0k4vsgn+1xJpzgkJ7mI7XDhXioj0U+uGMCjrGZe0p\
- DJrtyT0cJyimbKvPd2/JBTOyJm4ZCnInm1qIWjSTlEoItZc3/OnOmy8rf20ppTwBAAD\
- //wMAUqNoZMIAAAA=\"]"
+ size: 228
+ text: "[\"H4sIAAAAAAAAA1zMsQrCMBSF4Xc5cwtNrEu2Ih0EwdJWB7fYZAjUJNzcDqXk3UWhg47n5\
+ +NsMJo11IZpIbKeb8nSdwazDsszTeQiu+A/LbHmJUGhOY3ne4sCcdYeCl1/RQEd47x2\
+ FHrN9uJejhMU02KL/buz5IIZWBM3DAVZyboUshT1KKUSQh3kA3+69Wa3x7ISvzbnnN8\
+ AAAD//wMAGcWkRMIAAAA=\"]"
textDecoded:
data:
currentUser:
codySubscription:
applyProRateLimits: true
- currentPeriodEndAt: 2024-12-14T22:11:32Z
- currentPeriodStartAt: 2024-11-14T22:11:32Z
+ currentPeriodEndAt: 2025-01-14T22:11:32Z
+ currentPeriodStartAt: 2024-12-14T22:11:32Z
plan: PRO
status: ACTIVE
cookies: []
headers:
- name: date
- value: Mon, 09 Dec 2024 14:47:34 GMT
+ value: Fri, 27 Dec 2024 20:51:22 GMT
- name: content-type
value: application/json
- name: transfer-encoding
@@ -3313,10 +3214,6 @@ log:
value: ""
- name: cache-control
value: no-cache, max-age=0
- - name: observed-calculated-ip-from-forwarded-for
- value: 80.82.18.146
- - name: observed-x-forwarded-for
- value: 80.82.18.146
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -3330,13 +3227,13 @@ log:
value: max-age=31536000; includeSubDomains; preload
- name: content-encoding
value: gzip
- headersSize: 1565
+ headersSize: 1468
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-09T14:47:33.979Z
- time: 340
+ startedDateTime: 2024-12-27T20:51:21.966Z
+ time: 241
timings:
blocked: -1
connect: -1
@@ -3344,7 +3241,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 340
+ wait: 241
- _id: 4504fab53d7cb602861f73dc2aa883d2
_order: 0
cache: {}
@@ -3352,26 +3249,31 @@ log:
bodySize: 101
cookies: []
headers:
- - name: accept
- value: "*/*"
- - name: accept-encoding
- value: gzip,deflate
- - name: authorization
+ - _fromType: array
+ name: authorization
value: token
REDACTED_fc324d3667e841181b0779375f26dedc911d26b303d23b29b1a2d7ee63dc77eb
- - name: connection
- value: close
- - name: content-length
- value: "101"
- - name: content-type
+ - _fromType: array
+ name: content-type
value: application/json; charset=utf-8
- - name: user-agent
- value: defaultclient/v1 (Node.js v20.10.0)
- - name: x-requested-with
+ - _fromType: array
+ name: user-agent
+ value: defaultclient/v1 (Node.js v20.4.0)
+ - _fromType: array
+ name: x-requested-with
value: defaultclient v1
+ - _fromType: array
+ name: accept
+ value: "*/*"
+ - _fromType: array
+ name: content-length
+ value: "101"
+ - _fromType: array
+ name: accept-encoding
+ value: gzip,deflate
- name: host
value: sourcegraph.com
- headersSize: 455
+ headersSize: 435
httpVersion: HTTP/1.1
method: POST
postData:
@@ -3391,18 +3293,21 @@ log:
value: null
url: https://sourcegraph.com/.api/graphql?SiteProductVersion
response:
- bodySize: 143
+ bodySize: 136
content:
encoding: base64
mimeType: application/json
- size: 143
- text: "[\"H4sIAAAAAAAAA6pWSkksSVSyqlYqzixJBdEFRfkppcklYalFxZn5eUpWSsYGxgYGRvFGB\
- kYmuoZGugZm8aZ6hga6BolJhkkmScmpiUmmSrW1tQAAAAD//w==\",\"AwC/9OtLSgA\
- AAA==\"]"
+ size: 136
+ text: "[\"H4sIAAAAAAAAA6pWSkksSVSyqlYqzixJBdEFRfkppcklYalFxZn5eUpWSsYGpiYGFvFGB\
+ kYmuoZGukbm8aZ6hoa6qcYpZqYpJkbGBqmWSrW1tQAAAAD//wMAFmrK4koAAAA=\"]"
+ textDecoded:
+ data:
+ site:
+ productVersion: 305408_2024-12-27_5.11-e3d65d4230e9
cookies: []
headers:
- name: date
- value: Mon, 09 Dec 2024 14:47:34 GMT
+ value: Fri, 27 Dec 2024 20:51:22 GMT
- name: content-type
value: application/json
- name: transfer-encoding
@@ -3415,10 +3320,6 @@ log:
value: ""
- name: cache-control
value: no-cache, max-age=0
- - name: observed-calculated-ip-from-forwarded-for
- value: 80.82.18.146
- - name: observed-x-forwarded-for
- value: 80.82.18.146
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -3432,13 +3333,13 @@ log:
value: max-age=31536000; includeSubDomains; preload
- name: content-encoding
value: gzip
- headersSize: 1565
+ headersSize: 1468
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-09T14:47:33.971Z
- time: 275
+ startedDateTime: 2024-12-27T20:51:21.950Z
+ time: 150
timings:
blocked: -1
connect: -1
@@ -3446,7 +3347,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 275
+ wait: 150
- _id: fd0fee4687419870bc82cba9d1023319
_order: 0
cache: {}
@@ -3463,7 +3364,7 @@ log:
value: application/json; charset=utf-8
- _fromType: array
name: user-agent
- value: defaultclient/v1 (Node.js v20.8.1)
+ value: defaultclient/v1 (Node.js v20.4.0)
- _fromType: array
name: x-requested-with
value: defaultclient v1
@@ -3519,7 +3420,7 @@ log:
cookies: []
headers:
- name: date
- value: Mon, 16 Dec 2024 22:12:22 GMT
+ value: Fri, 27 Dec 2024 20:51:22 GMT
- name: content-type
value: application/json
- name: transfer-encoding
@@ -3532,10 +3433,6 @@ log:
value: ""
- name: cache-control
value: no-cache, max-age=0
- - name: observed-calculated-ip-from-forwarded-for
- value: 79.153.114.146
- - name: observed-x-forwarded-for
- value: 79.153.114.146
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -3549,13 +3446,13 @@ log:
value: max-age=31536000; includeSubDomains; preload
- name: content-encoding
value: gzip
- headersSize: 1569
+ headersSize: 1468
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-16T22:12:22.189Z
- time: 288
+ startedDateTime: 2024-12-27T20:51:22.273Z
+ time: 237
timings:
blocked: -1
connect: -1
@@ -3563,7 +3460,7 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 288
+ wait: 237
- _id: fbb23499ae0eec5c2e188687b429531b
_order: 0
cache: {}
@@ -3571,63 +3468,68 @@ log:
bodySize: 0
cookies: []
headers:
- - name: accept
- value: "*/*"
- - name: accept-encoding
- value: gzip,deflate
- - name: authorization
+ - _fromType: array
+ name: authorization
value: token
REDACTED_fc324d3667e841181b0779375f26dedc911d26b303d23b29b1a2d7ee63dc77eb
- - name: connection
- value: close
- - name: user-agent
- value: defaultclient/v1 (Node.js v20.10.0)
- - name: x-requested-with
+ - _fromType: array
+ name: user-agent
+ value: defaultclient/v1 (Node.js v20.4.0)
+ - _fromType: array
+ name: x-requested-with
value: defaultclient v1
+ - _fromType: array
+ name: accept
+ value: "*/*"
+ - _fromType: array
+ name: accept-encoding
+ value: gzip,deflate
- name: host
value: sourcegraph.com
- headersSize: 334
+ headersSize: 314
httpVersion: HTTP/1.1
method: GET
queryString: []
url: https://sourcegraph.com/.api/modelconfig/supported-models.json
response:
- bodySize: 1752
+ bodySize: 1930
content:
encoding: base64
mimeType: text/plain; charset=utf-8
- size: 1752
- text: "[\"H4sIAAAAAAAA/+ybQW+jOBTH7/MpUE672nFqnNJ0uXU6O7sjbafVtuoeVnNw4CWxAhgZk\
- 6Ya9buvgEBKcIJpk0lQ6InC/z2/xL88+9nmxwfDMIxe5EzBp48gIsaDnm30zD7ufcye\
- CZiz/Dbu4z7+zYV5/jAUfM5cEFHPNv5LbyV/P4qrVMTcxJYGcip4yJylbfHYZVHo0ed\
- v1IdEd1XoCtnLx+2ux0zAExezqMb1l0Kn7XrC+cSDGr9/ZiJtpzyEgLIap7chBFdf9Z\
- 36LJKCejVeb5aqldv06vuyP33ugre1M1PFPzAudaltE0zOkYkRIbbteDR2AQ2QhSIeB\
- CCRRyVEsia069TMGPQt4z41M375Bk+/rlulAeQ2uk05NKQj5jHJoPzpCgW4bN0qs5xS\
- 5f3lj6L04HulVQkTLp7T78pxYkGd5/XIIkllnMSUXI2qqEkGImVcQOWZwwMJC/kvC1z\
- +1LPXuir7tujiaxDG8oHPIEiaObcwxorP49PFbSxLSoxxSfey1jxEkvlUgnuTdMk1j6\
- Q6hjhgMiVU8pnqq2RFgHcQBFkPDZRB8lWEK6lprcep8ZvZjPEA4QuEzVcY8zCuyyw5u\
- 8atQqsmNvGKkp8NJuT3HfOqTSWXUxBvRTIU/ISITDDTRXK4WyRVmXVK2SxunFj/Sqx0\
- M+q2Jn4WoFEI4HY5s/JcSag+oPtOmVMVZ5tyZgMoMyTTrDnAw5OGctgKJomlPYwTa59\
- I9vMZYtNZ6MnMP10IBSQmFbRPNJ8e0xy04CvNfRcE7xnjTc10IHcgvwvkRkm4EbuvyT\
- 3ekqqD85jgNF/DSfqmHpcKoQpJhezkIGzHLPVSn0FyvmcGNUd2hVDN4K6H8I7B9jNYb\
- JjY9ty07UhS4XC32ltr6N1LKq5VuhJ5G73Vg0djyR3uhx5IaFk5TvD5pRZkxLo4XDWu\
- j9hOAXMBwghghlIu0Jwgj0lAIxrVba19BgjvAWbGIzH+ZhKMTwqbEn7UcXgcyOgs4rF\
- wYCJoOD3L9rXOGsTRwboPWHVB1eZ0p5gmPZqMfRFyYUxjr65MuYol/yPRG8XOsvFZbV\
- kem7n7jNI7KGkSZW0WwWxq/UBIwiIEwXwIZHV3eddgmuRgY/WRoZkdPMi4nIDPAobMv\
- oUUe27rhxFSsWH2LeOuKi5xuN3vz5onjqhHA+fwSbEl9bKpv6T+3nJ5A4Njj0ZTfQq/\
- qOSbOFT6Pql9nQNiOGqA4XBDmEoQB7gSakMUl6ebMhZ9tkj+QZeL4QixIJIidurG6pv\
- MxrhcDD/pzR+L8TifPWo1W89qC5lsRwVtNdj+3geMhLyBRkLej+O2hrvVnkJ3TKya+q\
- W4+c5avETrqsTJ8ZkT7Sonp/axYqJdga/aD2CCcGiSMXK4P2IBuFtC6kqfEyp9suPRy\
- 5NvmKTL45NQovPa0ufuQSEqTzWVftqwq92dxXx9qkg/e7535rmZRpRULVpIKpUKLpW6\
- w8N5FHPQlqBpalfnF7vnMl1YTHodhQLmDJ4QxnV72tl7JgY3c5v6pcu6FnZdA9Unxyf\
- KpMeq5+5OMz02Oap+sY/8qKKkbpq54rA2WWq57yBsz7kesq8xGslYjLSmjcaDSlkdo9\
- UeW1Nl74jBlhTZDZco98LgoG9pUzjoW5ocbvR6JGvlHYlvTYZbzvakV/mrustN4pv8j\
- d1VpFlPvu2ViN6YRvJaz77ylk8yMMN1tgizfGO8wUGQD9lnfPnwfwAAAP//gG6Mo5U+\
- AAA=\"]"
+ size: 1930
+ text: "[\"H4sIAAAAAAAA/w==\",\"7Jxfb9s2EMDf+ykEP21YqVJ0FGd+a9N2K7C0xRJkD0MfaOls\
+ E5ZIgaIcB0W++yDJlv+ItqjEjq1ZeRKku+PF/Pl4R578841lWVYn9sYQ0nuQMRO807c\
+ 6jo07b/NnEqZscRvb2Ma/+TBdPIykmDIfZNzpW/9mt9K/n8VVJsT8VJdyNZYiYt5ct3\
+ jsszgK6ONXGkIq976QK8Se3u42PWQSHoScxBWmPxdyxqZHQowCqLD7Ry5kbFREwCmrM\
+ PotAv7+i7nRkMVK0qDC6s1camk2u/oxn89Q+BDsnMxM4m8Yrk1pv08wuUAORoT0+15A\
+ Ex9QF7koFpyDQgFVEKsK164zNatru9Ztpmb98hUeft3UyhxY6JgO5dGIDljAFIP1/66\
+ QAJ9tauWaY6q9P/9SrD34URpVwUjIx+yz8rxEUu9x07NYUZWkPqVXgzJqioHMGJdQeu\
+ YJrmCm/mHcFw+d/sZU5Z8WnX3hUaLuxAR4OsyFizHW/D8hnX1L1JokxnhN7mljeIgVC\
+ 6kC/yadkmsRK70PCWcqI1SJie6jZIWD34HzfIa6WifF0sOlqONu+mnwndmOcRfhS4Sd\
+ FYxFlFRFlgW71jeNrJ7Y1CpKvzaYkN/3zKsxlUKNQT4XyUiKMyIyxcwUyd5+kdRF1jF\
+ lk6R2YP0z1TKNqLuGeC1A4wjAb2Nm6bmWUHNADx0yxzrOtsXMGlDmSGZRs4t7Zw1lrx\
+ FMEtd4GSfuIZG0Fxli3Sz0bPJPHyIJqUoJ7TONp6eUgxZ8ZbHvkuADY7xtmBbkFuQXg\
+ VwrCNdid5Xc0y2pWjhPCU5nFU5iO2ZcagR1SGrEzg7CZmSpV+YMkosDM2i4smsE9Qzu\
+ ewlvGWw+g8WBSb8/dfr9WFHpCb88Wxvo3Soqr3Vya+RttVYNHk2U8EQYBaCgYeU4wRd\
+ XRpAR9/J41bg5YnsFzAeIYoAJyrhAU4ICpgANaFx1tPYRILoFmFj3xPqLKbA+aHTW8K\
+ OeJxKu4nexSKQHI0mj8bv8XOtdDT9aWA8BqymoxpzuFdN0RtO1L0Y+DGkSVJUp7xMlP\
+ qXyVnGybH3Ua66vzcJ/RNkdlA6J8jELZ7aNfiQkYRaBZCFwVT5d3jeYDjnaWt0cNOcx\
+ LAtd5qBm2lYRT7N13Lonu2NpvVFbQFtAV1BJOBsy8NFIUp4EVCKfDYfGIfWGzZSkQSW\
+ iO5b7pU/TLgoYBxTAFAIUCD5CCmRYuOjHaTKQ5gEIkBO5LdmrgmdGdt7zlWM9gpBxhh\
+ zbRZp2h80+sEzYcmzX+l4WXsN2t93XKtEHNKDcO34+2pCtSsf8NPOlO5UaBomN0TCg8\
+ RjBLDIjkdjY+pyqWJ92RBIdmDsHO5Fz9teMjkckdFCD0N4WN7WMdnHJ1f1Eygwc81j5\
+ WSe+LVpqbZ8IkP/7YHnCKM7bn3MWwzx3RFez3gAxHiuZeFU10iLfvJr1PphlnEUGvMg\
+ 3jYatZrWBTDZji92t0R93CBgJeQaNhLwcx10Dt8dBhdwpseqY79U7L9ysX6N1WTMv8J\
+ mWCvDXqdk5jBCOHDJEnggHjIO/w6W2QD+jAj1/f2reGo9Jdn4+ihS6qCzQv99phNZTT\
+ a2dJrS9tS9rrLYdm0fPl2ae22lEadVihKRWUsOlVu74cJ5EDtoQNB3jPaTL/XOZnTym\
+ s44iCVMGDwjjqqa3/EVUSzgLneqzzaoR9l0DVQfHB8pUwMqN+ecZHuu8y3Z5iPioo6Q\
+ qzVxyWBksjcy3EDan8Zccao1GKpEDo7TRutNJltdovcXGVNl7YrAhRXbNLcqDMNi1XW\
+ MKu7ZryOFWqyeyV96S+NxguKP5N7ta/JbHvA==\",\"Sedm8ZMeS0/zmXzeO5OdIY3V\
+ tZl+6TXgdGGG63wTZv6TMjU6Rd/k/+PTm/8CAAD//z1KirK2RgAA\"]"
cookies: []
headers:
- name: date
- value: Mon, 09 Dec 2024 14:47:34 GMT
+ value: Fri, 27 Dec 2024 20:51:22 GMT
- name: content-type
value: text/plain; charset=utf-8
- name: transfer-encoding
@@ -3642,10 +3544,6 @@ log:
value: no-cache, max-age=0
- name: content-encoding
value: gzip
- - name: observed-calculated-ip-from-forwarded-for
- value: 80.82.18.146
- - name: observed-x-forwarded-for
- value: 80.82.18.146
- name: vary
value: Cookie,Accept-Encoding,Authorization,Cookie, Authorization,
X-Requested-With,Cookie
@@ -3657,13 +3555,13 @@ log:
value: 1; mode=block
- name: strict-transport-security
value: max-age=31536000; includeSubDomains; preload
- headersSize: 1434
+ headersSize: 1337
httpVersion: HTTP/1.1
redirectURL: ""
status: 200
statusText: OK
- startedDateTime: 2024-12-09T14:47:33.993Z
- time: 226
+ startedDateTime: 2024-12-27T20:51:22.522Z
+ time: 165
timings:
blocked: -1
connect: -1
@@ -3671,6 +3569,6 @@ log:
receive: 0
send: 0
ssl: -1
- wait: 226
+ wait: 165
pages: []
version: "1.2"
diff --git a/agent/src/__snapshots__/custom-commands.test.ts.snap b/agent/src/__snapshots__/custom-commands.test.ts.snap
index 77573cc4da56..44aa1259e36b 100644
--- a/agent/src/__snapshots__/custom-commands.test.ts.snap
+++ b/agent/src/__snapshots__/custom-commands.test.ts.snap
@@ -2,7 +2,6 @@
exports[`Custom Commands > commands/custom, chat command, open tabs context 1`] = `
"Here are all the files you've shared:
-
• src/example1.ts
• src/example2.ts
• src/example3.ts"
@@ -13,7 +12,7 @@ exports[`Custom Commands > commands/custom, edit command, edit mode 1`] = `
name: string
makeAnimalSound(): string
isMammal: boolean
- logName(): void
+ logAnimalName(): void
}"
`;
diff --git a/agent/src/__snapshots__/index.test.ts.snap b/agent/src/__snapshots__/index.test.ts.snap
index 4a822241c225..159e7a68f632 100644
--- a/agent/src/__snapshots__/index.test.ts.snap
+++ b/agent/src/__snapshots__/index.test.ts.snap
@@ -1,36 +1,38 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Agent > Chat > chat/submitMessage (long message) 1`] = `
-"I'll create a simple Hello World function in Java!
+"I'll create a simple Hello World function in Java for you.
-Here's a clear and standard Hello World implementation:
-
-\`\`\`java:HelloWorld.java
+\`\`\`java:src/HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
+ sayHello();
+ }
+
+ public static void sayHello() {
System.out.println("Hello, World!");
}
}
\`\`\`
-To compile and run this Java program, use these commands:
+To compile and run this Java program, you can use these commands:
\`\`\`bash
-javac HelloWorld.java
+javac src/HelloWorld.java
\`\`\`
\`\`\`bash
-java HelloWorld
+java -cp src HelloWorld
\`\`\`
-This code demonstrates the basic structure of a Java program with a main method that prints "Hello, World!" to the console. The code is straightforward and follows Java conventions perfectly."
+This creates a clean and simple Hello World program with a dedicated function to print the greeting. The program uses a separate \`sayHello()\` method which demonstrates good practice for function organization. Feel free to modify the message or add more functionality!"
`;
exports[`Agent > Chat > chat/submitMessage (short message) 1`] = `
{
"model": "anthropic::2024-10-22::claude-3-5-sonnet-latest",
"speaker": "assistant",
- "text": "Hi there! Great to meet you! I'm Cody, ready to help you with any coding or technical questions you have. What would you like to work on?",
+ "text": "Hi there! Great to meet you! I'm Cody, and I'm excited to help you with any coding or technical questions you may have. What would you like to work on?",
}
`;
@@ -38,7 +40,7 @@ exports[`Agent > Chat > chat/submitMessage (with mock context) 1`] = `
"\`\`\`typescript:src/dog.ts
export class Dog implements Animal {
name: string;
- isMammal: boolean = true;
+ isMammal = true;
constructor(name: string) {
this.name = name;
@@ -52,95 +54,83 @@ export class Dog implements Animal {
`;
exports[`Agent > Commands > commands/explain 1`] = `
-"The code you've shared is an excerpt from a TypeScript file, specifically an interface named \`Animal\`.
-
-The purpose of this code is to define a blueprint for an object that represents an animal. An interface in TypeScript works as a contract that defines the structure and behavior that an object implementing this interface should have.
-
-Let's break down the code to understand what it does:
-
-1. \`export interface Animal\`: This line declares an interface named \`Animal\`. By prefixing \`export\`, it allows other files or modules to import and use this interface.
-2. \`name: string\`: This line defines the first property in the \`Animal\` interface, which is \`name\`. This property's type should be of type \`string\`.
-3. \`makeAnimalSound(): string\`: This line introduces a method called \`makeAnimalSound\`. It does not take any input parameters, and it returns a value of type \`string\`. The intention of this method is to represent the sound that the animal makes.
-4. \`isMammal: boolean\`: This line defines a property named \`isMammal\` with type \`boolean\`. This indicates whether the animal is a mammal or not.
+"The code being explained is an interface for an object called \`Animal\` in the file \`animal.ts\`. This code defines the shape that an Animal object must take in order to be considered an Animal in the codebase.
-In summary, the \`Animal\` interface serves as a simple blueprint for what an object representing an animal should contain and look like. It expects the implementing object to have the following:
+1. The purpose of the code: The code is defining an \`Animal\` interface. This means that if any object is to be considered an \`Animal\`, it must have at least the following properties: \`name\` (a string), \`makeAnimalSound\` (a method that returns a string), and \`isMammal\` (a boolean value).
+2. Inputs: This code, as an interface, doesn't have inputs in the traditional sense. However, any object that wants to conform to the shape of an \`Animal\` will need to provide values for the required properties and methods defined in the \`Animal\` interface. For example, another code file might create an object like so: \`let myDog: Animal = { name: 'Fido', makeAnimalSound: () => 'Woof!', isMammal: true }\`.
+3. Outputs: The code doesn't produce outputs as it is just an interface. However, it enables other code to define objects with a consistent structure.
+4. Algorithm: The code uses TypeScript syntax to define an interface. This interface consists of three properties (\`name\`, \`makeAnimalSound\`, \`isMammal\`), each with a specific type; \`string\`, \`() => string\`, and \`boolean\`, respectively.
+5. Logic and data transformations: Since this is an interface, there are no actual logic and data transformations happening. However, it provides a blueprint for other objects so that they can implement the required logic and data transformations.
-* A \`name\` property as a \`string\`.
-* A \`makeAnimalSound\` method that returns a \`string\`.
-* An \`isMammal\` property as a \`boolean\`.
-
-This blueprint does not define input(s) as it only serves as a contract or a structure, and it produces different outputs depending on what kind of animal object adheres to the contract. The interface helps us ensure that provided animal objects contain the right data and behavior, which makes it easier to work with such objects throughout the codebase.
-
-A beginner should note that TypeScript interfaces help define data structures and behaviors for easier object manipulation, ensuring better consistency during coding while catching potential errors early on."
+In summary, the given code describes the Animal interface, providing a blueprint for other objects to implement the required shape and behavior. Working with this blueprint, programmers can maintain consistency throughout the codebase and implement specific functionalities according to their demands."
`;
exports[`Agent > Commands > commands/smell 1`] = `
-"Here are my suggestions:
-
-1. **Add type annotations to the methods of the \`Animal\` interface:**
-
-Adding type annotations to the \`makeAnimalSound\` method, like this:
-\`\`\`typescript
-makeAnimalSound(): string
-\`\`\`
-will ensure that the method returns a string, and will make it clear to other developers what type of value the method should return.
-
-2. **Add a constructor function to the \`Animal\` interface:**
-
-Adding a constructor function to the \`Animal\` interface, like this:
-\`\`\`typescript
-construct(name: string, isMammal: boolean)
-\`\`\`
-will make it clear how an \`Animal\` object should be initialized, and will ensure that all \`Animal\` objects have the necessary properties.
-
-3. **Use \`readonly\` properties for the \`name\` and \`isMammal\` properties:**
-
-Using \`readonly\` properties for the \`name\` and \`isMammal\` properties, like this:
+"Based on the provided code from \`@src/animal.ts:1-6\`:
\`\`\`typescript
export interface Animal {
- readonly name: string
- readonly isMammal: boolean
+ name: string
makeAnimalSound(): string
+ isMammal: boolean
}
\`\`\`
-will ensure that the \`name\` and \`isMammal\` properties cannot be changed after an \`Animal\` object is created. This can help prevent bugs caused by accidental changes to these properties.
-
-4. **Use a \`class\` instead of an \`interface\` to define \`Animal\`:**
-
-Using a \`class\` instead of an \`interface\` to define \`Animal\`, like this:
-\`\`\`typescript
-export class Animal {
- constructor(public name: string, public isMammal: boolean) { }
-
- makeAnimalSound(): string {
- throw new Error("Method 'makeAnimalSound' must be implemented.");
+Here are 5 suggestions to improve the code:
+1. **Add type annotations for the methods.** Adding type annotations for the methods in the interface could improve type safety and self-document the code.
+ \`\`\`typescript
+ export interface Animal {
+ name: string
+ makeAnimalSound(): string
+ isMammal: boolean
+ eat(food: string): void
+ }
+ \`\`\`
+ Benefit: Enhanced type safety, and clearer understanding of intended usage.
+2. **Add access modifiers.** By specifying access modifiers (public, private, protected) for members, we can ensure encapsulation and control access.
+ \`\`\`typescript
+ export interface Animal {
+ name: string
+ makeAnimalSound(): string
+ readonly isMammal: boolean // readonly ensures that this property cannot be changed
+ }
+ \`\`\`
+ Benefit: Improved encapsulation, and consistency in codebase.
+3. **Follow PascalCase for naming conventions in TypeScript.** Use PascalCase for method names inside the interface.
+ \`\`\`typescript
+ export interface Animal {
+ name: string
+ MakeAnimalSound(): string
+ isMammal: boolean
+ }
+ \`\`\`
+ Benefit: Adherence to community conventions and improved readability.
+
+4. **Use enums when defining a set of named values.** Instead of using boolean values for \`isMammal\`, use an enum.
+ \`\`\`typescript
+ export enum AnimalType {
+ Mammal,
+ Reptile,
+ Amphibian
}
-}
-\`\`\`
-will allow you to define a constructor and common methods that all \`Animal\` objects will inherit.
-
-5. **Add comments to the code:**
-
-Adding comments to the code, like this:
-\`\`\`typescript
-/**
- * An interface for defining an animal.
- */
-export interface Animal {
- /** The name of the animal. */
- name: string
+ export interface Animal {
+ name: string
+ makeAnimalSound(): string
+ type: AnimalType
+ }
+ \`\`\`
+ Benefit: Provides a clearer, more self-descriptive representation of the data.
+5. **Add JSDoc comments for TypeScript interfaces.** JSDoc comments make code more readable and provide useful information when interacting with code through an IDE.
+ \`\`\`typescript
/**
- * Makes the animal sound.
- * @returns The sound that the animal makes.
+ * Animal interface
*/
- makeAnimalSound(): string
-
- /** Whether the animal is a mammal. */
- isMammal: boolean
-}
-\`\`\`
-will make the code easier to understand for other developers, and will help them use the \`Animal\` interface correctly.
+ export interface Animal {
+ name: string
+ makeAnimalSound(): string
+ isMammal: boolean
+ }
+ \`\`\`
+ Benefit: Improved readability and discoverability of interface usage in IDEs.
-Overall, the code is well-written and follows good design principles. However, adding type annotations, constructor functions, \`readonly\` properties, a \`class\` definition, and comments could make it even more robust, efficient, and easy to understand."
+Overall, the provided code snippet demonstrates a good foundation for a TypeScript interface. The main opportunities for improvement center around adhering to TypeScript conventions and enhancing code readability for both humans and integrated development environments."
`;
diff --git a/agent/src/custom-commands.test.ts b/agent/src/custom-commands.test.ts
index 032b6be4cfc9..2aeac543116b 100644
--- a/agent/src/custom-commands.test.ts
+++ b/agent/src/custom-commands.test.ts
@@ -82,7 +82,7 @@ describe('Custom Commands', () => {
expect(result.type).toBe('chat')
const lastMessage = await client.firstNonEmptyTranscript(result.chatResult as string)
const reply = trimEndOfLine(lastMessage.messages.at(-1)?.text ?? '')
- expect(reply).toMatchInlineSnapshot(`"7"`, explainPollyError)
+ expect(reply).toMatchInlineSnapshot(`"6"`, explainPollyError)
}, 30_000)
it('commands/custom, edit command, insert mode', async () => {
diff --git a/agent/src/index.test.ts b/agent/src/index.test.ts
index c70c3ad8addc..6ce9dd6675ea 100644
--- a/agent/src/index.test.ts
+++ b/agent/src/index.test.ts
@@ -197,8 +197,8 @@ describe('Agent', () => {
expect(currentUserCodySubscription).toMatchInlineSnapshot(`
{
"applyProRateLimits": true,
- "currentPeriodEndAt": "2024-12-14T22:11:32Z",
- "currentPeriodStartAt": "2024-11-14T22:11:32Z",
+ "currentPeriodEndAt": "2025-01-14T22:11:32Z",
+ "currentPeriodStartAt": "2024-12-14T22:11:32Z",
"plan": "PRO",
"status": "ACTIVE",
}
diff --git a/jetbrains/src/main/kotlin/com/sourcegraph/cody/inspections/CodyFixHighlightPass.kt b/jetbrains/src/main/kotlin/com/sourcegraph/cody/inspections/CodyFixHighlightPass.kt
index 2013eea738ea..a3a5ed55a159 100644
--- a/jetbrains/src/main/kotlin/com/sourcegraph/cody/inspections/CodyFixHighlightPass.kt
+++ b/jetbrains/src/main/kotlin/com/sourcegraph/cody/inspections/CodyFixHighlightPass.kt
@@ -115,7 +115,9 @@ class CodyFixHighlightPass(val file: PsiFile, val editor: Editor) :
@RequiresEdt
override fun doApplyInformationToEditor() {
for (highlight in myHighlights) {
- highlight.unregisterQuickFix { (it as? CodeActionQuickFix)?.familyName == CodeActionQuickFix.FAMILY_NAME }
+ highlight.unregisterQuickFix {
+ (it as? CodeActionQuickFix)?.familyName == CodeActionQuickFix.FAMILY_NAME
+ }
if (highlight.startOffset > document.textLength ||
highlight.endOffset > document.textLength ||
diff --git a/vscode/src/chat/chat-view/ChatController.test.ts b/vscode/src/chat/chat-view/ChatController.test.ts
index 0b3df5c6164e..dd8f3aa130d1 100644
--- a/vscode/src/chat/chat-view/ChatController.test.ts
+++ b/vscode/src/chat/chat-view/ChatController.test.ts
@@ -130,7 +130,7 @@ describe('ChatController', () => {
signal: new AbortController().signal,
source: 'chat',
})
- expect(postMessageSpy.mock.calls.at(5)?.at(0)).toStrictEqual<
+ expect(postMessageSpy.mock.calls.at(4)?.at(0)).toStrictEqual<
Extract
>({
type: 'transcript',
@@ -146,7 +146,7 @@ describe('ChatController', () => {
search: undefined,
error: undefined,
editorState: null,
- contextFiles: [],
+ contextFiles: undefined,
processes: undefined,
},
{
@@ -167,7 +167,7 @@ describe('ChatController', () => {
await vi.runOnlyPendingTimersAsync()
expect(mockChatClient.chat).toBeCalledTimes(1)
expect(addBotMessageSpy).toHaveBeenCalledWith('1', ps`Test reply 1`, 'my-model')
- expect(postMessageSpy.mock.calls.at(6)?.at(0)).toStrictEqual<
+ expect(postMessageSpy.mock.calls.at(5)?.at(0)).toStrictEqual<
Extract
>({
type: 'transcript',
@@ -381,7 +381,7 @@ describe('ChatController', () => {
await vi.runOnlyPendingTimersAsync()
expect(mockChatClient.chat).toBeCalledTimes(1)
expect(addBotMessageSpy).toHaveBeenCalledWith('1', ps`Test partial reply`, 'my-model')
- expect(postMessageSpy.mock.calls.at(7)?.at(0)).toStrictEqual<
+ expect(postMessageSpy.mock.calls.at(8)?.at(0)).toStrictEqual<
Extract
>({
type: 'transcript',
@@ -402,12 +402,12 @@ describe('ChatController', () => {
},
{
speaker: 'assistant',
- model: undefined,
+ model: FIXTURE_MODEL.id,
error: errorToChatError(new Error('my-error')),
intent: undefined,
manuallySelectedIntent: undefined,
editorState: undefined,
- text: undefined,
+ text: 'Test partial reply',
contextFiles: undefined,
search: undefined,
processes: undefined,
diff --git a/vscode/src/chat/chat-view/ChatController.ts b/vscode/src/chat/chat-view/ChatController.ts
index 5462f133bdb9..de853295ecbd 100644
--- a/vscode/src/chat/chat-view/ChatController.ts
+++ b/vscode/src/chat/chat-view/ChatController.ts
@@ -9,30 +9,19 @@ import {
type ClientActionBroadcast,
ClientConfigSingleton,
type CodyClientConfig,
- type CompletionParameters,
type ContextItem,
- type ContextItemFile,
- type ContextItemOpenCtx,
- type ContextItemRepository,
ContextItemSource,
DOTCOM_URL,
type DefaultChatCommands,
- DefaultEditCommands,
type EventSource,
FeatureFlag,
type Guardrails,
- type Message,
ModelUsage,
type NLSSearchDynamicFilter,
PromptString,
- REMOTE_DIRECTORY_PROVIDER_URI,
- REMOTE_FILE_PROVIDER_URI,
- REMOTE_REPOSITORY_PROVIDER_URI,
- type RankedContext,
type SerializedChatInteraction,
type SerializedChatTranscript,
type SerializedPromptEditorState,
- Typewriter,
addMessageListenersForExtensionAPI,
authStatus,
cenv,
@@ -41,18 +30,15 @@ import {
currentAuthStatus,
currentAuthStatusAuthed,
currentResolvedConfig,
- currentSiteVersion,
currentUserProductSubscription,
distinctUntilChanged,
extractContextFromTraceparent,
featureFlagProvider,
firstResultFromOperation,
forceHydration,
- getContextForChatMessage,
graphqlClient,
hydrateAfterPostMessage,
inputTextWithMappedContextChipsFromPromptEditorState,
- inputTextWithoutContextChipsFromPromptEditorState,
isAbortErrorOrSocketHangUp,
isContextWindowLimitError,
isDefined,
@@ -74,7 +60,6 @@ import {
startWith,
storeLastValue,
subscriptionDisposable,
- telemetryEvents,
telemetryRecorder,
tracer,
truncatePromptString,
@@ -86,7 +71,6 @@ import * as vscode from 'vscode'
import { type Span, context } from '@opentelemetry/api'
import { captureException } from '@sentry/core'
-import { getTokenCounterUtils } from '@sourcegraph/cody-shared/src/token/counter'
import type { TelemetryEventParameters } from '@sourcegraph/telemetry'
import { Subject, map } from 'observable-fns'
import type { URI } from 'vscode-uri'
@@ -98,27 +82,19 @@ import {
} from '../../auth/auth-progress-indicator'
import type { startTokenReceiver } from '../../auth/token-receiver'
import { getCurrentUserId } from '../../auth/user'
-import { executeCodyCommand } from '../../commands/CommandsController'
import { getContextFileFromUri } from '../../commands/context/file-path'
import { getContextFileFromCursor } from '../../commands/context/selection'
-import { escapeRegExp } from '../../context/openctx/remoteFileSearch'
-import { getEditor } from '../../editor/active-editor'
-import { resolveContextItems } from '../../editor/utils/editor-context'
import type { VSCodeEditor } from '../../editor/vscode-editor'
import type { ExtensionClient } from '../../extension-client'
import { migrateAndNotifyForOutdatedModels } from '../../models/modelMigrator'
import { logDebug, outputChannelLogger } from '../../output-channel-logger'
-import { getCategorizedMentions } from '../../prompt-builder/utils'
import { hydratePromptText } from '../../prompts/prompt-hydration'
import { listPromptTags, mergedPromptsAndLegacyCommands } from '../../prompts/prompts'
-import { publicRepoMetadataIfAllWorkspaceReposArePublic } from '../../repository/githubRepoMetadata'
-import { getFirstRepoNameContainingUri } from '../../repository/repo-name-resolver'
import { authProvider } from '../../services/AuthProvider'
import { AuthProviderSimplified } from '../../services/AuthProviderSimplified'
import { localStorage } from '../../services/LocalStorageProvider'
import { secretStorage } from '../../services/SecretStorageProvider'
import { TraceSender } from '../../services/open-telemetry/trace-sender'
-import { recordExposedExperimentsToSpan } from '../../services/open-telemetry/utils'
import {
handleCodeFromInsertAtCursor,
handleCodeFromSaveToNewFile,
@@ -129,8 +105,6 @@ import { openExternalLinks } from '../../services/utils/workspace-action'
import { TestSupport } from '../../test-support'
import type { MessageErrorType } from '../MessageProvider'
import { CodyToolProvider } from '../agentic/CodyToolProvider'
-import { DeepCodyAgent } from '../agentic/DeepCody'
-import { DeepCodyRateLimiter } from '../agentic/DeepCodyRateLimiter'
import { getMentionMenuData } from '../context/chatContext'
import type { ChatIntentAPIClient } from '../context/chatIntentAPIClient'
import { observeDefaultContext } from '../initialContext'
@@ -146,11 +120,11 @@ import { countGeneratedCode } from '../utils'
import { ChatBuilder, prepareChatMessage } from './ChatBuilder'
import { chatHistory } from './ChatHistoryManager'
import { CodyChatEditorViewType } from './ChatsController'
-import { type ContextRetriever, toStructuredMentions } from './ContextRetriever'
+import type { ContextRetriever } from './ContextRetriever'
import { InitDoer } from './InitDoer'
import { getChatPanelTitle } from './chat-helpers'
-import { type HumanInput, getPriorityContext } from './context'
-import { DefaultPrompter, type PromptInfo } from './prompt'
+import { OmniboxTelemetry } from './handlers/OmniboxTelemetry'
+import { getAgent } from './handlers/registry'
import { getPromptsMigrationInfo, startPromptsMigration } from './prompts-migration'
export interface ChatControllerOptions {
@@ -562,12 +536,6 @@ export class ChatController implements vscode.Disposable, vscode.WebviewViewProv
private featureDeepCodyShellContext = storeLastValue(
featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.DeepCodyShellContext)
)
- private featureDeepCodyRateLimitBase = storeLastValue(
- featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.DeepCodyRateLimitBase)
- )
- private featureDeepCodyRateLimitMultiplier = storeLastValue(
- featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.DeepCodyRateLimitMultiplier)
- )
private async getConfigForWebview(): Promise {
const { configuration, auth } = await currentResolvedConfig()
@@ -779,7 +747,7 @@ export class ChatController implements vscode.Disposable, vscode.WebviewViewProv
return { intent: 'chat', intentScores: [] }
}
- public async sendChat(
+ private async sendChat(
{
requestID,
inputText,
@@ -795,7 +763,6 @@ export class ChatController implements vscode.Disposable, vscode.WebviewViewProv
span: Span
): Promise {
span.addEvent('ChatController.sendChat')
- const authStatus = currentAuthStatusAuthed()
// Use default model if no model is selected.
const model = await wrapInActiveSpan('chat.resolveModel', () =>
@@ -804,59 +771,19 @@ export class ChatController implements vscode.Disposable, vscode.WebviewViewProv
if (!model) {
throw new Error('No model selected, and no default chat model is available')
}
- this.chatBuilder.setSelectedModel(model)
-
- const isDeepCodyModel = model?.includes('deep-cody')
- // Deep Cody is only invoked for the first 2 submitted messages.
- const isDeepCodyEnabled = isDeepCodyModel && this.chatBuilder.getMessages().length < 4
- // The limit could be 0, 50 * 1 (50), 50 * 2 (100)
- const deepCodyRateLimiter = new DeepCodyRateLimiter(
- this.featureDeepCodyRateLimitBase.value.last ? 50 : 0,
- this.featureDeepCodyRateLimitMultiplier.value.last ? 2 : 1
- )
- const deepCodyLimit = deepCodyRateLimiter.isAtLimit()
- if (isDeepCodyEnabled && deepCodyLimit) {
- this.postError(deepCodyRateLimiter.getRateLimitError(deepCodyLimit), 'transcript')
- this.handleAbort()
- return
- }
- const { isPublic: repoIsPublic, repoMetadata } = await wrapInActiveSpan(
- 'chat.getRepoMetadata',
- () => firstResultFromOperation(publicRepoMetadataIfAllWorkspaceReposArePublic)
- )
+ this.chatBuilder.setSelectedModel(model)
- const telemetryProperties = {
+ const recorder = await OmniboxTelemetry.create({
requestID,
chatModel: model,
- authStatus,
source,
command,
sessionID: this.chatBuilder.sessionID,
- repoMetadata,
- repoIsPublic,
traceId: span.spanContext().traceId,
promptText: inputText,
- } as const
- const tokenCounterUtils = await wrapInActiveSpan('chat.getTokenCounterUtils', () =>
- getTokenCounterUtils()
- )
-
- telemetryEvents['cody.chat-question/submitted'].record(
- {
- ...telemetryProperties,
- mentions,
- },
- tokenCounterUtils
- )
-
- this.postEmptyMessageInProgress(model)
-
- const inputTextWithoutContextChips = editorState
- ? PromptString.unsafe_fromUserQuery(
- inputTextWithoutContextChipsFromPromptEditorState(editorState)
- )
- : inputText
+ })
+ recorder.recordChatQuestionSubmitted(mentions)
const { intent, intentScores } = await this.getIntentAndScores({
requestID,
@@ -867,114 +794,80 @@ export class ChatController implements vscode.Disposable, vscode.WebviewViewProv
detectedIntentScores,
signal,
})
-
signal.throwIfAborted()
this.chatBuilder.setLastMessageIntent(intent)
- this.postEmptyMessageInProgress(model)
-
- if (intent === 'search') {
- return await this.handleSearchIntent({
- inputTextWithoutContextChips: inputTextWithoutContextChips.toString(),
- mentions,
- signal,
- })
- }
-
- // All mentions we receive are either source=initial or source=user. If the caller
- // forgot to set the source, assume it's from the user.
- mentions = mentions.map(m => (m.source ? m : { ...m, source: ContextItemSource.User }))
-
- const contextAlternatives = await this.computeContext(
- { text: inputText, mentions },
- requestID,
- editorState,
- span,
- signal
- )
- signal.throwIfAborted()
- const corpusContext = contextAlternatives[0].items
- const userSpecifiedIntent =
- manuallySelectedIntent && detectedIntent
- ? detectedIntent
- : this.featureCodyExperimentalOneBox
- ? 'auto'
- : 'chat'
-
- signal.throwIfAborted()
-
- if (['edit', 'insert'].includes(intent || '')) {
- telemetryEvents['cody.chat-question/executed'].record(
- {
- ...telemetryProperties,
- context: corpusContext,
- userSpecifiedIntent,
- detectedIntent: intent,
- detectedIntentScores: intentScores,
- },
- { current: span, addMetadata: true },
- tokenCounterUtils
- )
- }
-
- if (intent === 'edit' || intent === 'insert') {
- return await this.handleEditMode({
- requestID,
- mode: intent,
- instruction: inputTextWithoutContextChips,
- context: corpusContext,
- signal,
- contextAlternatives,
- })
- }
-
- // Experimental Feature: Deep Cody
- if (isDeepCodyEnabled) {
- const agent = new DeepCodyAgent(
- this.chatBuilder,
- this.chatClient,
- this.toolProvider.getTools(),
- corpusContext
- )
- agent.setStatusCallback(model => this.postEmptyMessageInProgress(model))
- const agenticContext = await agent.getContext(requestID, signal)
- corpusContext.push(...agenticContext)
- }
+ this.postEmptyMessageInProgress(model)
- const { explicitMentions, implicitMentions } = getCategorizedMentions(corpusContext)
+ const agentName = ['search', 'edit', 'insert'].includes(intent ?? '')
+ ? (intent as string)
+ : model
+ const agent = getAgent(agentName, {
+ contextRetriever: this.contextRetriever,
+ editor: this.editor,
+ chatClient: this.chatClient,
+ codyToolProvider: this.toolProvider,
+ })
- const prompter = new DefaultPrompter(explicitMentions, implicitMentions, command !== undefined)
+ recorder.setIntentInfo({
+ userSpecifiedIntent:
+ manuallySelectedIntent && detectedIntent
+ ? detectedIntent
+ : this.featureCodyExperimentalOneBox
+ ? 'auto'
+ : 'chat',
+ detectedIntent: intent,
+ detectedIntentScores: intentScores,
+ })
+ this.postEmptyMessageInProgress(model)
+ let messageInProgress: ChatMessage | undefined = undefined
try {
- const versions = await currentSiteVersion()
- if (!versions) {
- throw new Error('unable to determine site version')
- }
- const { prompt, context } = await this.buildPrompt(
- prompter,
- signal,
- requestID,
- versions.codyAPIVersion,
- contextAlternatives
- )
-
- telemetryEvents['cody.chat-question/executed'].record(
+ await agent.handle(
{
- ...telemetryProperties,
- context,
- userSpecifiedIntent,
- detectedIntent: intent,
- detectedIntentScores: intentScores,
+ requestID,
+ inputText,
+ mentions,
+ editorState,
+ signal,
+ chatBuilder: this.chatBuilder,
+ span,
+ recorder,
},
{
- addMetadata: true,
- current: span,
- },
- tokenCounterUtils
- )
+ postError: (error: Error, type?: MessageErrorType): void => {
+ this.postError(error, type)
+ },
+ postMessageInProgress: (message?: ChatMessage): void => {
+ messageInProgress = message
+ this.postViewTranscript(message)
+ },
+ postDone: (op?: { abort: boolean }): void => {
+ if (op?.abort) {
+ this.handleAbort()
+ return
+ }
+
+ // HACK(beyang): This conditional preserves the behavior from when
+ // all the response generation logic was handled in this method.
+ // In future work, we should remove this special-casing and unify
+ // how new messages are posted to the transcript.
+ if (
+ messageInProgress &&
+ (['search', 'insert', 'edit'].includes(messageInProgress?.intent ?? '') ||
+ messageInProgress?.search ||
+ messageInProgress?.error)
+ ) {
+ this.chatBuilder.addBotMessage(messageInProgress, model)
+ } else if (messageInProgress?.text) {
+ this.addBotMessage(requestID, messageInProgress.text, model)
+ }
- signal.throwIfAborted()
- this.streamAssistantResponse(requestID, prompt, model, span, signal)
+ this.saveSession()
+ this.postViewTranscript()
+ },
+ }
+ )
} catch (error) {
if (isAbortErrorOrSocketHangUp(error as Error)) {
return
@@ -1017,310 +910,6 @@ export class ChatController implements vscode.Disposable, vscode.WebviewViewProv
return
}
- private async handleSearchIntent({
- inputTextWithoutContextChips,
- mentions,
- signal,
- }: {
- inputTextWithoutContextChips: string
- mentions: ContextItem[]
- signal: AbortSignal
- }): Promise {
- signal.throwIfAborted()
-
- this.chatBuilder.setLastMessageIntent('search')
- const scopes: string[] = await this.getSearchScopesFromMentions(mentions)
-
- const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri
- const currentFile = getEditor()?.active?.document?.uri || workspaceRoot
- const repoName = currentFile ? await getFirstRepoNameContainingUri(currentFile) : undefined
- const boostParameter = repoName ? `boost:repo(${repoName})` : ''
-
- const query = `content:"${inputTextWithoutContextChips.replaceAll(
- '"',
- '\\"'
- )}" ${boostParameter} ${scopes.length ? `(${scopes.join(' OR ')})` : ''}`
-
- try {
- const response = await graphqlClient.nlsSearchQuery({
- query,
- signal,
- })
-
- this.chatBuilder.addSearchResultAsBotMessage({
- query,
- response,
- })
-
- void this.saveSession()
- this.postViewTranscript()
- } catch (err) {
- this.chatBuilder.addErrorAsBotMessage(err as Error, ChatBuilder.NO_MODEL)
- void this.saveSession()
- this.postViewTranscript()
- }
- }
-
- private async getSearchScopesFromMentions(mentions: ContextItem[]): Promise {
- const validMentions = mentions.reduce(
- (groups, mention) => {
- switch (mention.type) {
- case 'repository':
- groups.repository.push(mention)
- break
- case 'file':
- groups[mention.type].push(mention)
- break
- case 'openctx':
- if (mention.providerUri === REMOTE_REPOSITORY_PROVIDER_URI) {
- groups.repository.push(mention)
- } else {
- groups.openctx.push(mention)
- }
- }
-
- return groups
- },
- { repository: [], file: [], openctx: [] } as {
- repository: (ContextItemRepository | ContextItemOpenCtx)[]
- file: ContextItemFile[]
- openctx: ContextItemOpenCtx[]
- }
- )
-
- const scopes: string[] = []
-
- // Convert all repo mentions to a single search filter.
- // Example: repo:^(github\.com/sourcegraph/sourcegraph|github\.com/sourcegraph/cody)$
- if (validMentions.repository.length > 0) {
- const escapedRepoNames = validMentions.repository
- .filter(({ repoName }) => !!repoName)
- .map(({ repoName }) => escapeRegExp(repoName || ''))
- .join('|')
- scopes.push(`(repo:^(${escapedRepoNames})$)`)
- }
-
- // Convert all local file mentions to combination of file & repo filters.
- // Example: (repo:a file:myfile)
- await Promise.all(
- validMentions.file.map(async mention => {
- const repoName =
- (mention as ContextItemFile).remoteRepositoryName ||
- (await getFirstRepoNameContainingUri(mention.uri))
-
- const workspace = vscode.workspace.getWorkspaceFolder(mention.uri)
- if (!repoName || !workspace) {
- return
- }
-
- const filePath = escapeRegExp(
- mention.uri.toString().split(`${workspace.name}/`)[1] || ''
- )
-
- if (!filePath || !repoName) {
- return
- }
-
- return scopes.push(`(file:^${filePath}$ repo:^${repoName}$)`)
- })
- )
-
- // Convert all remote file & directory mentions to combination of file & repo filters.
- // Example: (repo:a file:mydir)
- // biome-ignore lint/complexity/noForEach:
- validMentions.openctx.forEach(mention => {
- switch ((mention as ContextItemOpenCtx).providerUri) {
- case REMOTE_FILE_PROVIDER_URI:
- {
- const filePath = escapeRegExp(mention.mention?.data?.filepath || '')
- const repoName = escapeRegExp(mention.mention?.data?.reponame || '')
- if (!filePath || !repoName) {
- return
- }
- scopes.push(`(file:^${filePath}$ repo:^${repoName}$)`)
- }
- break
- case REMOTE_DIRECTORY_PROVIDER_URI: {
- const filePath = escapeRegExp(mention.mention?.data?.directoryPath || '')
- const repoName = escapeRegExp(mention.mention?.data?.repoName || '')
- if (!filePath || !repoName) {
- return
- }
-
- scopes.push(`(file:^${filePath} repo:^${repoName}$)`)
- }
- }
- })
-
- return scopes
- }
-
- private async handleEditMode({
- requestID,
- mode,
- instruction,
- context,
- signal,
- contextAlternatives,
- }: {
- requestID: string
- instruction: PromptString
- mode: 'edit' | 'insert'
- context: ContextItem[]
- signal: AbortSignal
- contextAlternatives: RankedContext[]
- }): Promise {
- signal.throwIfAborted()
-
- this.chatBuilder.setLastMessageContext(context, contextAlternatives)
- this.chatBuilder.setLastMessageIntent(mode)
-
- const result = await executeCodyCommand(DefaultEditCommands.Edit, {
- requestID,
- runInChatMode: true,
- userContextFiles: context,
- configuration: {
- instruction,
- mode,
- // Only document code uses non-edit (insert mode), set doc intent for Document code prompt
- // to specialize cody command runner for document code case.
- intent: mode === 'edit' ? 'edit' : 'doc',
- },
- })
-
- if (result?.type !== 'edit' || !result.task) {
- this.postError(new Error('Failed to execute edit command'), 'transcript')
- return
- }
-
- const task = result.task
-
- let responseMessage = `Here is the response for the ${task.intent} instruction:\n`
-
- if (!task.diff && task.replacement) {
- task.diff = [
- {
- type: 'insertion',
- text: task.replacement,
- range: task.originalRange,
- },
- ]
- }
-
- task.diff?.map(diff => {
- responseMessage += '\n```diff\n'
- if (diff.type === 'deletion') {
- responseMessage += task.document
- .getText(diff.range)
- .split('\n')
- .map(line => `- ${line}`)
- .join('\n')
- }
- if (diff.type === 'decoratedReplacement') {
- responseMessage += diff.oldText
- .split('\n')
- .map(line => `- ${line}`)
- .join('\n')
- responseMessage += diff.text
- .split('\n')
- .map(line => `+ ${line}`)
- .join('\n')
- }
- if (diff.type === 'insertion') {
- responseMessage += diff.text
- .split('\n')
- .map(line => `+ ${line}`)
- .join('\n')
- }
- responseMessage += '\n```'
- })
-
- this.chatBuilder.addBotMessage(
- {
- text: ps`${PromptString.unsafe_fromLLMResponse(responseMessage)}`,
- },
- this.chatBuilder.selectedModel || ChatBuilder.NO_MODEL
- )
-
- void this.saveSession()
- this.postViewTranscript()
- }
-
- private async computeContext(
- { text, mentions }: HumanInput,
- requestID: string,
- editorState: SerializedPromptEditorState | null,
- span: Span,
- signal?: AbortSignal
- ): Promise {
- try {
- return wrapInActiveSpan('chat.computeContext', span => {
- return this._computeContext({ text, mentions }, requestID, editorState, span, signal)
- })
- } catch (e) {
- this.postError(new Error(`Unexpected error computing context, no context was used: ${e}`))
- return [
- {
- strategy: 'none',
- items: [],
- },
- ]
- }
- }
-
- private async _computeContext(
- { text, mentions }: HumanInput,
- requestID: string,
- editorState: SerializedPromptEditorState | null,
- span: Span,
- signal?: AbortSignal
- ): Promise {
- // Remove context chips (repo, @-mentions) from the input text for context retrieval.
- const inputTextWithoutContextChips = editorState
- ? PromptString.unsafe_fromUserQuery(
- inputTextWithoutContextChipsFromPromptEditorState(editorState)
- )
- : text
- const structuredMentions = toStructuredMentions(mentions)
- const retrievedContextPromise = this.contextRetriever.retrieveContext(
- structuredMentions,
- inputTextWithoutContextChips,
- span,
- signal
- )
- const priorityContextPromise = retrievedContextPromise
- .then(p => getPriorityContext(text, this.editor, p))
- .catch(() => getPriorityContext(text, this.editor, []))
- const openCtxContextPromise = getContextForChatMessage(text.toString(), signal)
- const [priorityContext, retrievedContext, openCtxContext] = await Promise.all([
- priorityContextPromise,
- retrievedContextPromise.catch(e => {
- this.postError(new Error(`Failed to retrieve search context: ${e}`))
- return []
- }),
- openCtxContextPromise,
- ])
-
- const resolvedExplicitMentionsPromise = resolveContextItems(
- this.editor,
- [structuredMentions.symbols, structuredMentions.files, structuredMentions.openCtx].flat(),
- text,
- signal
- )
-
- return [
- {
- strategy: 'local+remote',
- items: combineContext(
- await resolvedExplicitMentionsPromise,
- openCtxContext,
- priorityContext,
- retrievedContext
- ),
- },
- ]
- }
-
private submitOrEditOperation: AbortController | undefined
public startNewSubmitOrEditOperation(): AbortSignal {
this.submitOrEditOperation?.abort()
@@ -1640,166 +1229,6 @@ export class ChatController implements vscode.Disposable, vscode.WebviewViewProv
// #region chat request lifecycle methods
// =======================================================================
- /**
- * Constructs the prompt and updates the UI with the context used in the prompt.
- */
- private async buildPrompt(
- prompter: DefaultPrompter,
- abortSignal: AbortSignal,
- requestID: string,
- codyApiVersion: number,
- contextAlternatives?: RankedContext[]
- ): Promise {
- const { prompt, context } = await prompter.makePrompt(this.chatBuilder, codyApiVersion)
- abortSignal.throwIfAborted()
-
- // Update UI based on prompt construction. Includes the excluded context items to display in the UI
- this.chatBuilder.setLastMessageContext(
- [...context.used, ...context.ignored],
- contextAlternatives
- )
-
- return { prompt, context }
- }
-
- private streamAssistantResponse(
- requestID: string,
- prompt: Message[],
- model: ChatModel,
- chatSpan: Span,
- abortSignal: AbortSignal
- ): void {
- abortSignal.throwIfAborted()
- this.postEmptyMessageInProgress(model)
-
- tracer.startActiveSpan('chat.streamResponse', llmSpan => {
- let firstTokenMeasured = false
- function measureFirstToken() {
- if (firstTokenMeasured) {
- return
- }
- firstTokenMeasured = true
- llmSpan.addEvent('firstToken')
- }
-
- this.sendLLMRequest(
- prompt,
- requestID,
- model,
- {
- update: content => {
- measureFirstToken()
- this.postViewTranscript({
- speaker: 'assistant',
- text: PromptString.unsafe_fromLLMResponse(content),
- model,
- })
- },
- close: content => {
- measureFirstToken()
- recordExposedExperimentsToSpan(chatSpan)
- llmSpan.end()
- this.addBotMessage(
- requestID,
- PromptString.unsafe_fromLLMResponse(content),
- model
- ).finally(() => {
- chatSpan.end()
- })
- },
- error: (partialResponse, error) => {
- this.postError(error, 'transcript')
- if (isAbortErrorOrSocketHangUp(error)) {
- abortSignal.throwIfAborted()
- }
- try {
- // We should still add the partial response if there was an error
- // This'd throw an error if one has already been added
- this.addBotMessage(
- requestID,
- PromptString.unsafe_fromLLMResponse(partialResponse),
- model
- )
- } catch {
- console.error('Streaming Error', error)
- }
- recordErrorToSpan(llmSpan, error)
- chatSpan.end()
- },
- },
- abortSignal
- )
- })
- }
-
- /**
- * Issue the chat request and stream the results back, updating the model and view
- * with the response.
- */
- private async sendLLMRequest(
- prompt: Message[],
- requestID: string,
- model: ChatModel,
- callbacks: {
- update: (response: string) => void
- close: (finalResponse: string) => void
- error: (completedResponse: string, error: Error) => void
- },
- abortSignal: AbortSignal
- ): Promise {
- let lastContent = ''
- const typewriter = new Typewriter({
- update: content => {
- lastContent = content
- callbacks.update(content)
- },
- close: () => {
- callbacks.close(lastContent)
- },
- error: error => {
- callbacks.error(lastContent, error)
- },
- })
-
- try {
- const contextWindow = await firstResultFromOperation(
- ChatBuilder.contextWindowForChat(this.chatBuilder)
- )
-
- const params = {
- model,
- maxTokensToSample: contextWindow.output,
- } as CompletionParameters
-
- // Set stream param only when the model is disabled for streaming.
- if (model && modelsService.isStreamDisabled(model)) {
- params.stream = false
- }
-
- const stream = await this.chatClient.chat(prompt, params, abortSignal, requestID)
- for await (const message of stream) {
- switch (message.type) {
- case 'change': {
- typewriter.update(message.text)
- break
- }
- case 'complete': {
- typewriter.close()
- typewriter.stop()
- break
- }
- case 'error': {
- typewriter.close()
- typewriter.stop(message.error)
- }
- }
- }
- } catch (error: unknown) {
- typewriter.close()
- typewriter.stop(isAbortErrorOrSocketHangUp(error as Error) ? undefined : (error as Error))
- }
- }
-
/**
* Finalizes adding a bot message to the chat model and triggers an update to the view.
*/
@@ -2258,18 +1687,6 @@ export function manipulateWebviewHTML(html: string, options: TransformHTMLOption
return html
}
-// This is the manual ordering of the different retrieved and explicit context sources
-// It should be equivalent to the ordering of things in
-// ChatController:legacyComputeContext > context.ts:resolveContext
-function combineContext(
- explicitMentions: ContextItem[],
- openCtxContext: ContextItemOpenCtx[],
- priorityContext: ContextItem[],
- retrievedContext: ContextItem[]
-): ContextItem[] {
- return [explicitMentions, openCtxContext, priorityContext, retrievedContext].flat()
-}
-
async function joinModelWaitlist(): Promise {
await localStorage.setOrDeleteWaitlistO1(true)
telemetryRecorder.recordEvent('cody.joinLlmWaitlist', 'clicked')
diff --git a/vscode/src/chat/chat-view/handlers/ChatHandler.ts b/vscode/src/chat/chat-view/handlers/ChatHandler.ts
new file mode 100644
index 000000000000..6edbc146c15b
--- /dev/null
+++ b/vscode/src/chat/chat-view/handlers/ChatHandler.ts
@@ -0,0 +1,313 @@
+import type { Span } from '@opentelemetry/api'
+import {
+ type ChatModel,
+ type CompletionParameters,
+ type ContextItem,
+ type ContextItemOpenCtx,
+ ContextItemSource,
+ type Message,
+ PromptString,
+ type RankedContext,
+ type SerializedPromptEditorState,
+ Typewriter,
+ currentSiteVersion,
+ firstResultFromOperation,
+ getContextForChatMessage,
+ inputTextWithoutContextChipsFromPromptEditorState,
+ isAbortErrorOrSocketHangUp,
+ modelsService,
+ wrapInActiveSpan,
+} from '@sourcegraph/cody-shared'
+import { resolveContextItems } from '../../../editor/utils/editor-context'
+import { getCategorizedMentions } from '../../../prompt-builder/utils'
+import { ChatBuilder } from '../ChatBuilder'
+import type { ChatControllerOptions } from '../ChatController'
+import { type ContextRetriever, toStructuredMentions } from '../ContextRetriever'
+import { type HumanInput, getPriorityContext } from '../context'
+import { DefaultPrompter, type PromptInfo } from '../prompt'
+import type { AgentHandler, AgentHandlerDelegate, AgentRequest } from './interfaces'
+
+export class ChatHandler implements AgentHandler {
+ constructor(
+ protected modelId: string,
+ protected contextRetriever: Pick,
+ protected readonly editor: ChatControllerOptions['editor'],
+ protected chatClient: ChatControllerOptions['chatClient']
+ ) {}
+
+ public async handle(
+ {
+ requestID,
+ inputText,
+ mentions,
+ editorState,
+ signal,
+ chatBuilder,
+ recorder,
+ span,
+ }: AgentRequest,
+ delegate: AgentHandlerDelegate
+ ): Promise {
+ // All mentions we receive are either source=initial or source=user. If the caller
+ // forgot to set the source, assume it's from the user.
+ mentions = mentions.map(m => (m.source ? m : { ...m, source: ContextItemSource.User }))
+
+ const contextResult = await this.computeContext(
+ requestID,
+ { text: inputText, mentions },
+ editorState,
+ chatBuilder,
+ signal
+ )
+ if (contextResult.error) {
+ delegate.postError(contextResult.error, 'transcript')
+ }
+ if (contextResult.abort) {
+ delegate.postDone({ abort: contextResult.abort })
+ return
+ }
+ const corpusContext = contextResult.contextItems ?? []
+ signal.throwIfAborted()
+
+ const { explicitMentions, implicitMentions } = getCategorizedMentions(corpusContext)
+ const prompter = new DefaultPrompter(explicitMentions, implicitMentions, false)
+
+ const versions = await currentSiteVersion()
+ if (!versions) {
+ throw new Error('unable to determine site version')
+ }
+ const { prompt } = await this.buildPrompt(prompter, chatBuilder, signal, versions.codyAPIVersion)
+
+ recorder.recordChatQuestionExecuted(corpusContext, { addMetadata: true, current: span })
+
+ signal.throwIfAborted()
+ this.streamAssistantResponse(requestID, prompt, this.modelId, signal, chatBuilder, delegate)
+ }
+
+ /**
+ * Issue the chat request and stream the results back, updating the model and view
+ * with the response.
+ */
+ private async sendLLMRequest(
+ requestID: string,
+ prompt: Message[],
+ model: ChatModel,
+ chatBuilder: ChatBuilder,
+ callbacks: {
+ update: (response: string) => void
+ close: (finalResponse: string) => void
+ error: (completedResponse: string, error: Error) => void
+ },
+ abortSignal: AbortSignal
+ ): Promise {
+ let lastContent = ''
+ const typewriter = new Typewriter({
+ update: content => {
+ lastContent = content
+ callbacks.update(content)
+ },
+ close: () => {
+ callbacks.close(lastContent)
+ },
+ error: error => {
+ callbacks.error(lastContent, error)
+ },
+ })
+
+ try {
+ const contextWindow = await firstResultFromOperation(
+ ChatBuilder.contextWindowForChat(chatBuilder)
+ )
+
+ const params = {
+ model,
+ maxTokensToSample: contextWindow.output,
+ } as CompletionParameters
+
+ // Set stream param only when the model is disabled for streaming.
+ if (model && modelsService.isStreamDisabled(model)) {
+ params.stream = false
+ }
+
+ const stream = await this.chatClient.chat(prompt, params, abortSignal, requestID)
+ for await (const message of stream) {
+ switch (message.type) {
+ case 'change': {
+ typewriter.update(message.text)
+ break
+ }
+ case 'complete': {
+ typewriter.close()
+ typewriter.stop()
+ break
+ }
+ case 'error': {
+ typewriter.close()
+ typewriter.stop(message.error)
+ }
+ }
+ }
+ } catch (error: unknown) {
+ typewriter.close()
+ typewriter.stop(isAbortErrorOrSocketHangUp(error as Error) ? undefined : (error as Error))
+ }
+ }
+
+ private streamAssistantResponse(
+ requestID: string,
+ prompt: Message[],
+ model: ChatModel,
+ abortSignal: AbortSignal,
+ chatBuilder: ChatBuilder,
+ delegate: AgentHandlerDelegate
+ ): void {
+ abortSignal.throwIfAborted()
+ this.sendLLMRequest(
+ requestID,
+ prompt,
+ model,
+ chatBuilder,
+ {
+ update: content => {
+ delegate.postMessageInProgress({
+ speaker: 'assistant',
+ text: PromptString.unsafe_fromLLMResponse(content),
+ model: this.modelId,
+ })
+ },
+ close: content => {
+ delegate.postMessageInProgress({
+ speaker: 'assistant',
+ text: PromptString.unsafe_fromLLMResponse(content),
+ model: this.modelId,
+ })
+ delegate.postDone()
+ },
+ error: (partialResponse, error) => {
+ delegate.postError(error, 'transcript')
+ // We should still add the partial response if there was an error
+ // This'd throw an error if one has already been added
+ delegate.postMessageInProgress({
+ speaker: 'assistant',
+ text: PromptString.unsafe_fromLLMResponse(partialResponse),
+ model: this.modelId,
+ })
+ delegate.postDone()
+ if (isAbortErrorOrSocketHangUp(error)) {
+ abortSignal.throwIfAborted()
+ }
+ },
+ },
+ abortSignal
+ )
+ }
+
+ private async buildPrompt(
+ prompter: DefaultPrompter,
+ chatBuilder: ChatBuilder,
+ abortSignal: AbortSignal,
+ codyApiVersion: number
+ ): Promise {
+ const { prompt, context } = await prompter.makePrompt(chatBuilder, codyApiVersion)
+ abortSignal.throwIfAborted()
+
+ // Update UI based on prompt construction. Includes the excluded context items to display in the UI
+ chatBuilder.setLastMessageContext([...context.used, ...context.ignored])
+
+ return { prompt, context }
+ }
+
+ // Overridable by subclasses that want to customize context computation
+ protected async computeContext(
+ _requestID: string,
+ { text, mentions }: HumanInput,
+ editorState: SerializedPromptEditorState | null,
+ _chatBuilder: ChatBuilder,
+ signal?: AbortSignal
+ ): Promise<{
+ contextItems?: ContextItem[]
+ error?: Error
+ abort?: boolean
+ }> {
+ try {
+ return wrapInActiveSpan('chat.computeContext', async span => {
+ const contextAlternatives = await computeContextAlternatives(
+ this.contextRetriever,
+ this.editor,
+ { text, mentions },
+ editorState,
+ span,
+ signal
+ )
+ return { contextItems: contextAlternatives[0].items }
+ })
+ } catch (e) {
+ return { error: new Error(`Unexpected error computing context, no context was used: ${e}`) }
+ }
+ }
+}
+
+export async function computeContextAlternatives(
+ contextRetriever: Pick,
+ editor: ChatControllerOptions['editor'],
+ { text, mentions }: HumanInput,
+ editorState: SerializedPromptEditorState | null,
+ span: Span,
+ signal?: AbortSignal
+): Promise {
+ // Remove context chips (repo, @-mentions) from the input text for context retrieval.
+ const inputTextWithoutContextChips = editorState
+ ? PromptString.unsafe_fromUserQuery(
+ inputTextWithoutContextChipsFromPromptEditorState(editorState)
+ )
+ : text
+ const structuredMentions = toStructuredMentions(mentions)
+ const retrievedContextPromise = contextRetriever.retrieveContext(
+ structuredMentions,
+ inputTextWithoutContextChips,
+ span,
+ signal
+ )
+ const priorityContextPromise = retrievedContextPromise
+ .then(p => getPriorityContext(text, editor, p))
+ .catch(() => getPriorityContext(text, editor, []))
+ const openCtxContextPromise = getContextForChatMessage(text.toString(), signal)
+ const [priorityContext, retrievedContext, openCtxContext] = await Promise.all([
+ priorityContextPromise,
+ retrievedContextPromise.catch(e => {
+ throw new Error(`Failed to retrieve search context: ${e}`)
+ }),
+ openCtxContextPromise,
+ ])
+
+ const resolvedExplicitMentionsPromise = resolveContextItems(
+ editor,
+ [structuredMentions.symbols, structuredMentions.files, structuredMentions.openCtx].flat(),
+ text,
+ signal
+ )
+
+ return [
+ {
+ strategy: 'local+remote',
+ items: combineContext(
+ await resolvedExplicitMentionsPromise,
+ openCtxContext,
+ priorityContext,
+ retrievedContext
+ ),
+ },
+ ]
+}
+
+// This is the manual ordering of the different retrieved and explicit context sources
+// It should be equivalent to the ordering of things in
+// ChatController:legacyComputeContext > context.ts:resolveContext
+function combineContext(
+ explicitMentions: ContextItem[],
+ openCtxContext: ContextItemOpenCtx[],
+ priorityContext: ContextItem[],
+ retrievedContext: ContextItem[]
+): ContextItem[] {
+ return [explicitMentions, openCtxContext, priorityContext, retrievedContext].flat()
+}
diff --git a/vscode/src/chat/chat-view/handlers/DeepCodyHandler.ts b/vscode/src/chat/chat-view/handlers/DeepCodyHandler.ts
new file mode 100644
index 000000000000..ea7b3108723f
--- /dev/null
+++ b/vscode/src/chat/chat-view/handlers/DeepCodyHandler.ts
@@ -0,0 +1,78 @@
+import {
+ type ContextItem,
+ FeatureFlag,
+ type SerializedPromptEditorState,
+ featureFlagProvider,
+ storeLastValue,
+} from '@sourcegraph/cody-shared'
+import type { CodyToolProvider } from '../../agentic/CodyToolProvider'
+import { DeepCodyAgent } from '../../agentic/DeepCody'
+import { DeepCodyRateLimiter } from '../../agentic/DeepCodyRateLimiter'
+import type { ChatBuilder } from '../ChatBuilder'
+import type { ChatControllerOptions } from '../ChatController'
+import type { ContextRetriever } from '../ContextRetriever'
+import type { HumanInput } from '../context'
+import { ChatHandler } from './ChatHandler'
+import type { AgentHandler } from './interfaces'
+
+export class DeepCodyHandler extends ChatHandler implements AgentHandler {
+ constructor(
+ modelId: string,
+ contextRetriever: Pick,
+ editor: ChatControllerOptions['editor'],
+ chatClient: ChatControllerOptions['chatClient'],
+ private toolProvider: CodyToolProvider
+ ) {
+ super(modelId, contextRetriever, editor, chatClient)
+ }
+
+ private featureDeepCodyRateLimitBase = storeLastValue(
+ featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.DeepCodyRateLimitBase)
+ )
+ private featureDeepCodyRateLimitMultiplier = storeLastValue(
+ featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.DeepCodyRateLimitMultiplier)
+ )
+
+ override async computeContext(
+ requestID: string,
+ { text, mentions }: HumanInput,
+ editorState: SerializedPromptEditorState | null,
+ chatBuilder: ChatBuilder,
+ signal: AbortSignal
+ ): Promise<{
+ contextItems?: ContextItem[]
+ error?: Error
+ abort?: boolean
+ }> {
+ const baseContextResult = await super.computeContext(
+ requestID,
+ { text, mentions },
+ editorState,
+ chatBuilder,
+ signal
+ )
+ const isEnabled = chatBuilder.getMessages().length < 4
+ if (!isEnabled || baseContextResult.error || baseContextResult.abort) {
+ return baseContextResult
+ }
+ const deepCodyRateLimiter = new DeepCodyRateLimiter(
+ this.featureDeepCodyRateLimitBase.value.last ? 50 : 0,
+ this.featureDeepCodyRateLimitMultiplier.value.last ? 2 : 1
+ )
+
+ const deepCodyLimit = deepCodyRateLimiter.isAtLimit()
+ if (isEnabled && deepCodyLimit) {
+ return { error: deepCodyRateLimiter.getRateLimitError(deepCodyLimit), abort: true }
+ }
+
+ const baseContext = baseContextResult.contextItems ?? []
+ const codyAgent = new DeepCodyAgent(
+ chatBuilder,
+ this.chatClient,
+ this.toolProvider.getTools(),
+ baseContext
+ )
+ const agenticContext = await codyAgent.getContext(requestID, signal)
+ return { contextItems: [...baseContext, ...agenticContext] }
+ }
+}
diff --git a/vscode/src/chat/chat-view/handlers/EditHandler.ts b/vscode/src/chat/chat-view/handlers/EditHandler.ts
new file mode 100644
index 000000000000..64b3e6dfd3f9
--- /dev/null
+++ b/vscode/src/chat/chat-view/handlers/EditHandler.ts
@@ -0,0 +1,119 @@
+import {
+ DefaultEditCommands,
+ PromptString,
+ inputTextWithoutContextChipsFromPromptEditorState,
+} from '@sourcegraph/cody-shared'
+import { executeCodyCommand } from '../../../commands/CommandsController'
+import type { ChatControllerOptions } from '../ChatController'
+import type { ContextRetriever } from '../ContextRetriever'
+import { computeContextAlternatives } from './ChatHandler'
+import type { AgentHandler, AgentHandlerDelegate, AgentRequest } from './interfaces'
+
+export class EditHandler implements AgentHandler {
+ constructor(
+ private mode: 'edit' | 'insert',
+ private contextRetriever: Pick,
+ private readonly editor: ChatControllerOptions['editor']
+ ) {}
+
+ async handle(
+ {
+ requestID,
+ inputText,
+ mentions,
+ editorState,
+ span,
+ signal,
+ chatBuilder,
+ recorder,
+ }: AgentRequest,
+ delegate: AgentHandlerDelegate
+ ): Promise {
+ const contextAlternatives = await computeContextAlternatives(
+ this.contextRetriever,
+ this.editor,
+ { text: inputText, mentions },
+ editorState,
+ span,
+ signal
+ )
+ signal.throwIfAborted()
+ const context = contextAlternatives[0].items
+
+ chatBuilder.setLastMessageContext(context, contextAlternatives)
+
+ const inputTextWithoutContextChips = editorState
+ ? PromptString.unsafe_fromUserQuery(
+ inputTextWithoutContextChipsFromPromptEditorState(editorState)
+ )
+ : inputText
+
+ recorder.recordChatQuestionExecuted(context, { addMetadata: true, current: span })
+
+ const result = await executeCodyCommand(DefaultEditCommands.Edit, {
+ requestID,
+ runInChatMode: true,
+ userContextFiles: context,
+ configuration: {
+ instruction: inputTextWithoutContextChips,
+ mode: this.mode,
+ // Only document code uses non-edit (insert mode), set doc intent for Document code prompt
+ // to specialize cody command runner for document code case.
+ intent: this.mode === 'edit' ? 'edit' : 'doc',
+ },
+ })
+ if (result?.type !== 'edit' || !result.task) {
+ delegate.postError(new Error('Failed to execute edit command'), 'transcript')
+ delegate.postDone()
+ return
+ }
+
+ const task = result.task
+
+ let responseMessage = `Here is the response for the ${task.intent} instruction:\n`
+
+ if (!task.diff && task.replacement) {
+ task.diff = [
+ {
+ type: 'insertion',
+ text: task.replacement,
+ range: task.originalRange,
+ },
+ ]
+ }
+
+ task.diff?.map(diff => {
+ responseMessage += '\n```diff\n'
+ if (diff.type === 'deletion') {
+ responseMessage += task.document
+ .getText(diff.range)
+ .split('\n')
+ .map(line => `- ${line}`)
+ .join('\n')
+ }
+ if (diff.type === 'decoratedReplacement') {
+ responseMessage += diff.oldText
+ .split('\n')
+ .map(line => `- ${line}`)
+ .join('\n')
+ responseMessage += diff.text
+ .split('\n')
+ .map(line => `+ ${line}`)
+ .join('\n')
+ }
+ if (diff.type === 'insertion') {
+ responseMessage += diff.text
+ .split('\n')
+ .map(line => `+ ${line}`)
+ .join('\n')
+ }
+ responseMessage += '\n```'
+ })
+
+ delegate.postMessageInProgress({
+ speaker: 'assistant',
+ text: PromptString.unsafe_fromLLMResponse(responseMessage),
+ })
+ delegate.postDone()
+ }
+}
diff --git a/vscode/src/chat/chat-view/handlers/OmniboxTelemetry.ts b/vscode/src/chat/chat-view/handlers/OmniboxTelemetry.ts
new file mode 100644
index 000000000000..49795efe34ba
--- /dev/null
+++ b/vscode/src/chat/chat-view/handlers/OmniboxTelemetry.ts
@@ -0,0 +1,95 @@
+import type { Span } from '@opentelemetry/api'
+import {
+ type ChatMessage,
+ type ContextItem,
+ type TokenCounterUtils,
+ currentAuthStatusAuthed,
+ firstResultFromOperation,
+ getTokenCounterUtils,
+ logError,
+ telemetryEvents,
+ wrapInActiveSpan,
+} from '@sourcegraph/cody-shared'
+import type { SharedProperties } from '@sourcegraph/cody-shared/src/telemetry-v2/events/chat-question'
+import { publicRepoMetadataIfAllWorkspaceReposArePublic } from '../../../repository/githubRepoMetadata'
+
+interface IntentInfo {
+ userSpecifiedIntent: ChatMessage['intent'] | 'auto'
+ detectedIntent: ChatMessage['intent']
+ detectedIntentScores:
+ | {
+ intent: string
+ score: number
+ }[]
+ | null
+ | undefined
+}
+
+/**
+ * Utility class for encapsulating omnibox telemetry events
+ */
+export class OmniboxTelemetry {
+ private intentInfo?: IntentInfo
+ constructor(
+ private baseProperties: SharedProperties,
+ private tokenCounterUtils: TokenCounterUtils
+ ) {}
+
+ public static async create(
+ baseProperties: Omit
+ ): Promise {
+ const tokenCounterUtils = wrapInActiveSpan('chat.getTokenCounterUtils', () =>
+ getTokenCounterUtils()
+ )
+ const { isPublic: repoIsPublic, repoMetadata } = await wrapInActiveSpan(
+ 'chat.getRepoMetadata',
+ () => firstResultFromOperation(publicRepoMetadataIfAllWorkspaceReposArePublic)
+ )
+
+ return new OmniboxTelemetry(
+ {
+ ...baseProperties,
+ authStatus: currentAuthStatusAuthed(),
+ repoIsPublic,
+ repoMetadata,
+ },
+ await tokenCounterUtils
+ )
+ }
+
+ public recordChatQuestionSubmitted(mentions: ContextItem[]) {
+ telemetryEvents['cody.chat-question/submitted'].record(
+ { ...this.baseProperties, mentions },
+ this.tokenCounterUtils
+ )
+ }
+
+ public setIntentInfo(intentInfo: IntentInfo) {
+ this.intentInfo = intentInfo
+ }
+
+ public recordChatQuestionExecuted(
+ context: ContextItem[] | { used: ContextItem[]; ignored: ContextItem[] },
+ spans: {
+ current: Span
+ addMetadata: boolean
+ }
+ ) {
+ if (!this.intentInfo) {
+ logError(
+ 'AgentTelemetry',
+ 'failed to log cody.chat-question/executed beacuse intent info was not set'
+ )
+ return
+ }
+ telemetryEvents['cody.chat-question/executed'].record(
+ {
+ ...this.baseProperties,
+ ...this.intentInfo,
+ context,
+ },
+ spans,
+ this.tokenCounterUtils
+ )
+ }
+}
diff --git a/vscode/src/chat/chat-view/handlers/SearchHandler.ts b/vscode/src/chat/chat-view/handlers/SearchHandler.ts
new file mode 100644
index 000000000000..89d816a77bdf
--- /dev/null
+++ b/vscode/src/chat/chat-view/handlers/SearchHandler.ts
@@ -0,0 +1,162 @@
+import {
+ type ChatMessage,
+ type ChatMessageSearch,
+ type ContextItem,
+ type ContextItemFile,
+ type ContextItemOpenCtx,
+ type ContextItemRepository,
+ REMOTE_DIRECTORY_PROVIDER_URI,
+ REMOTE_FILE_PROVIDER_URI,
+ REMOTE_REPOSITORY_PROVIDER_URI,
+ errorToChatError,
+ graphqlClient,
+ inputTextWithoutContextChipsFromPromptEditorState,
+ ps,
+} from '@sourcegraph/cody-shared'
+import * as vscode from 'vscode'
+import { escapeRegExp } from '../../../context/openctx/remoteFileSearch'
+import { getEditor } from '../../../editor/active-editor'
+import { getFirstRepoNameContainingUri } from '../../../repository/repo-name-resolver'
+import type { AgentHandler, AgentHandlerDelegate, AgentRequest } from './interfaces'
+
+export class SearchHandler implements AgentHandler {
+ async handle(
+ { editorState, inputText, mentions, chatBuilder, signal }: AgentRequest,
+ delegate: AgentHandlerDelegate
+ ): Promise {
+ const inputTextWithoutContextChips = editorState
+ ? inputTextWithoutContextChipsFromPromptEditorState(editorState)
+ : inputText.toString()
+
+ signal.throwIfAborted()
+
+ chatBuilder.setLastMessageIntent('search')
+ const scopes: string[] = await getSearchScopesFromMentions(mentions)
+
+ const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri
+ const currentFile = getEditor()?.active?.document?.uri || workspaceRoot
+ const repoName = currentFile ? await getFirstRepoNameContainingUri(currentFile) : undefined
+
+ const boostParameter = repoName ? `boost:repo(${repoName})` : ''
+
+ const query = `content:"${inputTextWithoutContextChips.replaceAll(
+ '"',
+ '\\"'
+ )}" ${boostParameter} ${scopes.length ? `(${scopes.join(' OR ')})` : ''}`
+
+ try {
+ const response = await graphqlClient.nlsSearchQuery({
+ query,
+ signal,
+ })
+ const search: ChatMessageSearch = { query, response }
+ const message: ChatMessage = {
+ search,
+ speaker: 'assistant',
+ text: ps`Search found ${search?.response?.results.results.length || 0} results`,
+ }
+ delegate.postMessageInProgress(message)
+ } catch (err) {
+ const message: ChatMessage = {
+ speaker: 'assistant',
+ error:
+ err instanceof Error ? errorToChatError(err) : errorToChatError(new Error(`${err}`)),
+ }
+ delegate.postMessageInProgress(message)
+ } finally {
+ delegate.postDone()
+ }
+ }
+}
+
+async function getSearchScopesFromMentions(mentions: ContextItem[]): Promise {
+ const validMentions = mentions.reduce(
+ (groups, mention) => {
+ switch (mention.type) {
+ case 'repository':
+ groups.repository.push(mention)
+ break
+ case 'file':
+ groups[mention.type].push(mention)
+ break
+ case 'openctx':
+ if (mention.providerUri === REMOTE_REPOSITORY_PROVIDER_URI) {
+ groups.repository.push(mention)
+ } else {
+ groups.openctx.push(mention)
+ }
+ }
+
+ return groups
+ },
+ { repository: [], file: [], openctx: [] } as {
+ repository: (ContextItemRepository | ContextItemOpenCtx)[]
+ file: ContextItemFile[]
+ openctx: ContextItemOpenCtx[]
+ }
+ )
+
+ const scopes: string[] = []
+
+ // Convert all repo mentions to a single search filter.
+ // Example: repo:^(github\.com/sourcegraph/sourcegraph|github\.com/sourcegraph/cody)$
+ if (validMentions.repository.length > 0) {
+ const escapedRepoNames = validMentions.repository
+ .filter(({ repoName }) => !!repoName)
+ .map(({ repoName }) => escapeRegExp(repoName || ''))
+ .join('|')
+ scopes.push(`(repo:^(${escapedRepoNames})$)`)
+ }
+
+ // Convert all local file mentions to combination of file & repo filters.
+ // Example: (repo:a file:myfile)
+ await Promise.all(
+ validMentions.file.map(async mention => {
+ const repoName =
+ (mention as ContextItemFile).remoteRepositoryName ||
+ (await getFirstRepoNameContainingUri(mention.uri))
+
+ const workspace = vscode.workspace.getWorkspaceFolder(mention.uri)
+ if (!repoName || !workspace) {
+ return
+ }
+
+ const filePath = escapeRegExp(mention.uri.toString().split(`${workspace.name}/`)[1] || '')
+
+ if (!filePath || !repoName) {
+ return
+ }
+
+ return scopes.push(`(file:^${filePath}$ repo:^${repoName}$)`)
+ })
+ )
+
+ // Convert all remote file & directory mentions to combination of file & repo filters.
+ // Example: (repo:a file:mydir)
+ // biome-ignore lint/complexity/noForEach:
+ validMentions.openctx.forEach(mention => {
+ switch ((mention as ContextItemOpenCtx).providerUri) {
+ case REMOTE_FILE_PROVIDER_URI:
+ {
+ const filePath = escapeRegExp(mention.mention?.data?.filepath || '')
+ const repoName = escapeRegExp(mention.mention?.data?.reponame || '')
+ if (!filePath || !repoName) {
+ return
+ }
+ scopes.push(`(file:^${filePath}$ repo:^${repoName}$)`)
+ }
+ break
+ case REMOTE_DIRECTORY_PROVIDER_URI: {
+ const filePath = escapeRegExp(mention.mention?.data?.directoryPath || '')
+ const repoName = escapeRegExp(mention.mention?.data?.repoName || '')
+ if (!filePath || !repoName) {
+ return
+ }
+
+ scopes.push(`(file:^${filePath} repo:^${repoName}$)`)
+ }
+ }
+ })
+
+ return scopes
+}
diff --git a/vscode/src/chat/chat-view/handlers/interfaces.ts b/vscode/src/chat/chat-view/handlers/interfaces.ts
new file mode 100644
index 000000000000..eb797a45db21
--- /dev/null
+++ b/vscode/src/chat/chat-view/handlers/interfaces.ts
@@ -0,0 +1,44 @@
+import type { Span } from '@opentelemetry/api'
+import type {
+ ChatMessage,
+ ContextItem,
+ PromptString,
+ SerializedPromptEditorState,
+} from '@sourcegraph/cody-shared'
+import type { MessageErrorType } from '../../MessageProvider'
+import type { CodyToolProvider } from '../../agentic/CodyToolProvider'
+import type { ChatBuilder } from '../ChatBuilder'
+import type { ChatControllerOptions } from '../ChatController'
+import type { ContextRetriever } from '../ContextRetriever'
+import type { OmniboxTelemetry } from './OmniboxTelemetry'
+
+export interface AgentTools {
+ contextRetriever: Pick
+ editor: ChatControllerOptions['editor']
+ chatClient: ChatControllerOptions['chatClient']
+ codyToolProvider: CodyToolProvider
+}
+
+/**
+ * Interface for the agent to post messages back to the user
+ */
+export interface AgentHandlerDelegate {
+ postError(error: Error, type?: MessageErrorType): void
+ postMessageInProgress(message: ChatMessage): void
+ postDone(ops?: { abort: boolean }): void
+}
+
+export interface AgentRequest {
+ requestID: string
+ inputText: PromptString
+ mentions: ContextItem[]
+ editorState: SerializedPromptEditorState | null
+ chatBuilder: ChatBuilder
+ signal: AbortSignal
+ span: Span
+ recorder: OmniboxTelemetry
+}
+
+export interface AgentHandler {
+ handle(request: AgentRequest, delegate: AgentHandlerDelegate): Promise
+}
diff --git a/vscode/src/chat/chat-view/handlers/registry.ts b/vscode/src/chat/chat-view/handlers/registry.ts
new file mode 100644
index 000000000000..a9ce38348aad
--- /dev/null
+++ b/vscode/src/chat/chat-view/handlers/registry.ts
@@ -0,0 +1,41 @@
+import { ChatHandler } from './ChatHandler'
+import { DeepCodyHandler } from './DeepCodyHandler'
+import { EditHandler } from './EditHandler'
+import { SearchHandler } from './SearchHandler'
+import type { AgentHandler, AgentTools } from './interfaces'
+
+/**
+ * The agentRegistry registers agent handlers under IDs which can then be invoked
+ * at query time to retrieve the appropriate handler for a user request.
+ */
+const agentRegistry = new Map AgentHandler>()
+
+function registerAgent(id: string, ctr: (id: string, tools: AgentTools) => AgentHandler) {
+ agentRegistry.set(id, ctr)
+}
+
+export function getAgent(id: string, tools: AgentTools): AgentHandler {
+ if (!agentRegistry.has(id)) {
+ // If id is not found, assume it's a base model
+ const { contextRetriever, editor, chatClient } = tools
+ return new ChatHandler(id, contextRetriever, editor, chatClient)
+ }
+ return agentRegistry.get(id)!(id, tools)
+}
+
+registerAgent(
+ 'sourcegraph::2023-06-01::deep-cody',
+ (id: string, { contextRetriever, editor, chatClient, codyToolProvider }: AgentTools) =>
+ new DeepCodyHandler(id, contextRetriever, editor, chatClient, codyToolProvider)
+)
+registerAgent('search', (_id: string, _tools: AgentTools) => new SearchHandler())
+registerAgent(
+ 'edit',
+ (_id: string, { contextRetriever, editor }: AgentTools) =>
+ new EditHandler('edit', contextRetriever, editor)
+)
+registerAgent(
+ 'insert',
+ (_id: string, { contextRetriever, editor }: AgentTools) =>
+ new EditHandler('insert', contextRetriever, editor)
+)