Skip to content

Commit aa77908

Browse files
author
Calvinn Ng
committed
re-add feature: export chat history to Markdown
1 parent 53290c0 commit aa77908

File tree

5 files changed

+173
-120
lines changed

5 files changed

+173
-120
lines changed

core/protocol/ideWebview.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ContextSubmenuItem } from "..";
1+
import type { ChatHistory, ContextSubmenuItem } from "..";
22
import type { RangeInFileWithContents } from "../commands/util";
33
import { ToIdeFromWebviewOrCoreProtocol } from "./ide.js";
44
import { ToWebviewFromIdeOrCoreProtocol } from "./webview.js";
@@ -27,6 +27,7 @@ export type ToIdeFromWebviewProtocol = ToIdeFromWebviewOrCoreProtocol & {
2727
copyText: [{ text: string }, void];
2828
"jetbrains/editorInsetHeight": [{ height: number }, void];
2929
setGitHubAuthToken: [{ token: string }, void];
30+
saveSessionChatHistory: [ { chatHistory: ChatHistory, defaultTitle: string }, void];
3031
};
3132

3233
export type ToWebviewFromIdeProtocol = ToWebviewFromIdeOrCoreProtocol & {
@@ -60,4 +61,5 @@ export type ToWebviewFromIdeProtocol = ToWebviewFromIdeOrCoreProtocol & {
6061
setupLocalModel: [undefined, void];
6162
incrementFtc: [undefined, void];
6263
openOnboarding: [undefined, void];
64+
sendSessionChatHistory: [undefined, void]
6365
};

extensions/vscode/package.json

Lines changed: 66 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "ahrefs-continue",
33
"icon": "media/a_ahrefs_logo.png",
4-
"version": "1.1.14",
4+
"version": "1.1.17",
55
"repository": {
66
"type": "git",
77
"url": "https://github.com/ahrefs/ahrefs-continue"
@@ -66,17 +66,17 @@
6666
}
6767
],
6868
"configuration": {
69-
"title": "Continue",
69+
"title": "Ahrefs-Continue",
7070
"properties": {
7171
"ahrefs-continue.telemetryEnabled": {
7272
"type": "boolean",
7373
"default": true,
74-
"markdownDescription": "Continue collects anonymous usage data, cleaned of PII, to help us improve the product for our users."
74+
"markdownDescription": "Ahrefs-Continue collects anonymous usage data, cleaned of PII, to help us improve the product for our users."
7575
},
7676
"ahrefs-continue.showInlineTip": {
7777
"type": "boolean",
7878
"default": true,
79-
"description": "Show inline suggestion to use the Continue keyboard shortcuts (e.g. \"Cmd/Ctrl L to select code, Cmd/Ctrl I to edit\")."
79+
"description": "Show inline suggestion to use the Ahrefs-Continue keyboard shortcuts (e.g. \"Cmd/Ctrl L to select code, Cmd/Ctrl I to edit\")."
8080
},
8181
"ahrefs-continue.enableQuickActions": {
8282
"type": "boolean",
@@ -86,12 +86,12 @@
8686
"ahrefs-continue.enableTabAutocomplete": {
8787
"type": "boolean",
8888
"default": true,
89-
"markdownDescription": "Enable Continue's tab autocomplete feature."
89+
"markdownDescription": "Enable Ahrefs-Continue's tab autocomplete feature."
9090
},
9191
"ahrefs-continue.pauseTabAutocompleteOnBattery": {
9292
"type": "boolean",
9393
"default": false,
94-
"markdownDescription": "Pause Continue's tab autocomplete feature when your battery is low."
94+
"markdownDescription": "Pause Ahrefs-Continue's tab autocomplete feature when your battery is low."
9595
},
9696
"ahrefs-continue.remoteConfigServerUrl": {
9797
"type": "string",
@@ -113,133 +113,139 @@
113113
"commands": [
114114
{
115115
"command": "ahrefs-continue.acceptDiff",
116-
"category": "Continue",
116+
"category": "Ahrefs-Continue",
117117
"title": "Accept Diff",
118-
"group": "Continue"
118+
"group": "Ahrefs-Continue"
119119
},
120120
{
121121
"command": "ahrefs-continue.rejectDiff",
122-
"category": "Continue",
122+
"category": "Ahrefs-Continue",
123123
"title": "Reject Diff",
124-
"group": "Continue",
124+
"group": "Ahrefs-Continue",
125125
"icon": "$(stop)"
126126
},
127127
{
128128
"command": "ahrefs-continue.acceptVerticalDiffBlock",
129-
"category": "Continue",
129+
"category": "Ahrefs-Continue",
130130
"title": "Accept Vertical Diff Block",
131-
"group": "Continue"
131+
"group": "Ahrefs-Continue"
132132
},
133133
{
134134
"command": "ahrefs-continue.rejectVerticalDiffBlock",
135-
"category": "Continue",
135+
"category": "Ahrefs-Continue",
136136
"title": "Reject Vertical Diff Block",
137-
"group": "Continue"
137+
"group": "Ahrefs-Continue"
138138
},
139139
{
140140
"command": "ahrefs-continue.quickEdit",
141-
"category": "Continue",
141+
"category": "Ahrefs-Continue",
142142
"title": "Generate Code",
143-
"group": "Continue"
143+
"group": "Ahrefs-Continue"
144144
},
145145
{
146146
"command": "ahrefs-continue.focusContinueInput",
147-
"category": "Continue",
147+
"category": "Ahrefs-Continue",
148148
"title": "Add Highlighted Code to Context",
149-
"group": "Continue"
149+
"group": "Ahrefs-Continue"
150150
},
151151
{
152152
"command": "ahrefs-continue.focusContinueInputWithoutClear",
153-
"category": "Continue",
153+
"category": "Ahrefs-Continue",
154154
"title": "Add Highlighted Code to Context",
155-
"group": "Continue"
155+
"group": "Ahrefs-Continue"
156156
},
157157
{
158158
"command": "ahrefs-continue.debugTerminal",
159-
"category": "Continue",
160-
"title": "Continue: Debug Terminal",
161-
"group": "Continue"
159+
"category": "Ahrefs-Continue",
160+
"title": "Ahrefs-Continue: Debug Terminal",
161+
"group": "Ahrefs-Continue"
162162
},
163163
{
164164
"command": "ahrefs-continue.toggleFullScreen",
165-
"category": "Continue",
165+
"category": "Ahrefs-Continue",
166166
"title": "Toggle Full Screen",
167167
"icon": "$(fullscreen)",
168-
"group": "Continue"
168+
"group": "Ahrefs-Continue"
169169
},
170170
{
171171
"command": "ahrefs-continue.openConfigJson",
172-
"category": "Continue",
172+
"category": "Ahrefs-Continue",
173173
"title": "Open config.json",
174-
"group": "Continue"
174+
"group": "Ahrefs-Continue"
175175
},
176176
{
177177
"command": "ahrefs-continue.toggleTabAutocompleteEnabled",
178-
"category": "Continue",
178+
"category": "Ahrefs-Continue",
179179
"title": "Toggle Autocomplete Enabled",
180-
"group": "Continue"
180+
"group": "Ahrefs-Continue"
181181
},
182182
{
183183
"command": "ahrefs-continue.selectFilesAsContext",
184-
"category": "Continue",
185-
"title": "Continue: Select Files as Context",
186-
"group": "Continue"
184+
"category": "Ahrefs-Continue",
185+
"title": "Ahrefs-Continue: Select Files as Context",
186+
"group": "Ahrefs-Continue"
187187
},
188188
{
189189
"command": "ahrefs-continue.newSession",
190-
"category": "Continue",
190+
"category": "Ahrefs-Continue",
191191
"title": "New Session",
192192
"icon": "$(add)",
193-
"group": "Continue"
193+
"group": "Ahrefs-Continue"
194194
},
195195
{
196196
"command": "ahrefs-continue.viewHistory",
197-
"category": "Continue",
197+
"category": "Ahrefs-Continue",
198198
"title": "View History",
199199
"icon": "$(history)",
200-
"group": "Continue"
200+
"group": "Ahrefs-Continue"
201201
},
202202
{
203203
"command": "ahrefs-continue.writeCommentsForCode",
204-
"category": "Continue",
204+
"category": "Ahrefs-Continue",
205205
"title": "Write Comments for this Code",
206-
"group": "Continue"
206+
"group": "Ahrefs-Continue"
207207
},
208208
{
209209
"command": "ahrefs-continue.writeDocstringForCode",
210-
"category": "Continue",
210+
"category": "Ahrefs-Continue",
211211
"title": "Write a Docstring for this Code",
212-
"group": "Continue"
212+
"group": "Ahrefs-Continue"
213213
},
214214
{
215215
"command": "ahrefs-continue.fixCode",
216-
"category": "Continue",
216+
"category": "Ahrefs-Continue",
217217
"title": "Fix this Code",
218-
"group": "Continue"
218+
"group": "Ahrefs-Continue"
219219
},
220220
{
221221
"command": "ahrefs-continue.optimizeCode",
222-
"category": "Continue",
222+
"category": "Ahrefs-Continue",
223223
"title": "Optimize this Code",
224-
"group": "Continue"
224+
"group": "Ahrefs-Continue"
225225
},
226226
{
227227
"command": "ahrefs-continue.fixGrammar",
228-
"category": "Continue",
228+
"category": "Ahrefs-Continue",
229229
"title": "Fix Grammar / Spelling",
230-
"group": "Continue"
230+
"group": "Ahrefs-Continue"
231231
},
232232
{
233233
"command": "ahrefs-continue.docsIndex",
234-
"category": "Continue",
234+
"category": "Ahrefs-Continue",
235235
"title": "Docs Index",
236-
"group": "Continue"
236+
"group": "Ahrefs-Continue"
237237
},
238238
{
239239
"command": "ahrefs-continue.docsReIndex",
240-
"category": "Continue",
240+
"category": "Ahrefs-Continue",
241241
"title": "Docs Force Re-Index",
242-
"group": "Continue"
242+
"group": "Ahrefs-Continue"
243+
},
244+
{
245+
"command": "ahrefs-continue.saveChatSession",
246+
"category": "Ahrefs-Continue",
247+
"title": "Save Chat Session",
248+
"group": "Ahrefs-Continue"
243249
}
244250
],
245251
"keybindings": [
@@ -322,7 +328,7 @@
322328
"submenus": [
323329
{
324330
"id": "ahrefs-continue.ahrefs-continueSubMenu",
325-
"label": "Continue"
331+
"label": "Ahrefs-Continue"
326332
}
327333
],
328334
"menus": {
@@ -433,7 +439,7 @@
433439
{
434440
"id": "ahrefs-continue",
435441
"title": "Ahrefs-Continue",
436-
"icon": "media/sidebar-icon.png"
442+
"icon": "media/a_ahrefs_square_bw_transparent_bg.png"
437443
}
438444
]
439445
},
@@ -451,12 +457,12 @@
451457
{
452458
"id": "ahrefs-continue",
453459
"title": "Getting Started",
454-
"description": "Learn how to use Continue",
460+
"description": "Learn how to use Ahrefs-Continue",
455461
"steps": [
456462
{
457463
"id": "edit",
458464
"title": "Edit in natural language",
459-
"description": "Highlight a section of code and instruct Continue to refactor it (e.g. `/edit rewrite this function to be async`)",
465+
"description": "Highlight a section of code and instruct Ahrefs-Continue to refactor it (e.g. `/edit rewrite this function to be async`)",
460466
"media": {
461467
"image": "media/edit.png",
462468
"altText": "Empty image"
@@ -466,7 +472,7 @@
466472
{
467473
"id": "explain",
468474
"title": "Get possible explanations",
469-
"description": "Ask Continue about a part of your code to get another perspective (e.g. `where in the page should I be making this request to the backend?`)",
475+
"description": "Ask Ahrefs-Continue about a part of your code to get another perspective (e.g. `where in the page should I be making this request to the backend?`)",
470476
"media": {
471477
"image": "media/explain.png",
472478
"altText": "Empty image"
@@ -476,7 +482,7 @@
476482
{
477483
"id": "generate",
478484
"title": "Generate files from scratch",
479-
"description": "Let Continue build the scaffolding of Python scripts, React components, and more (e.g. `/edit here is a connector for postgres, now write one for kafka`)",
485+
"description": "Let Ahrefs-Continue build the scaffolding of Python scripts, React components, and more (e.g. `/edit here is a connector for postgres, now write one for kafka`)",
480486
"media": {
481487
"image": "media/generate.png",
482488
"altText": "Empty image"
@@ -521,6 +527,7 @@
521527
"@biomejs/biome": "1.6.4",
522528
"@nestjs/common": "^8.4.7",
523529
"@openapitools/openapi-generator-cli": "^2.5.2",
530+
"@types/fast-levenshtein": "^0.0.4",
524531
"@types/cors": "^2.8.17",
525532
"@types/express": "^4.17.21",
526533
"@types/follow-redirects": "^1.14.4",
@@ -535,7 +542,6 @@
535542
"@typescript-eslint/parser": "^5.45.0",
536543
"@vscode/vsce": "^2.22.0",
537544
"cargo-cp-artifact": "^0.1",
538-
"esbuild": "0.17.19",
539545
"eslint": "^8.28.0",
540546
"glob": "^8.0.3",
541547
"json-schema-to-typescript": "^12.0.0",
@@ -550,6 +556,7 @@
550556
"@electron/rebuild": "^3.2.10",
551557
"@reduxjs/toolkit": "^1.9.3",
552558
"@types/node-fetch": "^2.6.11",
559+
"@types/fast-levenshtein": "^0.0.4",
553560
"@types/uuid": "^9.0.8",
554561
"@vscode/ripgrep": "^1.15.9",
555562
"@vscode/test-electron": "^2.3.9",
@@ -560,6 +567,7 @@
560567
"downshift": "^7.6.0",
561568
"esbuild": "^0.17.19",
562569
"express": "^4.18.2",
570+
"fast-levenshtein": "^3.0.0",
563571
"fkill": "^8.1.0",
564572
"follow-redirects": "^1.15.4",
565573
"handlebars": "^4.7.8",
@@ -594,4 +602,4 @@
594602
"ws": "^8.13.0",
595603
"yarn": "^1.22.21"
596604
}
597-
}
605+
}

extensions/vscode/src/extension/VsCodeMessenger.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
ToCoreOrIdeFromWebviewProtocol,
2020
VsCodeWebviewProtocol,
2121
} from "../webviewProtocol";
22+
import { stripImages } from "../../../../core/llm/countTokens";
2223

2324
/**
2425
* A shared messenger class between Core and Webview
@@ -118,6 +119,36 @@ export class VsCodeMessenger {
118119
msg.data.stepIndex,
119120
);
120121
});
122+
this.onWebview("saveSessionChatHistory", async (msg) => {
123+
const datetime = new Date();
124+
const year = datetime.getFullYear();
125+
const month = String(datetime.getMonth() + 1).padStart(2, '0');
126+
const day = String(datetime.getDate()).padStart(2, '0');
127+
const hours = String(datetime.getHours()).padStart(2, '0');
128+
const minutes = String(datetime.getMinutes()).padStart(2, '0');
129+
const seconds = String(datetime.getSeconds()).padStart(2, '0');
130+
131+
const datetime_filename = `${year}${month}${day}_${hours}${minutes}${seconds}`;
132+
133+
let content = `This is a session transcript from Ahrefs-Continue on ${datetime.toLocaleString()}.`;
134+
135+
for (const m of msg.data.chatHistory) {
136+
content += `\n\n## ${
137+
m.message.role === "user" ? "User" : `Ahrefs-Continue: ${msg.data.defaultTitle}`
138+
}\n\n${stripImages(m.message.content)}`;
139+
}
140+
141+
const continueDir = await ide.getContinueDir();
142+
const savedSessionsPath = `${continueDir}/saved_sessions`
143+
if (!fs.existsSync(savedSessionsPath)) {
144+
fs.mkdirSync(savedSessionsPath);
145+
}
146+
const path = `${savedSessionsPath}/${datetime_filename}_session.md`;
147+
await ide.writeFile(path, content);
148+
await ide.openFile(path);
149+
150+
vscode.window.showInformationMessage(`Chat session saved to ${path}`);
151+
})
121152

122153
this.onWebview("applyToCurrentFile", async (msg) => {
123154
// Select the entire current file

gui/src/hooks/useNavigationListener.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const openGUITypes: (keyof ToWebviewProtocol)[] = [
99
"focusContinueInput",
1010
"focusContinueInputWithoutClear",
1111
"newSession",
12+
"sendSessionChatHistory"
1213
];
1314

1415
export const useNavigationListener = () => {

0 commit comments

Comments
 (0)