Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/chronicle/common/standupPrompt.ts
13399 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import type { RefRow, SessionRow } from '../../../platform/chronicle/common/sessionStore';
7
8
/** A session row annotated with its source. */
9
export interface AnnotatedSession extends SessionRow {
10
/** Where this session came from: 'vscode', 'cli', or 'cloud'. */
11
source: 'vscode' | 'cli' | 'cloud';
12
}
13
14
/** A ref row annotated with its source. */
15
export interface AnnotatedRef extends RefRow {
16
source: 'vscode' | 'cli' | 'cloud';
17
}
18
19
/** Sessions query — SQLite dialect, last 24 hours */
20
export const SESSIONS_QUERY_SQLITE = `SELECT *
21
FROM sessions
22
WHERE updated_at >= datetime('now', '-1 day')
23
ORDER BY updated_at DESC`;
24
25
/** Build refs query for a list of session IDs */
26
export function buildRefsQuery(sessionIds: string[]): string {
27
const ids = sessionIds.map(s => `'${s.replace(/'/g, '\'\'')}'`).join(',');
28
return `SELECT session_id, ref_type, ref_value FROM session_refs WHERE session_id IN (${ids})`;
29
}
30
31
/** Build files query for a list of session IDs */
32
export function buildFilesQuery(sessionIds: string[]): string {
33
const ids = sessionIds.map(s => `'${s.replace(/'/g, '\'\'')}'`).join(',');
34
return `SELECT session_id, file_path, tool_name FROM session_files WHERE session_id IN (${ids})`;
35
}
36
37
/** Build turns query for a list of session IDs (user messages + assistant response summaries, truncated) */
38
export function buildTurnsQuery(sessionIds: string[]): string {
39
const ids = sessionIds.map(s => `'${s.replace(/'/g, '\'\'')}'`).join(',');
40
return `SELECT session_id, turn_index, substr(user_message, 1, 120) as user_message, substr(assistant_response, 1, 200) as assistant_response FROM turns WHERE session_id IN (${ids}) AND (user_message IS NOT NULL OR assistant_response IS NOT NULL) ORDER BY session_id, turn_index`;
41
}
42
43
/** A file row from the session_files table. */
44
export interface SessionFileInfo {
45
session_id: string;
46
file_path: string;
47
tool_name?: string;
48
}
49
50
/** A turn summary from the turns table. */
51
export interface SessionTurnInfo {
52
session_id: string;
53
turn_index: number;
54
user_message?: string;
55
assistant_response?: string;
56
}
57
58
/**
59
* Build a standup prompt from pre-fetched session and ref data.
60
*/
61
export function buildStandupPrompt(
62
sessions: AnnotatedSession[],
63
refs: AnnotatedRef[],
64
turns: SessionTurnInfo[],
65
files: SessionFileInfo[],
66
extra?: string,
67
): string {
68
if (sessions.length === 0) {
69
return 'The user ran /standup but no sessions were found. Let them know there\'s no recent activity to report.';
70
}
71
72
const sessionLines = sessions.map(s => {
73
const branch = s.branch ?? 'unknown';
74
const repo = s.repository ?? 'unknown';
75
const agent = s.agent_name ?? s.source;
76
77
// Include turn summaries for this session (first few user messages + assistant responses)
78
const sessionTurns = turns.filter(t => t.session_id === s.id).slice(0, 5);
79
80
// Use first turn's user_message as summary when sessions.summary is empty
81
const firstTurnMessage = sessionTurns[0]?.user_message;
82
const summary = s.summary || firstTurnMessage || 'No summary';
83
84
const turnLines = sessionTurns
85
.filter(t => t.user_message || t.assistant_response)
86
.map(t => {
87
const parts: string[] = [];
88
if (t.user_message) { parts.push(`User: ${t.user_message}`); }
89
if (t.assistant_response) { parts.push(`Assistant: ${t.assistant_response}`); }
90
return ` - ${parts.join(' → ')}`;
91
});
92
93
// Include files touched in this session (capped to avoid noise)
94
const sessionFiles = files.filter(f => f.session_id === s.id);
95
const uniqueFiles = [...new Set(sessionFiles.map(f => f.file_path))];
96
const shownFiles = uniqueFiles.slice(0, 5);
97
const fileLines = shownFiles.length > 0
98
? [` - Files (${uniqueFiles.length} total): ${shownFiles.join(', ')}${uniqueFiles.length > 5 ? `, +${uniqueFiles.length - 5} more` : ''}`]
99
: [];
100
101
return [
102
`- ${s.id} | ${repo} (${branch}) | ${agent} | ${summary} | updated ${s.updated_at}`,
103
...turnLines,
104
...fileLines,
105
].join('\n');
106
});
107
108
const refLines = refs.map(r => `- ${r.session_id} | ${r.ref_type}: ${r.ref_value}`);
109
110
let prompt = `The user ran /chronicle standup. Generate a concise standup update from the pre-fetched data below.
111
112
## Pre-fetched Session Data (last 24 hours)
113
114
### Sessions (${sessions.length})
115
${sessionLines.join('\n')}
116
117
### References (PRs, Issues, Commits)
118
${refLines.length > 0 ? refLines.join('\n') : 'No references found.'}
119
120
## Instructions
121
122
1. Analyze the turn data (user messages and assistant responses) to understand the actual work done in each session.
123
2. Use file paths to identify which components, modules, or areas of the codebase were affected.
124
3. For any PR/issue references, mention them with links.
125
4. If a session has no turns or summary, note it briefly but don't skip it entirely.
126
127
## Output Format
128
129
Format the update grouped by work stream (branch/feature). Use this structure:
130
131
Standup for <date>:
132
133
**✅ Done**
134
135
**Feature name** (\`branch-name\` branch, \`repo-name\`)
136
- Summary of what was accomplished (1-2 sentences grounded in the user messages and assistant responses)
137
- Key files: list 2-3 most important files changed
138
- Tools used: mention key tools if visible (e.g., apply_patch, run_in_terminal, search)
139
- PR: [#123](link) — merged/closed (if applicable)
140
141
**🚧 In Progress**
142
143
**Feature name** (\`branch-name\` branch, \`repo-name\`)
144
- Summary of current work (1-2 sentences based on turn content)
145
- Key files: list 2-3 most important files being worked on
146
- PR: [#789](link) — draft/open (if applicable)
147
148
Formatting rules:
149
- Use the turn data (user messages AND assistant responses) to understand WHAT was done, not just that something happened
150
- Use file paths to identify which components/areas were affected
151
- Group related sessions on the same branch into one entry
152
- Link PRs and issues using markdown link syntax
153
- Classify as Done if the session has no recent activity or the work appears complete, In Progress otherwise
154
- If a session has no branch or repo, still include it under an "Other" section`;
155
156
if (extra) {
157
prompt += `\n\nAdditional context: ${extra}`;
158
}
159
160
return prompt;
161
}
162
163