@sourcegraph/cody-web 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +24 -0
  2. package/dist/demo/App.d.ts +4 -0
  3. package/dist/demo/App.d.ts.map +1 -0
  4. package/dist/demo/index.d.ts +2 -0
  5. package/dist/demo/index.d.ts.map +1 -0
  6. package/dist/index-BMP2aYCb.js +516 -0
  7. package/dist/index.js +143330 -0
  8. package/dist/lib/agent/agent.client.d.ts +19 -0
  9. package/dist/lib/agent/agent.client.d.ts.map +1 -0
  10. package/dist/lib/agent/agent.worker.d.ts +2 -0
  11. package/dist/lib/agent/agent.worker.d.ts.map +1 -0
  12. package/dist/lib/agent/index-db-storage.d.ts +16 -0
  13. package/dist/lib/agent/index-db-storage.d.ts.map +1 -0
  14. package/dist/lib/agent/shims/child_process.d.ts +4 -0
  15. package/dist/lib/agent/shims/child_process.d.ts.map +1 -0
  16. package/dist/lib/agent/shims/env-paths.d.ts +2 -0
  17. package/dist/lib/agent/shims/env-paths.d.ts.map +1 -0
  18. package/dist/lib/agent/shims/fs.d.ts +8 -0
  19. package/dist/lib/agent/shims/fs.d.ts.map +1 -0
  20. package/dist/lib/agent/shims/fs__promises.d.ts +12 -0
  21. package/dist/lib/agent/shims/fs__promises.d.ts.map +1 -0
  22. package/dist/lib/agent/shims/inline-completion-item-provider.d.ts +4 -0
  23. package/dist/lib/agent/shims/inline-completion-item-provider.d.ts.map +1 -0
  24. package/dist/lib/agent/shims/os.d.ts +8 -0
  25. package/dist/lib/agent/shims/os.d.ts.map +1 -0
  26. package/dist/lib/agent/shims/stream.d.ts +3 -0
  27. package/dist/lib/agent/shims/stream.d.ts.map +1 -0
  28. package/dist/lib/components/CodyWebChat.d.ts +7 -0
  29. package/dist/lib/components/CodyWebChat.d.ts.map +1 -0
  30. package/dist/lib/components/CodyWebChatProvider.d.ts +37 -0
  31. package/dist/lib/components/CodyWebChatProvider.d.ts.map +1 -0
  32. package/dist/lib/components/CodyWebHistory.d.ts +18 -0
  33. package/dist/lib/components/CodyWebHistory.d.ts.map +1 -0
  34. package/dist/lib/index.d.ts +5 -0
  35. package/dist/lib/index.d.ts.map +1 -0
  36. package/dist/lib/types.d.ts +9 -0
  37. package/dist/lib/types.d.ts.map +1 -0
  38. package/dist/lib/utils/use-local-storage.d.ts +14 -0
  39. package/dist/lib/utils/use-local-storage.d.ts.map +1 -0
  40. package/dist/style.css +3344 -0
  41. package/dist/tsconfig.tsbuildinfo +1 -0
  42. package/dist/util-CPyRplc_.js +24 -0
  43. package/package.json +46 -0
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # Cody standalone web app
2
+
3
+ **Status:** experimental (currently is used by Sourcegraph Web client)
4
+
5
+ The `@sourcegraph/cody-web` package implements a standalone web app/components for Cody Web.
6
+
7
+ To run demo standalone web app:
8
+ - Run `pnpm dev`
9
+ - Then open http://localhost:5777 and enter a Sourcegraph.com access token.
10
+
11
+ If the demo app doesn't load, it could be because there's an invalid token stored in local storage
12
+ or in your IndexDB.
13
+
14
+ To clear the token, open the browser dev tools and run `localStorage.removeItem('accessToken')`.
15
+ To clear tokens in IndexDB, open browser dev tools and go to applications tab and clear
16
+ IndexDB tables for http://localhost:5777 domain.
17
+
18
+ ## How to run within Sourcegraph client
19
+
20
+ - Build `@sourcegraph/cody-web` package by running `pnpm build`
21
+ - Register package local link with `pnpm link --global`
22
+ - Go to the Sourcegraph repository and create a link with `pnpm link @sourcegraph/cody-web --global`
23
+ - Run Sourcegraph `sg start` or `sg start web-standalone`
24
+
@@ -0,0 +1,4 @@
1
+ import type { FC } from 'react';
2
+ import '../../vscode/webviews/utils/highlight.css';
3
+ export declare const App: FC;
4
+ //# sourceMappingURL=App.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../demo/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAM/B,OAAO,2CAA2C,CAAA;AAyClD,eAAO,MAAM,GAAG,EAAE,EAwDjB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../demo/index.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,516 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => {
4
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+ import { U as Uri, P as Position, R as Range, w as window, D as DiagnosticSeverity, a as workspace, u as updateRangeMultipleChanges, c as commands, t as telemetryRecorder, e as executeEdit, p as ps, T as TERMINAL_EDIT_STATES, d as dedent, b as ThemeColor, l as languages, C as CodeLens, s as setTutorialUri, f as logSidebarClick, g as Disposable } from "./agent.worker-swWtwpQQ.js";
8
+ const EMOJI_SVG_TEMPLATE = `<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg">
9
+ <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="24px">{emoji}</text>
10
+ </svg>`;
11
+ const transformEmojiToSvg = (emoji) => {
12
+ const svg = EMOJI_SVG_TEMPLATE.replace("{emoji}", emoji);
13
+ const uri = "data:image/svg+xml;base64," + Buffer.from(svg).toString("base64");
14
+ return Uri.parse(uri);
15
+ };
16
+ function findRangeOfText(document, searchText) {
17
+ for (let line = 0; line < document.lineCount; line++) {
18
+ const lineText = document.lineAt(line);
19
+ const indexOfText = lineText.text.indexOf(searchText);
20
+ if (indexOfText >= 0) {
21
+ const start = new Position(line, indexOfText);
22
+ const end = new Position(line, indexOfText + searchText.length);
23
+ return new Range(start, end);
24
+ }
25
+ }
26
+ return null;
27
+ }
28
+ const TUTORIAL_EMOJIS = {
29
+ Todo: "&#128073;"
30
+ // 👉
31
+ };
32
+ const TODO_DECORATION = window.createTextEditorDecorationType({
33
+ gutterIconPath: transformEmojiToSvg(TUTORIAL_EMOJIS.Todo),
34
+ gutterIconSize: "contain"
35
+ });
36
+ const setFixDiagnostic = (collection, uri, range) => {
37
+ if (!collection || collection.has(uri)) {
38
+ return;
39
+ }
40
+ collection.set(uri, [
41
+ {
42
+ range,
43
+ message: "Python: Implicit string concatenation not allowed",
44
+ severity: DiagnosticSeverity.Error
45
+ }
46
+ ]);
47
+ };
48
+ const registerEditTutorialCommand = (editor, onComplete, range) => {
49
+ let trackedRange = range;
50
+ const rangeTracker = workspace.onDidChangeTextDocument((event) => {
51
+ if (event.document !== editor.document) {
52
+ return;
53
+ }
54
+ const changes = new Array(...event.contentChanges);
55
+ const updatedRange = updateRangeMultipleChanges(trackedRange, changes);
56
+ if (!updatedRange.isEqual(trackedRange)) {
57
+ trackedRange = updatedRange;
58
+ }
59
+ });
60
+ const editCommand = commands.registerCommand(
61
+ "cody.tutorial.edit",
62
+ async (_document, source = "editor") => {
63
+ telemetryRecorder.recordEvent("cody.interactiveTutorial", "edit", {
64
+ privateMetadata: { source }
65
+ });
66
+ editor.setDecorations(TODO_DECORATION, []);
67
+ const task = await executeEdit({
68
+ configuration: {
69
+ document: editor.document,
70
+ range: trackedRange,
71
+ preInstruction: ps`Function that finds logs in a dir`
72
+ }
73
+ });
74
+ if (!task) {
75
+ return;
76
+ }
77
+ const interval = setInterval(async () => {
78
+ if (TERMINAL_EDIT_STATES.includes(task.state)) {
79
+ clearInterval(interval);
80
+ onComplete();
81
+ }
82
+ }, 100);
83
+ }
84
+ );
85
+ return [rangeTracker, editCommand];
86
+ };
87
+ const registerChatTutorialCommand = (onComplete) => {
88
+ const disposable = commands.registerCommand(
89
+ "cody.tutorial.chat",
90
+ async (_document, source = "editor") => {
91
+ telemetryRecorder.recordEvent("cody.interactiveTutorial", "chat", {
92
+ privateMetadata: { source }
93
+ });
94
+ await commands.executeCommand("cody.chat.newEditorPanel");
95
+ onComplete();
96
+ }
97
+ );
98
+ return disposable;
99
+ };
100
+ const registerAutocompleteListener = (editor, activeStep) => {
101
+ const disposable = window.onDidChangeTextEditorSelection(async ({ textEditor }) => {
102
+ const document = textEditor.document;
103
+ if (document.uri !== editor.document.uri) {
104
+ return;
105
+ }
106
+ if (!textEditor.selection.isEmpty) {
107
+ return;
108
+ }
109
+ if (!activeStep || activeStep.type !== "onTextChange") {
110
+ return;
111
+ }
112
+ if (activeStep.range.contains(textEditor.selection.active) && document.getText(activeStep.range).trim() === activeStep.originalText) {
113
+ await commands.executeCommand("cody.autocomplete.manual-trigger");
114
+ }
115
+ });
116
+ return disposable;
117
+ };
118
+ var define_process_default = { env: {} };
119
+ const getStepContent = (step) => {
120
+ let stepContent = "";
121
+ switch (step) {
122
+ case "autocomplete":
123
+ stepContent = dedent`
124
+ ### Welcome to Cody!
125
+ """
126
+ Learn how to use Cody to write, edit and fix code by completing the 4 tasks below.
127
+ """
128
+
129
+ ### Task 1 of 4: Autocomplete
130
+ """
131
+ Place your cursor at the end of the following function and press tab to accept the Cody-powered autocomplete.
132
+ """
133
+ def greet(name, surname):
134
+ """Greets a user with a simple message"""
135
+
136
+ # ^ Autocomplete: Place cursor above
137
+ # When you see a suggestion, press Tab to accept or Opt+\ to generate another.
138
+ `;
139
+ break;
140
+ case "edit":
141
+ stepContent = dedent`
142
+ \n\n
143
+ ### Task 2 of 4: Edit Code with instructions
144
+ """
145
+ Place the cursor on the empty line below, and press Opt+K to open the Edit Code input.
146
+ We've pre-filled the instruction, all you need to do is choose Submit.
147
+ """
148
+
149
+ # ^ Start an Edit (Opt+K)
150
+ `;
151
+ break;
152
+ case "fix":
153
+ stepContent = dedent`
154
+ \n\n
155
+ ### Task 3 of 4: Ask Cody to Fix
156
+ """
157
+ The following code has a bug. Hover over the text with the error,
158
+ select "Quick Fix" and then "Ask Cody to Fix".
159
+ """
160
+ def log_fruits():
161
+ print("List of fruits:", "apple,", "banana,", "cherry")
162
+ # ^ Fix: Place cursor anywhere here, press Cmd+., and "Ask Cody to Fix"
163
+ `;
164
+ break;
165
+ case "chat":
166
+ stepContent = dedent`
167
+ \n\n
168
+ ### Task 4 of 4: Start a chat
169
+ #
170
+ # Start a Chat (Opt+L)
171
+ `;
172
+ }
173
+ return define_process_default.platform === "darwin" ? stepContent : stepContent.replace("Opt", "Alt").replace("Cmd", "Ctrl");
174
+ };
175
+ const getStepData = (document, step) => {
176
+ switch (step) {
177
+ case "autocomplete": {
178
+ const triggerText = findRangeOfText(document, "^ Autocomplete:");
179
+ if (!triggerText) {
180
+ return null;
181
+ }
182
+ const autocompleteRange = new Range(
183
+ new Position(triggerText.start.line - 1, 0),
184
+ new Position(triggerText.start.line - 1, Number.MAX_SAFE_INTEGER)
185
+ );
186
+ return {
187
+ key: "autocomplete",
188
+ range: autocompleteRange,
189
+ originalText: document.getText(autocompleteRange).trim(),
190
+ type: "onTextChange"
191
+ };
192
+ }
193
+ case "edit": {
194
+ const triggerText = findRangeOfText(document, "Start an Edit");
195
+ if (!triggerText) {
196
+ return null;
197
+ }
198
+ const editLine = triggerText.start.line - 1;
199
+ return {
200
+ key: "edit",
201
+ range: new Range(
202
+ new Position(editLine, 0),
203
+ new Position(editLine, Number.MAX_SAFE_INTEGER)
204
+ ),
205
+ type: "manual"
206
+ };
207
+ }
208
+ case "fix": {
209
+ const triggerText = findRangeOfText(document, "^ Fix:");
210
+ if (!triggerText) {
211
+ return null;
212
+ }
213
+ const fixLine = triggerText.start.line - 1;
214
+ const fixRange = new Range(
215
+ new Position(fixLine, document.lineAt(fixLine).firstNonWhitespaceCharacterIndex),
216
+ new Position(fixLine, Number.MAX_SAFE_INTEGER)
217
+ );
218
+ return {
219
+ key: "fix",
220
+ range: fixRange,
221
+ originalText: document.getText(fixRange).trim(),
222
+ type: "onTextChange"
223
+ };
224
+ }
225
+ case "chat": {
226
+ const triggerText = findRangeOfText(document, "Start a Chat");
227
+ if (!triggerText) {
228
+ return null;
229
+ }
230
+ const chatLine = triggerText.start.line;
231
+ return {
232
+ key: "chat",
233
+ range: new Range(
234
+ new Position(chatLine, 0),
235
+ new Position(chatLine, Number.MAX_SAFE_INTEGER)
236
+ ),
237
+ type: "manual"
238
+ };
239
+ }
240
+ }
241
+ };
242
+ const getNextStep = (step) => {
243
+ switch (step) {
244
+ case "autocomplete":
245
+ return "edit";
246
+ case "edit":
247
+ return "fix";
248
+ case "fix":
249
+ return "chat";
250
+ case "chat":
251
+ return null;
252
+ }
253
+ };
254
+ const initTutorialDocument = async (uri) => {
255
+ const firstStep = getStepContent("autocomplete");
256
+ await workspace.fs.writeFile(uri, Buffer.from(firstStep));
257
+ return workspace.openTextDocument(uri);
258
+ };
259
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
260
+ const resetDocument = async (uri) => {
261
+ await commands.executeCommand("workbench.action.closeActiveEditor", uri);
262
+ await sleep(250);
263
+ return initTutorialDocument(uri);
264
+ };
265
+ class TutorialLinkProvider {
266
+ constructor(editor) {
267
+ this.editor = editor;
268
+ }
269
+ provideDocumentLinks(document, token) {
270
+ if (document.uri.fsPath !== this.editor.document.uri.fsPath) {
271
+ return [];
272
+ }
273
+ const links = [];
274
+ const editRange = findRangeOfText(document, "Start an Edit");
275
+ if (editRange) {
276
+ const params = [document, "link"];
277
+ links.push(
278
+ new (void 0)(
279
+ editRange,
280
+ Uri.parse(
281
+ `command:cody.tutorial.edit?${encodeURIComponent(JSON.stringify(params))}`
282
+ )
283
+ )
284
+ );
285
+ }
286
+ const chatRange = findRangeOfText(document, "Start a Chat");
287
+ if (chatRange) {
288
+ const params = [document, "link"];
289
+ links.push(
290
+ new (void 0)(
291
+ chatRange,
292
+ Uri.parse(
293
+ `command:cody.tutorial.chat?${encodeURIComponent(JSON.stringify(params))}`
294
+ )
295
+ )
296
+ );
297
+ }
298
+ const linkDecoration = window.createTextEditorDecorationType({
299
+ color: new ThemeColor("textLink.activeForeground")
300
+ });
301
+ this.editor.setDecorations(linkDecoration, links);
302
+ return links;
303
+ }
304
+ }
305
+ class ResetLensProvider {
306
+ constructor(editor) {
307
+ __publicField(this, "disposables", []);
308
+ this.editor = editor;
309
+ this.disposables.push(languages.registerCodeLensProvider(editor.document.uri, this));
310
+ }
311
+ provideCodeLenses(document) {
312
+ return [
313
+ new CodeLens(new Range(0, 0, 0, 0), {
314
+ title: "Reset Tutorial",
315
+ command: "cody.tutorial.reset"
316
+ })
317
+ ];
318
+ }
319
+ dispose() {
320
+ for (const disposable of this.disposables) {
321
+ disposable.dispose();
322
+ }
323
+ this.disposables = [];
324
+ }
325
+ }
326
+ const startTutorial = async (document) => {
327
+ const disposables = [];
328
+ const editor = await window.showTextDocument(document);
329
+ const diagnosticCollection = languages.createDiagnosticCollection("codyTutorial");
330
+ disposables.push(diagnosticCollection);
331
+ telemetryRecorder.recordEvent("cody.interactiveTutorial", "started");
332
+ let activeStep = null;
333
+ let activeRangeListener;
334
+ let successListener;
335
+ const setActiveRangeListener = (range) => {
336
+ activeRangeListener == null ? void 0 : activeRangeListener.dispose();
337
+ activeRangeListener = workspace.onDidChangeTextDocument((event) => {
338
+ if (event.document.uri !== editor.document.uri) {
339
+ return;
340
+ }
341
+ if (!activeStep) {
342
+ return;
343
+ }
344
+ const changes = new Array(...event.contentChanges);
345
+ const newInteractiveRange = updateRangeMultipleChanges(range, changes);
346
+ if (!newInteractiveRange.isEqual(range)) {
347
+ activeStep.range = newInteractiveRange;
348
+ }
349
+ });
350
+ return activeRangeListener;
351
+ };
352
+ const progressToNextStep = async () => {
353
+ const nextStep = (activeStep == null ? void 0 : activeStep.key) ? getNextStep(activeStep.key) : "autocomplete";
354
+ if (activeStep == null ? void 0 : activeStep.key) {
355
+ telemetryRecorder.recordEvent("cody.interactiveTutorial.stepComplete", activeStep.key);
356
+ }
357
+ if (nextStep === null) {
358
+ editor.setDecorations(TODO_DECORATION, []);
359
+ telemetryRecorder.recordEvent("cody.interactiveTutorial", "finished");
360
+ return;
361
+ }
362
+ switch (activeStep == null ? void 0 : activeStep.key) {
363
+ case "autocomplete":
364
+ break;
365
+ case "fix":
366
+ diagnosticCollection == null ? void 0 : diagnosticCollection.clear();
367
+ break;
368
+ }
369
+ activeRangeListener == null ? void 0 : activeRangeListener.dispose();
370
+ editor.setDecorations(TODO_DECORATION, []);
371
+ const needsInsertion = nextStep !== "autocomplete";
372
+ if (needsInsertion) {
373
+ const content = getStepContent(nextStep);
374
+ await editor.edit((editBuilder) => {
375
+ editBuilder.insert(new Position(editor.document.lineCount, 0), content);
376
+ });
377
+ }
378
+ editor.document.save();
379
+ activeStep = getStepData(editor.document, nextStep);
380
+ if (!activeStep) {
381
+ return;
382
+ }
383
+ disposables.push(startListeningForSuccess(nextStep), setActiveRangeListener(activeStep.range));
384
+ editor.setDecorations(TODO_DECORATION, [activeStep.range]);
385
+ switch (nextStep) {
386
+ case "autocomplete":
387
+ disposables.push(registerAutocompleteListener(editor, activeStep));
388
+ break;
389
+ case "fix":
390
+ setFixDiagnostic(diagnosticCollection, editor.document.uri, activeStep.range);
391
+ break;
392
+ case "edit":
393
+ disposables.push(
394
+ ...registerEditTutorialCommand(editor, progressToNextStep, activeStep.range)
395
+ );
396
+ break;
397
+ case "chat":
398
+ disposables.push(registerChatTutorialCommand(progressToNextStep));
399
+ break;
400
+ }
401
+ };
402
+ const startListeningForSuccess = (key) => {
403
+ successListener == null ? void 0 : successListener.dispose();
404
+ successListener = workspace.onDidChangeTextDocument(async ({ document: document2 }) => {
405
+ if (document2.uri !== editor.document.uri) {
406
+ return;
407
+ }
408
+ if ((activeStep == null ? void 0 : activeStep.key) !== key || activeStep.type !== "onTextChange") {
409
+ return;
410
+ }
411
+ const activeText = editor.document.getText(activeStep.range).trim();
412
+ if (activeText.length > 0 && activeText !== activeStep.originalText) {
413
+ if (key === "fix") {
414
+ diagnosticCollection.clear();
415
+ }
416
+ successListener == null ? void 0 : successListener.dispose();
417
+ progressToNextStep();
418
+ }
419
+ });
420
+ return successListener;
421
+ };
422
+ progressToNextStep();
423
+ disposables.push(
424
+ startListeningForSuccess("autocomplete"),
425
+ new ResetLensProvider(editor),
426
+ languages.registerDocumentLinkProvider(
427
+ editor.document.uri,
428
+ new TutorialLinkProvider(editor)
429
+ ),
430
+ window.onDidChangeVisibleTextEditors((editors) => {
431
+ const tutorialIsActive = editors.find(
432
+ (editor2) => editor2.document.uri.toString() === document.uri.toString()
433
+ );
434
+ if (!tutorialIsActive || !(activeStep == null ? void 0 : activeStep.range)) {
435
+ return;
436
+ }
437
+ editor.setDecorations(TODO_DECORATION, [activeStep.range]);
438
+ })
439
+ );
440
+ return new Disposable(() => {
441
+ for (const disposable of disposables) {
442
+ disposable.dispose();
443
+ }
444
+ return initTutorialDocument(document.uri);
445
+ });
446
+ };
447
+ const registerInteractiveTutorial = async (context) => {
448
+ const disposables = [];
449
+ const documentUri = setTutorialUri(context);
450
+ let document = await initTutorialDocument(documentUri);
451
+ let status = "stopped";
452
+ let cleanup;
453
+ const start = async () => {
454
+ status = "starting";
455
+ cleanup = await startTutorial(document);
456
+ disposables.push(cleanup);
457
+ status = "started";
458
+ };
459
+ const stop = async () => {
460
+ cleanup == null ? void 0 : cleanup.dispose();
461
+ status = "stopped";
462
+ };
463
+ disposables.push(
464
+ window.onDidChangeVisibleTextEditors((editors) => {
465
+ const tutorialIsVisible = editors.find(
466
+ (editor) => editor.document.uri.toString() === documentUri.toString()
467
+ );
468
+ if (status === "starting") {
469
+ return;
470
+ }
471
+ if (status === "started" && !tutorialIsVisible) {
472
+ return stop();
473
+ }
474
+ if (status === "stopped" && tutorialIsVisible) {
475
+ return start();
476
+ }
477
+ return;
478
+ }),
479
+ window.onDidChangeActiveTextEditor(async (editor) => {
480
+ const tutorialIsActive = editor && editor.document.uri.toString() === documentUri.toString();
481
+ return commands.executeCommand("setContext", "cody.tutorialActive", tutorialIsActive);
482
+ }),
483
+ workspace.onDidCloseTextDocument((document2) => {
484
+ if (document2.uri !== documentUri) {
485
+ return;
486
+ }
487
+ telemetryRecorder.recordEvent("cody.interactiveTutorial", "closed");
488
+ }),
489
+ commands.registerCommand("cody.tutorial.start", async () => {
490
+ if (status === "started") {
491
+ return window.showTextDocument(documentUri);
492
+ }
493
+ return start();
494
+ }),
495
+ commands.registerCommand("cody.tutorial.reset", async () => {
496
+ telemetryRecorder.recordEvent("cody.interactiveTutorial", "reset");
497
+ stop();
498
+ document = await resetDocument(documentUri);
499
+ return start();
500
+ }),
501
+ commands.registerCommand("cody.sidebar.tutorial", () => {
502
+ logSidebarClick("tutorial");
503
+ void commands.executeCommand("cody.tutorial.start");
504
+ })
505
+ );
506
+ const tutorialVisible = window.visibleTextEditors.some(
507
+ (editor) => editor.document.uri.toString() === documentUri.toString()
508
+ );
509
+ if (tutorialVisible) {
510
+ await start();
511
+ }
512
+ return disposables;
513
+ };
514
+ export {
515
+ registerInteractiveTutorial
516
+ };