diff --git a/lib/shared/src/codebase-context/messages.ts b/lib/shared/src/codebase-context/messages.ts index 7bea5ccb05..e91c7a3382 100644 --- a/lib/shared/src/codebase-context/messages.ts +++ b/lib/shared/src/codebase-context/messages.ts @@ -97,7 +97,7 @@ export enum ContextItemSource { /** * An item (such as a file or symbol) that is included as context in a chat message. */ -export type ContextItem = ContextItemFile | ContextItemSymbol | ContextItemPackage +export type ContextItem = ContextItemFile | ContextItemSymbol | ContextItemPackage | ContextItemHistory /** * A file (or a subset of a file given by a range) that is included as context in a chat message. @@ -147,6 +147,19 @@ export interface ContextItemSymbol extends ContextItemCommon { /** The valid kinds of a symbol. */ export type SymbolKind = 'class' | 'function' | 'method' +/** + * The output of source control history for a file. + * + * Note: Currently this is only used for the "Explain History" action which runs + * on a symbol. + */ +export interface ContextItemHistory extends ContextItemCommon { + type: 'history' + + /** The symbol name we asked history for, used for presentation only (not semantically meaningful). */ + symbolName: string +} + /** {@link ContextItem} with the `content` field set to the content. */ export type ContextItemWithContent = ContextItem & Required> diff --git a/lib/shared/src/index.ts b/lib/shared/src/index.ts index 12b3d32ca2..b1307e28e8 100644 --- a/lib/shared/src/index.ts +++ b/lib/shared/src/index.ts @@ -52,6 +52,7 @@ export type { export { type ContextItem, type ContextItemFile, + type ContextItemHistory, ContextItemSource, type ContextItemWithContent, type ContextItemSymbol, diff --git a/vscode/src/commands/context/git-log.ts b/vscode/src/commands/context/git-log.ts index aa95b9ed6c..32ada1c20b 100644 --- a/vscode/src/commands/context/git-log.ts +++ b/vscode/src/commands/context/git-log.ts @@ -2,11 +2,11 @@ import { type SpawnOptionsWithoutStdio, spawn } from 'node:child_process' import path from 'node:path' import { type ContextItem, + type ContextItemHistory, ContextItemSource, type FileURI, wrapInActiveSpan, } from '@sourcegraph/cody-shared' -import * as vscode from 'vscode' export async function getContextFileFromGitLog( file: FileURI, @@ -45,15 +45,15 @@ export async function getContextFileFromGitLog( throw new Error(`git log failed with exit code ${result.code}: ${result.stderr}`) } - return [ - { - type: 'file', - content: result.stdout, - title: 'Terminal Output', - uri: vscode.Uri.file('terminal-output'), - source: ContextItemSource.History, - }, - ] + const contextItem: ContextItemHistory = { + type: 'history', + content: result.stdout, + title: `history for ${options.funcname}`, + uri: file, + symbolName: options.funcname, + source: ContextItemSource.History, + } + return [contextItem] }) } diff --git a/vscode/webviews/promptEditor/nodes/ContextItemMentionNode.ts b/vscode/webviews/promptEditor/nodes/ContextItemMentionNode.ts index b4a5d3599c..9915cb54e2 100644 --- a/vscode/webviews/promptEditor/nodes/ContextItemMentionNode.ts +++ b/vscode/webviews/promptEditor/nodes/ContextItemMentionNode.ts @@ -4,6 +4,7 @@ import styles from './ContextItemMentionNode.module.css' import { type ContextItem, type ContextItemFile, + type ContextItemHistory, type ContextItemPackage, type ContextItemSymbol, displayLineRange, @@ -33,6 +34,7 @@ export type SerializedContextItem = { uri: string; title?: string; content?: und | Omit | Omit | Omit + | Omit ) export function serializeContextItem( @@ -180,20 +182,19 @@ export function contextItemMentionNodeDisplayText(contextItem: SerializedContext // range needs to go to the start (0th character) of line 5. Also, `RangeData` is 0-indexed but // display ranges are 1-indexed. const rangeText = contextItem.range?.start ? `:${displayLineRange(contextItem.range)}` : '' - if (contextItem.type === 'file') { - if (contextItem.provider && contextItem.title) { - return `@${contextItem.title}` - } - return `@${decodeURIComponent(displayPath(URI.parse(contextItem.uri)))}${rangeText}` - } - if (contextItem.type === 'symbol') { - return `@${displayPath(URI.parse(contextItem.uri))}${rangeText}#${contextItem.symbolName}` - } - if (contextItem.type === 'package') { - return `@${contextItem.ecosystem}:${contextItem.name}` + switch (contextItem.type) { + case 'file': + if (contextItem.provider && contextItem.title) { + return `@${contextItem.title}` + } + return `@${decodeURIComponent(displayPath(URI.parse(contextItem.uri)))}${rangeText}` + case 'symbol': + return `@${displayPath(URI.parse(contextItem.uri))}${rangeText}#${contextItem.symbolName}` + case 'package': + return `@${contextItem.ecosystem}:${contextItem.name}` + case 'history': + return `@history:${contextItem.symbolName}:${displayPath(URI.parse(contextItem.uri))}` } - // @ts-ignore - throw new Error(`unrecognized context item type ${contextItem.type}`) } export function $createContextItemMentionNode( diff --git a/vscode/webviews/promptEditor/plugins/atMentions/OptionsList.tsx b/vscode/webviews/promptEditor/plugins/atMentions/OptionsList.tsx index 642974d7d0..830a9cc884 100644 --- a/vscode/webviews/promptEditor/plugins/atMentions/OptionsList.tsx +++ b/vscode/webviews/promptEditor/plugins/atMentions/OptionsList.tsx @@ -105,7 +105,7 @@ const Item: FunctionComponent<{ const isFileType = item.type === 'file' const isPackageType = item.type === 'package' const icon = - isFileType || isPackageType ? null : item.kind === 'class' ? 'symbol-structure' : 'symbol-method' + item.type === 'symbol' ? (item.kind === 'class' ? 'symbol-structure' : 'symbol-method') : null const title = item.title ?? (isFileType || isPackageType ? displayPathBasename(item.uri) : item.symbolName)