@keepgoingdev/mcp-server 0.1.0
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.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/printMomentum.d.ts +9 -0
- package/dist/printMomentum.js +40 -0
- package/dist/printMomentum.js.map +1 -0
- package/dist/prompts/resume.d.ts +2 -0
- package/dist/prompts/resume.js +23 -0
- package/dist/prompts/resume.js.map +1 -0
- package/dist/storage.d.ts +40 -0
- package/dist/storage.js +101 -0
- package/dist/storage.js.map +1 -0
- package/dist/tools/getMomentum.d.ts +3 -0
- package/dist/tools/getMomentum.js +66 -0
- package/dist/tools/getMomentum.js.map +1 -0
- package/dist/tools/getReentryBriefing.d.ts +3 -0
- package/dist/tools/getReentryBriefing.js +47 -0
- package/dist/tools/getReentryBriefing.js.map +1 -0
- package/dist/tools/getSessionHistory.d.ts +3 -0
- package/dist/tools/getSessionHistory.js +50 -0
- package/dist/tools/getSessionHistory.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/gitUtils.d.ts +8 -0
- package/dist/utils/gitUtils.js +52 -0
- package/dist/utils/gitUtils.js.map +1 -0
- package/dist/utils/reentry.d.ts +6 -0
- package/dist/utils/reentry.js +197 -0
- package/dist/utils/reentry.js.map +1 -0
- package/dist/utils/timeUtils.d.ts +5 -0
- package/dist/utils/timeUtils.js +47 -0
- package/dist/utils/timeUtils.js.map +1 -0
- package/package.json +26 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { KeepGoingReader } from './storage.js';
|
|
5
|
+
import { formatRelativeTime } from '@keepgoingdev/shared';
|
|
6
|
+
import { registerGetMomentum } from './tools/getMomentum.js';
|
|
7
|
+
import { registerGetSessionHistory } from './tools/getSessionHistory.js';
|
|
8
|
+
import { registerGetReentryBriefing } from './tools/getReentryBriefing.js';
|
|
9
|
+
import { registerResumePrompt } from './prompts/resume.js';
|
|
10
|
+
// Handle --print-momentum CLI flag: print momentum context and exit.
|
|
11
|
+
// Used by the Claude Code SessionStart hook (scripts/keepgoing-hook.sh).
|
|
12
|
+
if (process.argv.includes('--print-momentum')) {
|
|
13
|
+
// Workspace path is the first non-flag argument after the script path
|
|
14
|
+
const wsPath = process.argv.slice(2).find(a => a !== '--print-momentum') || process.cwd();
|
|
15
|
+
const reader = new KeepGoingReader(wsPath);
|
|
16
|
+
if (!reader.exists()) {
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
const lastSession = reader.getLastSession();
|
|
20
|
+
if (!lastSession) {
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
23
|
+
const touchedCount = lastSession.touchedFiles?.length ?? 0;
|
|
24
|
+
const lines = [];
|
|
25
|
+
lines.push(`[KeepGoing] Last checkpoint: ${formatRelativeTime(lastSession.timestamp)}`);
|
|
26
|
+
if (lastSession.summary) {
|
|
27
|
+
lines.push(` Summary: ${lastSession.summary}`);
|
|
28
|
+
}
|
|
29
|
+
if (lastSession.nextStep) {
|
|
30
|
+
lines.push(` Next step: ${lastSession.nextStep}`);
|
|
31
|
+
}
|
|
32
|
+
if (lastSession.blocker) {
|
|
33
|
+
lines.push(` Blocker: ${lastSession.blocker}`);
|
|
34
|
+
}
|
|
35
|
+
if (lastSession.gitBranch) {
|
|
36
|
+
lines.push(` Branch: ${lastSession.gitBranch}`);
|
|
37
|
+
}
|
|
38
|
+
if (touchedCount > 0) {
|
|
39
|
+
lines.push(` Worked on ${touchedCount} files on ${lastSession.gitBranch ?? 'unknown branch'}`);
|
|
40
|
+
}
|
|
41
|
+
lines.push(' Tip: Use the get_reentry_briefing tool for a full briefing');
|
|
42
|
+
console.log(lines.join('\n'));
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
// Default: start MCP server
|
|
46
|
+
// Workspace path can be passed as an argument, otherwise defaults to CWD.
|
|
47
|
+
// MCP hosts (Claude Code, etc.) typically launch the server with the project root as CWD.
|
|
48
|
+
const workspacePath = process.argv[2] || process.cwd();
|
|
49
|
+
const reader = new KeepGoingReader(workspacePath);
|
|
50
|
+
const server = new McpServer({
|
|
51
|
+
name: 'keepgoing',
|
|
52
|
+
version: '0.1.0',
|
|
53
|
+
});
|
|
54
|
+
// Register tools
|
|
55
|
+
registerGetMomentum(server, reader, workspacePath);
|
|
56
|
+
registerGetSessionHistory(server, reader);
|
|
57
|
+
registerGetReentryBriefing(server, reader, workspacePath);
|
|
58
|
+
// Register prompts
|
|
59
|
+
registerResumePrompt(server);
|
|
60
|
+
// Connect via stdio
|
|
61
|
+
const transport = new StdioServerTransport();
|
|
62
|
+
await server.connect(transport);
|
|
63
|
+
console.error('KeepGoing MCP server started');
|
|
64
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,qEAAqE;AACrE,yEAAyE;AACzE,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;IAC9C,sEAAsE;IACtE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,kBAAkB,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1F,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IAE3C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;IAC5C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,gCAAgC,kBAAkB,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACxF,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,gBAAgB,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,aAAa,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,eAAe,YAAY,aAAa,WAAW,CAAC,SAAS,IAAI,gBAAgB,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;IAE3E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,4BAA4B;AAC5B,0EAA0E;AAC1E,0FAA0F;AAC1F,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;AACvD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,aAAa,CAAC,CAAC;AAElD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,iBAAiB;AACjB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AACnD,yBAAyB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC1C,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AAE1D,mBAAmB;AACnB,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAE7B,oBAAoB;AACpB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhC,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Standalone CLI script that prints momentum context to stdout.
|
|
4
|
+
* Used by the Claude Code SessionStart hook (scripts/keepgoing-hook.sh).
|
|
5
|
+
*
|
|
6
|
+
* Usage: node printMomentum.js [workspacePath]
|
|
7
|
+
* Exits silently (code 0) if no data is available.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Standalone CLI script that prints momentum context to stdout.
|
|
4
|
+
* Used by the Claude Code SessionStart hook (scripts/keepgoing-hook.sh).
|
|
5
|
+
*
|
|
6
|
+
* Usage: node printMomentum.js [workspacePath]
|
|
7
|
+
* Exits silently (code 0) if no data is available.
|
|
8
|
+
*/
|
|
9
|
+
import { KeepGoingReader } from './storage.js';
|
|
10
|
+
import { formatRelativeTime } from '@keepgoing/shared';
|
|
11
|
+
const workspacePath = process.argv[2] || process.cwd();
|
|
12
|
+
const reader = new KeepGoingReader(workspacePath);
|
|
13
|
+
if (!reader.exists()) {
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
const lastSession = reader.getLastSession();
|
|
17
|
+
if (!lastSession) {
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
const touchedCount = lastSession.touchedFiles?.length ?? 0;
|
|
21
|
+
const lines = [];
|
|
22
|
+
lines.push(`[KeepGoing] Last checkpoint: ${formatRelativeTime(lastSession.timestamp)}`);
|
|
23
|
+
if (lastSession.summary) {
|
|
24
|
+
lines.push(` Summary: ${lastSession.summary}`);
|
|
25
|
+
}
|
|
26
|
+
if (lastSession.nextStep) {
|
|
27
|
+
lines.push(` Next step: ${lastSession.nextStep}`);
|
|
28
|
+
}
|
|
29
|
+
if (lastSession.blocker) {
|
|
30
|
+
lines.push(` Blocker: ${lastSession.blocker}`);
|
|
31
|
+
}
|
|
32
|
+
if (lastSession.gitBranch) {
|
|
33
|
+
lines.push(` Branch: ${lastSession.gitBranch}`);
|
|
34
|
+
}
|
|
35
|
+
if (touchedCount > 0) {
|
|
36
|
+
lines.push(` Worked on ${touchedCount} files on ${lastSession.gitBranch ?? 'unknown branch'}`);
|
|
37
|
+
}
|
|
38
|
+
lines.push(' Tip: Use the get_reentry_briefing tool for a full briefing');
|
|
39
|
+
console.log(lines.join('\n'));
|
|
40
|
+
//# sourceMappingURL=printMomentum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"printMomentum.js","sourceRoot":"","sources":["../src/printMomentum.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;AACvD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,aAAa,CAAC,CAAC;AAElD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;AAC5C,IAAI,CAAC,WAAW,EAAE,CAAC;IACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC;AAE3D,MAAM,KAAK,GAAa,EAAE,CAAC;AAC3B,KAAK,CAAC,IAAI,CAAC,gCAAgC,kBAAkB,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;AACxF,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;IACxB,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;AAClD,CAAC;AACD,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,gBAAgB,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;AACrD,CAAC;AACD,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;IACxB,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;AAClD,CAAC;AACD,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;IAC1B,KAAK,CAAC,IAAI,CAAC,aAAa,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC;AACnD,CAAC;AACD,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;IACrB,KAAK,CAAC,IAAI,CAAC,eAAe,YAAY,aAAa,WAAW,CAAC,SAAS,IAAI,gBAAgB,EAAE,CAAC,CAAC;AAClG,CAAC;AACD,KAAK,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;AAE3E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function registerResumePrompt(server) {
|
|
2
|
+
server.prompt('resume', 'Check developer momentum and suggest what to work on next', async () => ({
|
|
3
|
+
messages: [
|
|
4
|
+
{
|
|
5
|
+
role: 'user',
|
|
6
|
+
content: {
|
|
7
|
+
type: 'text',
|
|
8
|
+
text: [
|
|
9
|
+
'I just opened this project and want to pick up where I left off.',
|
|
10
|
+
'',
|
|
11
|
+
'Please use the KeepGoing tools to:',
|
|
12
|
+
'1. Check my current momentum (get_momentum)',
|
|
13
|
+
'2. Get a re-entry briefing (get_reentry_briefing)',
|
|
14
|
+
'3. Based on the results, give me a concise summary of where I left off and suggest what to work on next.',
|
|
15
|
+
'',
|
|
16
|
+
'Keep your response brief and actionable.',
|
|
17
|
+
].join('\n'),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../src/prompts/resume.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,MAAM,CACX,QAAQ,EACR,2DAA2D,EAC3D,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;wBACJ,kEAAkE;wBAClE,EAAE;wBACF,oCAAoC;wBACpC,6CAA6C;wBAC7C,mDAAmD;wBACnD,0GAA0G;wBAC1G,EAAE;wBACF,0CAA0C;qBAC3C,CAAC,IAAI,CAAC,IAAI,CAAC;iBACb;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type SessionCheckpoint, type ProjectState, type ProjectMeta } from '@keepgoingdev/shared';
|
|
2
|
+
/**
|
|
3
|
+
* Read-only reader for .keepgoing/ directory.
|
|
4
|
+
* Does not write or create any files.
|
|
5
|
+
*/
|
|
6
|
+
export declare class KeepGoingReader {
|
|
7
|
+
private readonly storagePath;
|
|
8
|
+
private readonly metaFilePath;
|
|
9
|
+
private readonly sessionsFilePath;
|
|
10
|
+
private readonly stateFilePath;
|
|
11
|
+
constructor(workspacePath: string);
|
|
12
|
+
/** Check if .keepgoing/ directory exists. */
|
|
13
|
+
exists(): boolean;
|
|
14
|
+
/** Read state.json, returns undefined if missing or corrupt. */
|
|
15
|
+
getState(): ProjectState | undefined;
|
|
16
|
+
/** Read meta.json, returns undefined if missing or corrupt. */
|
|
17
|
+
getMeta(): ProjectMeta | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Read sessions from sessions.json.
|
|
20
|
+
* Handles both formats:
|
|
21
|
+
* - Flat array: SessionCheckpoint[] (from ProjectStorage)
|
|
22
|
+
* - Wrapper object: ProjectSessions (from SessionStorage)
|
|
23
|
+
*/
|
|
24
|
+
getSessions(): SessionCheckpoint[];
|
|
25
|
+
/**
|
|
26
|
+
* Get the most recent session checkpoint.
|
|
27
|
+
* Uses state.lastSessionId if available, falls back to last in array.
|
|
28
|
+
*/
|
|
29
|
+
getLastSession(): SessionCheckpoint | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Returns the last N sessions, newest first.
|
|
32
|
+
*/
|
|
33
|
+
getRecentSessions(count: number): SessionCheckpoint[];
|
|
34
|
+
/**
|
|
35
|
+
* Parses sessions.json once, returning both the session list
|
|
36
|
+
* and the optional lastSessionId from a ProjectSessions wrapper.
|
|
37
|
+
*/
|
|
38
|
+
private parseSessions;
|
|
39
|
+
private readJsonFile;
|
|
40
|
+
}
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getRecentSessions, } from '@keepgoingdev/shared';
|
|
4
|
+
const STORAGE_DIR = '.keepgoing';
|
|
5
|
+
const META_FILE = 'meta.json';
|
|
6
|
+
const SESSIONS_FILE = 'sessions.json';
|
|
7
|
+
const STATE_FILE = 'state.json';
|
|
8
|
+
/**
|
|
9
|
+
* Read-only reader for .keepgoing/ directory.
|
|
10
|
+
* Does not write or create any files.
|
|
11
|
+
*/
|
|
12
|
+
export class KeepGoingReader {
|
|
13
|
+
storagePath;
|
|
14
|
+
metaFilePath;
|
|
15
|
+
sessionsFilePath;
|
|
16
|
+
stateFilePath;
|
|
17
|
+
constructor(workspacePath) {
|
|
18
|
+
this.storagePath = path.join(workspacePath, STORAGE_DIR);
|
|
19
|
+
this.metaFilePath = path.join(this.storagePath, META_FILE);
|
|
20
|
+
this.sessionsFilePath = path.join(this.storagePath, SESSIONS_FILE);
|
|
21
|
+
this.stateFilePath = path.join(this.storagePath, STATE_FILE);
|
|
22
|
+
}
|
|
23
|
+
/** Check if .keepgoing/ directory exists. */
|
|
24
|
+
exists() {
|
|
25
|
+
return fs.existsSync(this.storagePath);
|
|
26
|
+
}
|
|
27
|
+
/** Read state.json, returns undefined if missing or corrupt. */
|
|
28
|
+
getState() {
|
|
29
|
+
return this.readJsonFile(this.stateFilePath);
|
|
30
|
+
}
|
|
31
|
+
/** Read meta.json, returns undefined if missing or corrupt. */
|
|
32
|
+
getMeta() {
|
|
33
|
+
return this.readJsonFile(this.metaFilePath);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read sessions from sessions.json.
|
|
37
|
+
* Handles both formats:
|
|
38
|
+
* - Flat array: SessionCheckpoint[] (from ProjectStorage)
|
|
39
|
+
* - Wrapper object: ProjectSessions (from SessionStorage)
|
|
40
|
+
*/
|
|
41
|
+
getSessions() {
|
|
42
|
+
return this.parseSessions().sessions;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the most recent session checkpoint.
|
|
46
|
+
* Uses state.lastSessionId if available, falls back to last in array.
|
|
47
|
+
*/
|
|
48
|
+
getLastSession() {
|
|
49
|
+
const { sessions, wrapperLastSessionId } = this.parseSessions();
|
|
50
|
+
if (sessions.length === 0) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const state = this.getState();
|
|
54
|
+
if (state?.lastSessionId) {
|
|
55
|
+
const found = sessions.find((s) => s.id === state.lastSessionId);
|
|
56
|
+
if (found) {
|
|
57
|
+
return found;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (wrapperLastSessionId) {
|
|
61
|
+
const found = sessions.find((s) => s.id === wrapperLastSessionId);
|
|
62
|
+
if (found) {
|
|
63
|
+
return found;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return sessions[sessions.length - 1];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns the last N sessions, newest first.
|
|
70
|
+
*/
|
|
71
|
+
getRecentSessions(count) {
|
|
72
|
+
return getRecentSessions(this.getSessions(), count);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parses sessions.json once, returning both the session list
|
|
76
|
+
* and the optional lastSessionId from a ProjectSessions wrapper.
|
|
77
|
+
*/
|
|
78
|
+
parseSessions() {
|
|
79
|
+
const raw = this.readJsonFile(this.sessionsFilePath);
|
|
80
|
+
if (!raw) {
|
|
81
|
+
return { sessions: [] };
|
|
82
|
+
}
|
|
83
|
+
if (Array.isArray(raw)) {
|
|
84
|
+
return { sessions: raw };
|
|
85
|
+
}
|
|
86
|
+
return { sessions: raw.sessions ?? [], wrapperLastSessionId: raw.lastSessionId };
|
|
87
|
+
}
|
|
88
|
+
readJsonFile(filePath) {
|
|
89
|
+
try {
|
|
90
|
+
if (!fs.existsSync(filePath)) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
94
|
+
return JSON.parse(raw);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { getCurrentBranch, formatRelativeTime } from '@keepgoingdev/shared';
|
|
2
|
+
export function registerGetMomentum(server, reader, workspacePath) {
|
|
3
|
+
server.tool('get_momentum', 'Get current developer momentum: last checkpoint, next step, blockers, and branch context. Use this to understand where the developer left off.', {}, async () => {
|
|
4
|
+
if (!reader.exists()) {
|
|
5
|
+
return {
|
|
6
|
+
content: [
|
|
7
|
+
{
|
|
8
|
+
type: 'text',
|
|
9
|
+
text: 'No KeepGoing data found. The developer has not saved any checkpoints yet.',
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const lastSession = reader.getLastSession();
|
|
15
|
+
if (!lastSession) {
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: 'KeepGoing is set up but no session checkpoints exist yet.',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const state = reader.getState();
|
|
26
|
+
const currentBranch = getCurrentBranch(workspacePath);
|
|
27
|
+
const branchChanged = lastSession.gitBranch &&
|
|
28
|
+
currentBranch &&
|
|
29
|
+
lastSession.gitBranch !== currentBranch;
|
|
30
|
+
const lines = [
|
|
31
|
+
`## Developer Momentum`,
|
|
32
|
+
'',
|
|
33
|
+
`**Last checkpoint:** ${formatRelativeTime(lastSession.timestamp)}`,
|
|
34
|
+
`**Summary:** ${lastSession.summary || 'No summary'}`,
|
|
35
|
+
`**Next step:** ${lastSession.nextStep || 'Not specified'}`,
|
|
36
|
+
];
|
|
37
|
+
if (lastSession.blocker) {
|
|
38
|
+
lines.push(`**Blocker:** ${lastSession.blocker}`);
|
|
39
|
+
}
|
|
40
|
+
if (lastSession.projectIntent) {
|
|
41
|
+
lines.push(`**Project intent:** ${lastSession.projectIntent}`);
|
|
42
|
+
}
|
|
43
|
+
lines.push('');
|
|
44
|
+
if (currentBranch) {
|
|
45
|
+
lines.push(`**Current branch:** ${currentBranch}`);
|
|
46
|
+
}
|
|
47
|
+
if (branchChanged) {
|
|
48
|
+
lines.push(`**Note:** Branch changed since last checkpoint (was \`${lastSession.gitBranch}\`, now \`${currentBranch}\`)`);
|
|
49
|
+
}
|
|
50
|
+
if (lastSession.touchedFiles.length > 0) {
|
|
51
|
+
lines.push('');
|
|
52
|
+
lines.push(`**Files touched (${lastSession.touchedFiles.length}):** ${lastSession.touchedFiles.slice(0, 10).join(', ')}`);
|
|
53
|
+
if (lastSession.touchedFiles.length > 10) {
|
|
54
|
+
lines.push(` ...and ${lastSession.touchedFiles.length - 10} more`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (state?.derivedCurrentFocus) {
|
|
58
|
+
lines.push('');
|
|
59
|
+
lines.push(`**Derived focus:** ${state.derivedCurrentFocus}`);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=getMomentum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getMomentum.js","sourceRoot":"","sources":["../../src/tools/getMomentum.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getCurrentBranch, getCommitMessagesSince, generateBriefing, } from '@keepgoingdev/shared';
|
|
2
|
+
export function registerGetReentryBriefing(server, reader, workspacePath) {
|
|
3
|
+
server.tool('get_reentry_briefing', 'Get a synthesized re-entry briefing that helps a developer understand where they left off. Includes focus, recent activity, and suggested next steps.', {}, async () => {
|
|
4
|
+
if (!reader.exists()) {
|
|
5
|
+
return {
|
|
6
|
+
content: [
|
|
7
|
+
{
|
|
8
|
+
type: 'text',
|
|
9
|
+
text: 'No KeepGoing data found. The developer has not saved any checkpoints yet.',
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const lastSession = reader.getLastSession();
|
|
15
|
+
const recentSessions = reader.getRecentSessions(5);
|
|
16
|
+
const state = reader.getState() ?? {};
|
|
17
|
+
const gitBranch = getCurrentBranch(workspacePath);
|
|
18
|
+
const sinceTimestamp = lastSession?.timestamp;
|
|
19
|
+
const recentCommits = sinceTimestamp
|
|
20
|
+
? getCommitMessagesSince(workspacePath, sinceTimestamp)
|
|
21
|
+
: [];
|
|
22
|
+
const briefing = generateBriefing(lastSession, recentSessions, state, gitBranch, recentCommits);
|
|
23
|
+
if (!briefing) {
|
|
24
|
+
return {
|
|
25
|
+
content: [
|
|
26
|
+
{
|
|
27
|
+
type: 'text',
|
|
28
|
+
text: 'No session data available to generate a briefing.',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const lines = [
|
|
34
|
+
`## Re-entry Briefing`,
|
|
35
|
+
'',
|
|
36
|
+
`**Last worked:** ${briefing.lastWorked}`,
|
|
37
|
+
`**Current focus:** ${briefing.currentFocus}`,
|
|
38
|
+
`**Recent activity:** ${briefing.recentActivity}`,
|
|
39
|
+
`**Suggested next:** ${briefing.suggestedNext}`,
|
|
40
|
+
`**Quick start:** ${briefing.smallNextStep}`,
|
|
41
|
+
];
|
|
42
|
+
return {
|
|
43
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=getReentryBriefing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getReentryBriefing.js","sourceRoot":"","sources":["../../src/tools/getReentryBriefing.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,UAAU,0BAA0B,CAAC,MAAiB,EAAE,MAAuB,EAAE,aAAqB;IAC1G,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,uJAAuJ,EACvJ,EAAE,EACF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACrB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,2EAA2E;qBAClF;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;QAC5C,MAAM,cAAc,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;QACtC,MAAM,SAAS,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;QAElD,MAAM,cAAc,GAAG,WAAW,EAAE,SAAS,CAAC;QAC9C,MAAM,aAAa,GAAG,cAAc;YAClC,CAAC,CAAC,sBAAsB,CAAC,aAAa,EAAE,cAAc,CAAC;YACvD,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,QAAQ,GAAG,gBAAgB,CAC/B,WAAW,EACX,cAAc,EACd,KAAK,EACL,SAAS,EACT,aAAa,CACd,CAAC;QAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,mDAAmD;qBAC1D;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAa;YACtB,sBAAsB;YACtB,EAAE;YACF,oBAAoB,QAAQ,CAAC,UAAU,EAAE;YACzC,sBAAsB,QAAQ,CAAC,YAAY,EAAE;YAC7C,wBAAwB,QAAQ,CAAC,cAAc,EAAE;YACjD,uBAAuB,QAAQ,CAAC,aAAa,EAAE;YAC/C,oBAAoB,QAAQ,CAAC,aAAa,EAAE;SAC7C,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;SAC7D,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { formatRelativeTime } from '@keepgoingdev/shared';
|
|
3
|
+
export function registerGetSessionHistory(server, reader) {
|
|
4
|
+
server.tool('get_session_history', 'Get recent session checkpoints. Returns a chronological list of what the developer worked on.', { limit: z.number().min(1).max(50).default(5).describe('Number of recent sessions to return (1-50, default 5)') }, async ({ limit }) => {
|
|
5
|
+
if (!reader.exists()) {
|
|
6
|
+
return {
|
|
7
|
+
content: [
|
|
8
|
+
{
|
|
9
|
+
type: 'text',
|
|
10
|
+
text: 'No KeepGoing data found.',
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const sessions = reader.getRecentSessions(limit);
|
|
16
|
+
if (sessions.length === 0) {
|
|
17
|
+
return {
|
|
18
|
+
content: [
|
|
19
|
+
{
|
|
20
|
+
type: 'text',
|
|
21
|
+
text: 'No session checkpoints found.',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const lines = [
|
|
27
|
+
`## Session History (last ${sessions.length})`,
|
|
28
|
+
'',
|
|
29
|
+
];
|
|
30
|
+
for (const session of sessions) {
|
|
31
|
+
lines.push(`### ${formatRelativeTime(session.timestamp)}`);
|
|
32
|
+
lines.push(`- **Summary:** ${session.summary || 'No summary'}`);
|
|
33
|
+
lines.push(`- **Next step:** ${session.nextStep || 'Not specified'}`);
|
|
34
|
+
if (session.blocker) {
|
|
35
|
+
lines.push(`- **Blocker:** ${session.blocker}`);
|
|
36
|
+
}
|
|
37
|
+
if (session.gitBranch) {
|
|
38
|
+
lines.push(`- **Branch:** ${session.gitBranch}`);
|
|
39
|
+
}
|
|
40
|
+
if (session.touchedFiles.length > 0) {
|
|
41
|
+
lines.push(`- **Files:** ${session.touchedFiles.slice(0, 5).join(', ')}${session.touchedFiles.length > 5 ? ` (+${session.touchedFiles.length - 5} more)` : ''}`);
|
|
42
|
+
}
|
|
43
|
+
lines.push('');
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=getSessionHistory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSessionHistory.js","sourceRoot":"","sources":["../../src/tools/getSessionHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,UAAU,yBAAyB,CAAC,MAAiB,EAAE,MAAuB;IAClF,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,+FAA+F,EAC/F,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uDAAuD,CAAC,EAAE,EACjH,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QAClB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACrB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,0BAA0B;qBACjC;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,+BAA+B;qBACtC;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAa;YACtB,4BAA4B,QAAQ,CAAC,MAAM,GAAG;YAC9C,EAAE;SACH,CAAC;QAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,OAAO,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YAC3D,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,OAAO,IAAI,YAAY,EAAE,CAAC,CAAC;YAChE,KAAK,CAAC,IAAI,CAAC,oBAAoB,OAAO,CAAC,QAAQ,IAAI,eAAe,EAAE,CAAC,CAAC;YACtE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;YAClD,CAAC;YACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,KAAK,CAAC,IAAI,CACR,gBAAgB,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CACrJ,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;SAC7D,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for KeepGoing MCP server.
|
|
3
|
+
* Mirrors apps/extension/src/core/session.ts. Keep in sync manually.
|
|
4
|
+
*/
|
|
5
|
+
export interface SessionCheckpoint {
|
|
6
|
+
id: string;
|
|
7
|
+
timestamp: string;
|
|
8
|
+
summary: string;
|
|
9
|
+
nextStep: string;
|
|
10
|
+
blocker?: string;
|
|
11
|
+
gitBranch?: string;
|
|
12
|
+
touchedFiles: string[];
|
|
13
|
+
workspaceRoot: string;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
source?: 'manual' | 'auto';
|
|
16
|
+
projectIntent?: string;
|
|
17
|
+
sessionDuration?: number;
|
|
18
|
+
commitHashes?: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface ProjectSessions {
|
|
21
|
+
version: number;
|
|
22
|
+
project: string;
|
|
23
|
+
sessions: SessionCheckpoint[];
|
|
24
|
+
lastSessionId?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ProjectMeta {
|
|
27
|
+
projectId: string;
|
|
28
|
+
createdAt: string;
|
|
29
|
+
lastUpdated: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ProjectState {
|
|
32
|
+
lastSessionId?: string;
|
|
33
|
+
lastKnownBranch?: string;
|
|
34
|
+
lastActivityAt?: string;
|
|
35
|
+
derivedCurrentFocus?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ReEntryBriefing {
|
|
38
|
+
lastWorked: string;
|
|
39
|
+
currentFocus: string;
|
|
40
|
+
recentActivity: string;
|
|
41
|
+
suggestedNext: string;
|
|
42
|
+
smallNextStep: string;
|
|
43
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the current git branch name, or undefined if not in a git repo.
|
|
3
|
+
*/
|
|
4
|
+
export declare function getCurrentBranch(workspacePath: string): string | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* Returns a list of commit subject lines since a given ISO timestamp.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getCommitMessagesSince(workspacePath: string, sinceTimestamp?: string): string[];
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git utilities for extracting context from the workspace.
|
|
3
|
+
* Copied from apps/extension/src/git/gitUtils.ts. Keep in sync manually.
|
|
4
|
+
*/
|
|
5
|
+
import { execFileSync } from 'node:child_process';
|
|
6
|
+
/**
|
|
7
|
+
* Returns the current git branch name, or undefined if not in a git repo.
|
|
8
|
+
*/
|
|
9
|
+
export function getCurrentBranch(workspacePath) {
|
|
10
|
+
try {
|
|
11
|
+
const result = execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
|
12
|
+
cwd: workspacePath,
|
|
13
|
+
encoding: 'utf-8',
|
|
14
|
+
timeout: 5000,
|
|
15
|
+
});
|
|
16
|
+
return result.trim() || undefined;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Runs git log with the given format since a timestamp.
|
|
24
|
+
*/
|
|
25
|
+
function getGitLogSince(workspacePath, format, sinceTimestamp) {
|
|
26
|
+
try {
|
|
27
|
+
const since = sinceTimestamp ||
|
|
28
|
+
new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
|
|
29
|
+
const result = execFileSync('git', ['log', `--since=${since}`, `--format=${format}`], {
|
|
30
|
+
cwd: workspacePath,
|
|
31
|
+
encoding: 'utf-8',
|
|
32
|
+
timeout: 5000,
|
|
33
|
+
});
|
|
34
|
+
if (!result.trim()) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
return result
|
|
38
|
+
.trim()
|
|
39
|
+
.split('\n')
|
|
40
|
+
.filter((line) => line.length > 0);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Returns a list of commit subject lines since a given ISO timestamp.
|
|
48
|
+
*/
|
|
49
|
+
export function getCommitMessagesSince(workspacePath, sinceTimestamp) {
|
|
50
|
+
return getGitLogSince(workspacePath, '%s', sinceTimestamp);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=gitUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitUtils.js","sourceRoot":"","sources":["../../src/utils/gitUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,aAAqB;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE;YACxE,GAAG,EAAE,aAAa;YAClB,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACrB,aAAqB,EACrB,MAAc,EACd,cAAuB;IAEvB,IAAI,CAAC;QACH,MAAM,KAAK,GACT,cAAc;YACd,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3D,MAAM,MAAM,GAAG,YAAY,CACzB,KAAK,EACL,CAAC,KAAK,EAAE,WAAW,KAAK,EAAE,EAAE,YAAY,MAAM,EAAE,CAAC,EACjD;YACE,GAAG,EAAE,aAAa;YAClB,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;SACd,CACF,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACnB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,MAAM;aACV,IAAI,EAAE;aACN,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CACpC,aAAqB,EACrB,cAAuB;IAEvB,OAAO,cAAc,CAAC,aAAa,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-entry briefing generator.
|
|
3
|
+
* Ported from apps/extension/src/reentry/reEntryService.ts. Keep in sync manually.
|
|
4
|
+
*/
|
|
5
|
+
import type { SessionCheckpoint, ProjectState, ReEntryBriefing } from '../types.js';
|
|
6
|
+
export declare function generateBriefing(lastSession: SessionCheckpoint | undefined, recentSessions: SessionCheckpoint[], projectState: ProjectState, gitBranch?: string, recentCommitMessages?: string[]): ReEntryBriefing | undefined;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { formatRelativeTime } from './timeUtils.js';
|
|
2
|
+
export function generateBriefing(lastSession, recentSessions, projectState, gitBranch, recentCommitMessages) {
|
|
3
|
+
if (!lastSession) {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
lastWorked: formatRelativeTime(lastSession.timestamp),
|
|
8
|
+
currentFocus: buildCurrentFocus(lastSession, projectState, gitBranch),
|
|
9
|
+
recentActivity: buildRecentActivity(lastSession, recentSessions, recentCommitMessages),
|
|
10
|
+
suggestedNext: buildSuggestedNext(lastSession, gitBranch),
|
|
11
|
+
smallNextStep: buildSmallNextStep(lastSession, gitBranch, recentCommitMessages),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function buildCurrentFocus(lastSession, projectState, gitBranch) {
|
|
15
|
+
if (projectState.derivedCurrentFocus) {
|
|
16
|
+
return projectState.derivedCurrentFocus;
|
|
17
|
+
}
|
|
18
|
+
const branchFocus = inferFocusFromBranch(gitBranch);
|
|
19
|
+
if (branchFocus) {
|
|
20
|
+
return branchFocus;
|
|
21
|
+
}
|
|
22
|
+
if (lastSession.summary) {
|
|
23
|
+
return lastSession.summary;
|
|
24
|
+
}
|
|
25
|
+
if (lastSession.touchedFiles.length > 0) {
|
|
26
|
+
return inferFocusFromFiles(lastSession.touchedFiles);
|
|
27
|
+
}
|
|
28
|
+
return 'Unknown';
|
|
29
|
+
}
|
|
30
|
+
function buildRecentActivity(lastSession, recentSessions, recentCommitMessages) {
|
|
31
|
+
const parts = [];
|
|
32
|
+
const sessionCount = recentSessions.length;
|
|
33
|
+
if (sessionCount > 1) {
|
|
34
|
+
parts.push(`${sessionCount} recent sessions`);
|
|
35
|
+
}
|
|
36
|
+
else if (sessionCount === 1) {
|
|
37
|
+
parts.push('1 recent session');
|
|
38
|
+
}
|
|
39
|
+
if (lastSession.summary) {
|
|
40
|
+
parts.push(`Last: ${lastSession.summary}`);
|
|
41
|
+
}
|
|
42
|
+
if (lastSession.touchedFiles.length > 0) {
|
|
43
|
+
parts.push(`${lastSession.touchedFiles.length} files touched`);
|
|
44
|
+
}
|
|
45
|
+
if (recentCommitMessages && recentCommitMessages.length > 0) {
|
|
46
|
+
parts.push(`${recentCommitMessages.length} recent commits`);
|
|
47
|
+
}
|
|
48
|
+
return parts.length > 0 ? parts.join('. ') : 'No recent activity recorded';
|
|
49
|
+
}
|
|
50
|
+
function buildSuggestedNext(lastSession, gitBranch) {
|
|
51
|
+
if (lastSession.nextStep) {
|
|
52
|
+
return lastSession.nextStep;
|
|
53
|
+
}
|
|
54
|
+
const branchFocus = inferFocusFromBranch(gitBranch);
|
|
55
|
+
if (branchFocus) {
|
|
56
|
+
return `Continue working on ${branchFocus}`;
|
|
57
|
+
}
|
|
58
|
+
if (lastSession.touchedFiles.length > 0) {
|
|
59
|
+
return `Continue working on ${inferFocusFromFiles(lastSession.touchedFiles)}`;
|
|
60
|
+
}
|
|
61
|
+
return 'Save a checkpoint to track your next step';
|
|
62
|
+
}
|
|
63
|
+
function buildSmallNextStep(lastSession, gitBranch, recentCommitMessages) {
|
|
64
|
+
const fallback = 'Review last changed files to resume flow';
|
|
65
|
+
if (lastSession.nextStep) {
|
|
66
|
+
const distilled = distillToSmallStep(lastSession.nextStep, lastSession.touchedFiles);
|
|
67
|
+
if (distilled) {
|
|
68
|
+
return distilled;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (recentCommitMessages && recentCommitMessages.length > 0) {
|
|
72
|
+
const commitStep = deriveStepFromCommits(recentCommitMessages);
|
|
73
|
+
if (commitStep) {
|
|
74
|
+
return commitStep;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (lastSession.touchedFiles.length > 0) {
|
|
78
|
+
const fileStep = deriveStepFromFiles(lastSession.touchedFiles);
|
|
79
|
+
if (fileStep) {
|
|
80
|
+
return fileStep;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const branchFocus = inferFocusFromBranch(gitBranch);
|
|
84
|
+
if (branchFocus) {
|
|
85
|
+
return `Check git status for ${branchFocus}`;
|
|
86
|
+
}
|
|
87
|
+
return fallback;
|
|
88
|
+
}
|
|
89
|
+
function distillToSmallStep(nextStep, touchedFiles) {
|
|
90
|
+
if (!nextStep.trim()) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const words = nextStep.trim().split(/\s+/);
|
|
94
|
+
if (words.length <= 12) {
|
|
95
|
+
if (touchedFiles.length > 0 && !mentionsFile(nextStep)) {
|
|
96
|
+
const primaryFile = getPrimaryFileName(touchedFiles);
|
|
97
|
+
const enhanced = `${nextStep.trim()} in ${primaryFile}`;
|
|
98
|
+
if (enhanced.split(/\s+/).length <= 12) {
|
|
99
|
+
return enhanced;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return nextStep.trim();
|
|
103
|
+
}
|
|
104
|
+
return words.slice(0, 12).join(' ');
|
|
105
|
+
}
|
|
106
|
+
function deriveStepFromCommits(commitMessages) {
|
|
107
|
+
const lastCommit = commitMessages[0];
|
|
108
|
+
if (!lastCommit || !lastCommit.trim()) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
const wipPattern = /^(?:wip|work in progress|started?|begin|draft)[:\s]/i;
|
|
112
|
+
if (wipPattern.test(lastCommit)) {
|
|
113
|
+
const topic = lastCommit.replace(wipPattern, '').trim();
|
|
114
|
+
if (topic) {
|
|
115
|
+
const words = topic.split(/\s+/).slice(0, 8).join(' ');
|
|
116
|
+
return `Continue ${words}`;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
function deriveStepFromFiles(files) {
|
|
122
|
+
const primaryFile = getPrimaryFileName(files);
|
|
123
|
+
if (files.length > 1) {
|
|
124
|
+
return `Open ${primaryFile} and review ${files.length} changed files`;
|
|
125
|
+
}
|
|
126
|
+
return `Open ${primaryFile} and pick up where you left off`;
|
|
127
|
+
}
|
|
128
|
+
function getPrimaryFileName(files) {
|
|
129
|
+
const sourceFiles = files.filter((f) => {
|
|
130
|
+
const lower = f.toLowerCase();
|
|
131
|
+
return (!lower.includes('test') &&
|
|
132
|
+
!lower.includes('spec') &&
|
|
133
|
+
!lower.includes('.config') &&
|
|
134
|
+
!lower.includes('package.json') &&
|
|
135
|
+
!lower.includes('tsconfig'));
|
|
136
|
+
});
|
|
137
|
+
const target = sourceFiles.length > 0 ? sourceFiles[0] : files[0];
|
|
138
|
+
const parts = target.replace(/\\/g, '/').split('/');
|
|
139
|
+
return parts[parts.length - 1];
|
|
140
|
+
}
|
|
141
|
+
function mentionsFile(text) {
|
|
142
|
+
return /\w+\.(?:ts|tsx|js|jsx|py|go|rs|java|rb|css|scss|html|json|yaml|yml|md|sql|sh)\b/i.test(text);
|
|
143
|
+
}
|
|
144
|
+
function inferFocusFromBranch(branch) {
|
|
145
|
+
if (!branch ||
|
|
146
|
+
branch === 'main' ||
|
|
147
|
+
branch === 'master' ||
|
|
148
|
+
branch === 'develop' ||
|
|
149
|
+
branch === 'HEAD') {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
const prefixPattern = /^(?:feature|feat|fix|bugfix|hotfix|chore|refactor|docs|test|ci)\//i;
|
|
153
|
+
const isFix = /^(?:fix|bugfix|hotfix)\//i.test(branch);
|
|
154
|
+
const stripped = branch.replace(prefixPattern, '');
|
|
155
|
+
const cleaned = stripped
|
|
156
|
+
.replace(/[-_/]/g, ' ')
|
|
157
|
+
.replace(/^\d+\s*/, '')
|
|
158
|
+
.trim();
|
|
159
|
+
if (!cleaned) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
return isFix ? `${cleaned} fix` : cleaned;
|
|
163
|
+
}
|
|
164
|
+
function inferFocusFromFiles(files) {
|
|
165
|
+
if (files.length === 0) {
|
|
166
|
+
return 'unknown files';
|
|
167
|
+
}
|
|
168
|
+
const dirs = files
|
|
169
|
+
.map((f) => {
|
|
170
|
+
const parts = f.replace(/\\/g, '/').split('/');
|
|
171
|
+
return parts.length > 1 ? parts.slice(0, -1).join('/') : '';
|
|
172
|
+
})
|
|
173
|
+
.filter((d) => d.length > 0);
|
|
174
|
+
if (dirs.length > 0) {
|
|
175
|
+
const counts = new Map();
|
|
176
|
+
for (const dir of dirs) {
|
|
177
|
+
counts.set(dir, (counts.get(dir) ?? 0) + 1);
|
|
178
|
+
}
|
|
179
|
+
let topDir = '';
|
|
180
|
+
let topCount = 0;
|
|
181
|
+
for (const [dir, count] of counts) {
|
|
182
|
+
if (count > topCount) {
|
|
183
|
+
topDir = dir;
|
|
184
|
+
topCount = count;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (topDir) {
|
|
188
|
+
return `files in ${topDir}`;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const names = files.slice(0, 3).map((f) => {
|
|
192
|
+
const parts = f.replace(/\\/g, '/').split('/');
|
|
193
|
+
return parts[parts.length - 1];
|
|
194
|
+
});
|
|
195
|
+
return names.join(', ');
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=reentry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reentry.js","sourceRoot":"","sources":["../../src/utils/reentry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a timestamp as a human-readable relative time string.
|
|
3
|
+
* Copied from apps/extension/src/utils/timeUtils.ts. Keep in sync manually.
|
|
4
|
+
*/
|
|
5
|
+
export function formatRelativeTime(timestamp) {
|
|
6
|
+
const now = Date.now();
|
|
7
|
+
const then = new Date(timestamp).getTime();
|
|
8
|
+
const diffMs = now - then;
|
|
9
|
+
if (isNaN(diffMs)) {
|
|
10
|
+
return 'unknown time';
|
|
11
|
+
}
|
|
12
|
+
if (diffMs < 0) {
|
|
13
|
+
return 'in the future';
|
|
14
|
+
}
|
|
15
|
+
const seconds = Math.floor(diffMs / 1000);
|
|
16
|
+
const minutes = Math.floor(seconds / 60);
|
|
17
|
+
const hours = Math.floor(minutes / 60);
|
|
18
|
+
const days = Math.floor(hours / 24);
|
|
19
|
+
const weeks = Math.floor(days / 7);
|
|
20
|
+
const months = Math.floor(days / 30);
|
|
21
|
+
const years = Math.floor(days / 365);
|
|
22
|
+
if (seconds < 10) {
|
|
23
|
+
return 'just now';
|
|
24
|
+
}
|
|
25
|
+
else if (seconds < 60) {
|
|
26
|
+
return `${seconds} seconds ago`;
|
|
27
|
+
}
|
|
28
|
+
else if (minutes < 60) {
|
|
29
|
+
return minutes === 1 ? '1 minute ago' : `${minutes} minutes ago`;
|
|
30
|
+
}
|
|
31
|
+
else if (hours < 24) {
|
|
32
|
+
return hours === 1 ? '1 hour ago' : `${hours} hours ago`;
|
|
33
|
+
}
|
|
34
|
+
else if (days < 7) {
|
|
35
|
+
return days === 1 ? '1 day ago' : `${days} days ago`;
|
|
36
|
+
}
|
|
37
|
+
else if (weeks < 4) {
|
|
38
|
+
return weeks === 1 ? '1 week ago' : `${weeks} weeks ago`;
|
|
39
|
+
}
|
|
40
|
+
else if (months < 12) {
|
|
41
|
+
return months === 1 ? '1 month ago' : `${months} months ago`;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return years === 1 ? '1 year ago' : `${years} years ago`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=timeUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeUtils.js","sourceRoot":"","sources":["../../src/utils/timeUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC;IAE1B,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAClB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;IAErC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACjB,OAAO,UAAU,CAAC;IACpB,CAAC;SAAM,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACxB,OAAO,GAAG,OAAO,cAAc,CAAC;IAClC,CAAC;SAAM,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACxB,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,cAAc,CAAC;IACnE,CAAC;SAAM,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QACtB,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,KAAK,YAAY,CAAC;IAC3D,CAAC;SAAM,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,WAAW,CAAC;IACvD,CAAC;SAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,KAAK,YAAY,CAAC;IAC3D,CAAC;SAAM,IAAI,MAAM,GAAG,EAAE,EAAE,CAAC;QACvB,OAAO,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,aAAa,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,KAAK,YAAY,CAAC;IAC3D,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@keepgoingdev/mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"keepgoing-mcp": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc -p ./tsconfig.json",
|
|
14
|
+
"watch": "tsc -watch -p ./tsconfig.json",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@keepgoingdev/shared": "0.1.0",
|
|
19
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
20
|
+
"zod": "^3.23.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^20.11.0",
|
|
24
|
+
"typescript": "^5.3.0"
|
|
25
|
+
}
|
|
26
|
+
}
|