Skip to content

Commit 6aeede9

Browse files
committed
feat(chat): Enhance workflow context and fixes
- Introduce workflows as context items in chat mentions - Add support for custom links in chat mentions - Correctly calculate token count for context files and human message editor - Rename file to align with workflow context - Bump version to 1.76.0+0
1 parent e9676c2 commit 6aeede9

File tree

13 files changed

+128
-15
lines changed

13 files changed

+128
-15
lines changed

lib/prompt-editor/src/mentions/mentionMenu/MentionMenuItem.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ import {
1616
displayPathBasename,
1717
displayPathDirname,
1818
} from '@sourcegraph/cody-shared'
19+
import { WORKFLOW_PROVIDER } from '@sourcegraph/cody-shared/src/mentions/api'
1920
import { clsx } from 'clsx'
2021
import {
2122
ArrowRightIcon,
2223
BookCheckIcon,
2324
BoxIcon,
25+
Cog,
2426
DatabaseIcon,
2527
ExternalLinkIcon,
2628
FileIcon,
@@ -184,6 +186,7 @@ export const iconForProvider: Record<
184186
[REMOTE_DIRECTORY_PROVIDER_URI]: FolderGitIcon,
185187
[WEB_PROVIDER_URI]: LinkIcon,
186188
[RULES_PROVIDER_URI]: BookCheckIcon,
189+
[WORKFLOW_PROVIDER.id]: Cog,
187190
}
188191

189192
const iconForItem: Record<

lib/prompt-editor/src/nodes/ContextItemMentionNode.tsx

+8-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
contextItemMentionNodeDisplayText,
1010
serializeContextItem,
1111
} from '@sourcegraph/cody-shared'
12+
import { WORKFLOW_PROVIDER } from '@sourcegraph/cody-shared/src/mentions/api'
1213
import {
1314
$applyNodeReplacement,
1415
type DOMConversionMap,
@@ -157,11 +158,13 @@ function iconForContextItem(contextItem: SerializedContextItem): React.Component
157158
? FILE_CONTEXT_MENTION_PROVIDER.id
158159
: contextItem.type === 'symbol'
159160
? SYMBOL_CONTEXT_MENTION_PROVIDER.id
160-
: contextItem.type === 'repository' || contextItem.type === 'tree'
161-
? REMOTE_REPOSITORY_PROVIDER_URI
162-
: contextItem.type === 'openctx'
163-
? contextItem.providerUri
164-
: 'unknown'
161+
: contextItem.type === 'workflows' // Our new type
162+
? WORKFLOW_PROVIDER.id
163+
: contextItem.type === 'repository' || contextItem.type === 'tree'
164+
? REMOTE_REPOSITORY_PROVIDER_URI
165+
: contextItem.type === 'openctx'
166+
? contextItem.providerUri
167+
: 'unknown'
165168
return iconForProvider[providerUri] ?? AtSignIcon
166169
}
167170

lib/shared/src/codebase-context/messages.ts

+6
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export type ContextItem =
143143
| ContextItemCurrentDirectory
144144
| ContextItemCurrentOpenTabs
145145
| ContextItemMedia
146+
| ContextItemWorkflows
146147

147148
/**
148149
* Context items to show by default in the chat input, or as suggestions in the chat UI.
@@ -268,6 +269,11 @@ export type SymbolKind = 'class' | 'function' | 'method'
268269
/** {@link ContextItem} with the `content` field set to the content. */
269270
export type ContextItemWithContent = ContextItem & { content: string }
270271

272+
export interface ContextItemWorkflows extends ContextItemCommon {
273+
type: 'workflows'
274+
name: string
275+
}
276+
271277
/**
272278
* A system chat message that adds a context item to the conversation.
273279
*/

lib/shared/src/lexicalEditor/nodes.ts

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
ContextItemSource,
1717
ContextItemSymbol,
1818
ContextItemTree,
19+
ContextItemWorkflows,
1920
} from '../codebase-context/messages'
2021
import {
2122
displayLineRange,
@@ -51,6 +52,7 @@ export type SerializedContextItem = {
5152
| Omit<ContextItemCurrentDirectory, 'uri' | 'content' | 'source'>
5253
| Omit<ContextItemCurrentOpenTabs, 'uri' | 'content' | 'source'>
5354
| Omit<ContextItemMedia, 'uri' | 'content' | 'source'>
55+
| Omit<ContextItemWorkflows, 'uri' | 'content' | 'source'>
5456
)
5557

5658
export type SerializedTemplateInput = {
@@ -338,6 +340,8 @@ export function contextItemMentionNodeDisplayText(contextItem: SerializedContext
338340

339341
case 'current-open-tabs':
340342
return 'currently open tabs'
343+
case 'workflows':
344+
return contextItem.name
341345
}
342346

343347
// @ts-ignore

lib/shared/src/mentions/api.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,21 @@ export const SYMBOL_CONTEXT_MENTION_PROVIDER: ContextMentionProviderMetadata & {
5151
emptyLabel: 'No symbols found',
5252
}
5353

54+
export const WORKFLOW_PROVIDER: ContextMentionProviderMetadata & { id: 'workflows' } = {
55+
id: 'workflows',
56+
title: 'Workflows',
57+
queryLabel: 'Enter a name for your workflow...',
58+
emptyLabel: 'No workflows found',
59+
}
60+
5461
export function mentionProvidersMetadata(options?: {
5562
disableProviders: ContextMentionProviderID[]
5663
}): Observable<ContextMentionProviderMetadata[]> {
5764
return openCtxMentionProviders().map(providers =>
58-
[...[FILE_CONTEXT_MENTION_PROVIDER, SYMBOL_CONTEXT_MENTION_PROVIDER], ...providers].filter(
59-
provider => !options?.disableProviders.includes(provider.id)
60-
)
65+
[
66+
...[FILE_CONTEXT_MENTION_PROVIDER, SYMBOL_CONTEXT_MENTION_PROVIDER, WORKFLOW_PROVIDER],
67+
...providers,
68+
].filter(provider => !options?.disableProviders.includes(provider.id))
6169
)
6270
}
6371

lib/shared/src/telemetry-v2/events/chat-question.ts

+2
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ function publicContextSummary(globalPrefix: string, context: ContextItem[]) {
212212
'current-repository': cloneDeep(defaultByTypeCount),
213213
'current-directory': cloneDeep(defaultByTypeCount),
214214
'current-open-tabs': cloneDeep(defaultByTypeCount),
215+
workflows: cloneDeep(defaultByTypeCount),
215216
}
216217
const byOpenctxProvider = {
217218
[REMOTE_REPOSITORY_PROVIDER_URI]: cloneDeep(defaultSharedItemCount),
@@ -359,6 +360,7 @@ const defaultBySourceCount: BySourceCount = {
359360
'current-directory': undefined,
360361
'current-open-tabs': undefined,
361362
media: undefined,
363+
workflows: undefined,
362364
},
363365
}
364366

vscode/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "cody-ai",
44
"private": true,
55
"displayName": "Cody: AI Code Assistant",
6-
"version": "1.74.0+3",
6+
"version": "1.76.0+0",
77
"publisher": "sourcegraph",
88
"license": "Apache-2.0",
99
"icon": "resources/sourcegraph.png",

vscode/src/chat/context/chatContext.ts

+6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
switchMapReplayOperation,
2525
telemetryEvents,
2626
} from '@sourcegraph/cody-shared'
27+
import { WORKFLOW_PROVIDER } from '@sourcegraph/cody-shared/src/mentions/api'
2728
import { LRUCache } from 'lru-cache'
2829
import { Observable, map } from 'observable-fns'
2930
import * as vscode from 'vscode'
@@ -36,6 +37,7 @@ import {
3637
} from '../../editor/utils/editor-context'
3738
import { repoNameResolver } from '../../repository/repo-name-resolver'
3839
import { ChatBuilder } from '../chat-view/ChatBuilder'
40+
import { getWorkflowForMention } from './getWorkflowForMention'
3941

4042
/**
4143
* This state is used to keep track of telemetry events that have already fired
@@ -152,6 +154,10 @@ export async function getChatContextItemsForMention(
152154
return files
153155
}
154156

157+
case WORKFLOW_PROVIDER.id: {
158+
return getWorkflowForMention(mentionQuery.text)
159+
}
160+
155161
default: {
156162
const items = await currentOpenCtxController().mentions(
157163
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import * as fs from 'node:fs'
2+
import * as path from 'node:path'
3+
import { type ContextItem, ContextItemSource } from '@sourcegraph/cody-shared'
4+
import type { ContextItemWorkflows } from '@sourcegraph/cody-shared/src/codebase-context/messages'
5+
import { WORKFLOW_PROVIDER } from '@sourcegraph/cody-shared/src/mentions/api'
6+
import * as vscode from 'vscode'
7+
import { URI } from 'vscode-uri'
8+
import { CODY_WORKFLOWS_DIR } from '../../workflow/workflow-io'
9+
10+
export function getWorkflowForMention(query: string): ContextItem[] {
11+
const workspaceFolders = vscode.workspace.workspaceFolders
12+
if (!workspaceFolders || workspaceFolders.length === 0) {
13+
return []
14+
}
15+
16+
const customLinks: Array<{ name: string; url: string; description: string }> = []
17+
18+
// Scan all workspace folders for workflows
19+
for (const folder of workspaceFolders) {
20+
const workflowsDir = path.join(folder.uri.path, CODY_WORKFLOWS_DIR)
21+
22+
// Check if the workflows directory exists
23+
if (fs.existsSync(workflowsDir)) {
24+
try {
25+
const files = fs.readdirSync(workflowsDir)
26+
27+
// Filter for JSON files
28+
const jsonFiles = files.filter(file => file.endsWith('.json'))
29+
30+
// Create a link for each JSON file
31+
for (const file of jsonFiles) {
32+
const filePath = path.join(workflowsDir, file)
33+
const fileUri = vscode.Uri.file(filePath)
34+
const fileName = path.basename(file, '.json')
35+
36+
customLinks.push({
37+
name: fileName,
38+
url: fileUri.toString(),
39+
description: 'Workflow',
40+
})
41+
}
42+
} catch (error) {
43+
console.error('Error reading workflows directory:', error)
44+
}
45+
}
46+
}
47+
48+
// Only filter links if a non-empty query is provided
49+
let linksToReturn = customLinks
50+
if (query && query.trim().length > 0) {
51+
linksToReturn = customLinks.filter(
52+
link =>
53+
link.name.toLowerCase().includes(query.toLowerCase()) ||
54+
link.description.toLowerCase().includes(query.toLowerCase())
55+
)
56+
}
57+
58+
// Sort the links alphabetically by name
59+
linksToReturn.sort((a, b) => a.name.localeCompare(b.name))
60+
61+
// Convert to ContextItems
62+
return linksToReturn.map(
63+
link =>
64+
({
65+
type: 'workflows',
66+
uri: URI.parse(link.url),
67+
name: link.name, // Required property based on similar interfaces
68+
title: link.name,
69+
description: link.description,
70+
content: 'Workflow',
71+
source: ContextItemSource.User,
72+
provider: WORKFLOW_PROVIDER.id,
73+
}) as ContextItemWorkflows
74+
)
75+
}

vscode/src/workflow/workflow-io.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { writeToCodyJSON } from '../commands/utils/config-file'
44
import { migrateWorkflowData } from './workflow-migration'
55

66
export const WORKFLOW_VERSION = '1.1.0'
7-
const CODY_NODES_DIR = '.sourcegraph/nodes'
8-
const CODY_WORKFLOWS_DIR = '.sourcegraph/workflows'
7+
export const CODY_NODES_DIR = '.sourcegraph/nodes'
8+
export const CODY_WORKFLOWS_DIR = '.sourcegraph/workflows'
99

1010
/**
1111
* Handles the workflow saving process by displaying a save dialog to the user, allowing them to select a location to save the workflow file.

vscode/webviews/chat/Transcript.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,11 @@ export const Transcript: FC<TranscriptProps> = props => {
143143
// Calculate context file tokens
144144
const contextTokens = await Promise.all(
145145
messages.flatMap(msg =>
146-
(msg.contextFiles || []).map(item => counter.encode(item.content || '').length)
146+
(msg.contextFiles || [])
147+
.filter(item => !item.isTooLarge && !item.isIgnored)
148+
.map(item => counter.encode(item.content || '').length)
147149
)
148150
)
149-
150151
const total = [...messageTokens, ...contextTokens].reduce((a, b) => a + b, 0)
151152
setTranscriptTokens(total)
152153
}, 300),

vscode/webviews/chat/cells/messageCell/human/HumanMessageCell.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ export const HumanMessageCell: FC<HumanMessageCellProps> = ({ message, ...otherP
5858
<HumanMessageCellContent
5959
{...otherProps}
6060
initialEditorState={initialEditorState}
61-
intent={message.manuallySelectedIntent}
6261
imageFile={imageFile}
6362
setImageFile={setImageFile}
6463
/>

vscode/webviews/chat/cells/messageCell/human/editor/HumanMessageEditor.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,13 @@ export const HumanMessageEditor: FunctionComponent<{
141141
setTokenAdded(0)
142142
return
143143
}
144-
setTokenAdded(items.reduce((acc, item) => acc + (item.size ? item.size : 0), 0))
144+
setTokenAdded(
145+
items.reduce(
146+
(acc, item) =>
147+
acc + (!item.isTooLarge && !item.isIgnored && item.size ? item.size : 0),
148+
0
149+
)
150+
)
145151
})
146152
return unregister
147153
}, [])

0 commit comments

Comments
 (0)