@memnexus-ai/cli 1.7.61 → 1.7.63
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/commands/commit-context.d.ts +10 -0
- package/dist/commands/commit-context.d.ts.map +1 -0
- package/dist/commands/commit-context.js +356 -0
- package/dist/commands/commit-context.js.map +1 -0
- package/dist/commands/hook.d.ts +15 -0
- package/dist/commands/hook.d.ts.map +1 -0
- package/dist/commands/hook.js +201 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +42 -0
- package/dist/commands/setup.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-help.d.ts.map +1 -1
- package/dist/lib/agent-help.js +37 -0
- package/dist/lib/agent-help.js.map +1 -1
- package/dist/lib/commit-context/fact-enricher.d.ts +40 -0
- package/dist/lib/commit-context/fact-enricher.d.ts.map +1 -0
- package/dist/lib/commit-context/fact-enricher.js +46 -0
- package/dist/lib/commit-context/fact-enricher.js.map +1 -0
- package/dist/lib/commit-context/git-reader.d.ts +23 -0
- package/dist/lib/commit-context/git-reader.d.ts.map +1 -0
- package/dist/lib/commit-context/git-reader.js +108 -0
- package/dist/lib/commit-context/git-reader.js.map +1 -0
- package/dist/lib/commit-context/heuristic-summarizer.d.ts +18 -0
- package/dist/lib/commit-context/heuristic-summarizer.d.ts.map +1 -0
- package/dist/lib/commit-context/heuristic-summarizer.js +124 -0
- package/dist/lib/commit-context/heuristic-summarizer.js.map +1 -0
- package/dist/lib/commit-context/hook-installer.d.ts +18 -0
- package/dist/lib/commit-context/hook-installer.d.ts.map +1 -0
- package/dist/lib/commit-context/hook-installer.js +140 -0
- package/dist/lib/commit-context/hook-installer.js.map +1 -0
- package/dist/lib/commit-context/index.d.ts +15 -0
- package/dist/lib/commit-context/index.d.ts.map +1 -0
- package/dist/lib/commit-context/index.js +55 -0
- package/dist/lib/commit-context/index.js.map +1 -0
- package/dist/lib/commit-context/llm-summarizer.d.ts +9 -0
- package/dist/lib/commit-context/llm-summarizer.d.ts.map +1 -0
- package/dist/lib/commit-context/llm-summarizer.js +145 -0
- package/dist/lib/commit-context/llm-summarizer.js.map +1 -0
- package/dist/lib/commit-context/local-cache.d.ts +35 -0
- package/dist/lib/commit-context/local-cache.d.ts.map +1 -0
- package/dist/lib/commit-context/local-cache.js +161 -0
- package/dist/lib/commit-context/local-cache.js.map +1 -0
- package/dist/lib/commit-context/privacy-filter.d.ts +13 -0
- package/dist/lib/commit-context/privacy-filter.d.ts.map +1 -0
- package/dist/lib/commit-context/privacy-filter.js +46 -0
- package/dist/lib/commit-context/privacy-filter.js.map +1 -0
- package/dist/lib/commit-context/session-reader.d.ts +36 -0
- package/dist/lib/commit-context/session-reader.d.ts.map +1 -0
- package/dist/lib/commit-context/session-reader.js +277 -0
- package/dist/lib/commit-context/session-reader.js.map +1 -0
- package/dist/lib/commit-context/types.d.ts +62 -0
- package/dist/lib/commit-context/types.d.ts.map +1 -0
- package/dist/lib/commit-context/types.js +6 -0
- package/dist/lib/commit-context/types.js.map +1 -0
- package/dist/lib/setup/rules-templates.d.ts.map +1 -1
- package/dist/lib/setup/rules-templates.js +2 -0
- package/dist/lib/setup/rules-templates.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isTrivialCommit = isTrivialCommit;
|
|
4
|
+
exports.summarizeCommit = summarizeCommit;
|
|
5
|
+
/** Patterns for trivial commits that should be skipped */
|
|
6
|
+
const TRIVIAL_PATTERNS = [
|
|
7
|
+
/^Merge\s+(branch|pull\s+request|remote)/i,
|
|
8
|
+
/^v?\d+\.\d+\.\d+/, // Version bumps like v1.2.3
|
|
9
|
+
/^\[skip ci\]/i,
|
|
10
|
+
/^wip$/i,
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
* Check if a commit is trivial and should be skipped.
|
|
14
|
+
*/
|
|
15
|
+
function isTrivialCommit(git) {
|
|
16
|
+
// Merge commits
|
|
17
|
+
if (git.isMergeCommit) {
|
|
18
|
+
return { trivial: true, reason: 'merge commit' };
|
|
19
|
+
}
|
|
20
|
+
// Pattern-based detection
|
|
21
|
+
for (const pattern of TRIVIAL_PATTERNS) {
|
|
22
|
+
if (pattern.test(git.message)) {
|
|
23
|
+
// [skip ci] with <=1 file is trivial; with more files, it's worth capturing
|
|
24
|
+
if (/^\[skip ci\]/i.test(git.message) && git.filesChanged.length > 1) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
return { trivial: true, reason: `matches pattern: ${pattern.source}` };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Bare "wip" with <=1 file
|
|
31
|
+
if (/^wip$/i.test(git.message) && git.filesChanged.length <= 1) {
|
|
32
|
+
return { trivial: true, reason: 'bare wip commit' };
|
|
33
|
+
}
|
|
34
|
+
return { trivial: false };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build the structured markdown content for a commit context memory.
|
|
38
|
+
*/
|
|
39
|
+
function buildContent(git, session) {
|
|
40
|
+
const lines = [];
|
|
41
|
+
// Header
|
|
42
|
+
lines.push(`## CommitContext: ${git.message} (${git.shortSha})`);
|
|
43
|
+
lines.push('');
|
|
44
|
+
// Metadata
|
|
45
|
+
lines.push(`**Commit:** ${git.sha}`);
|
|
46
|
+
lines.push(`**Branch:** ${git.branch}`);
|
|
47
|
+
if (session) {
|
|
48
|
+
const modelPart = session.model ? ` | **Model:** ${session.model}` : '';
|
|
49
|
+
lines.push(`**Agent:** ${session.agent}${modelPart}`);
|
|
50
|
+
}
|
|
51
|
+
// Files changed
|
|
52
|
+
const changeStats = `+${git.insertions} -${git.deletions}`;
|
|
53
|
+
lines.push(`**Files changed** (${git.filesChanged.length}): ${changeStats}`);
|
|
54
|
+
for (const file of git.filesChanged.slice(0, 20)) {
|
|
55
|
+
lines.push(`- ${file}`);
|
|
56
|
+
}
|
|
57
|
+
if (git.filesChanged.length > 20) {
|
|
58
|
+
lines.push(`- ... and ${git.filesChanged.length - 20} more`);
|
|
59
|
+
}
|
|
60
|
+
// Session info
|
|
61
|
+
if (session && session.totalToolCalls > 0) {
|
|
62
|
+
lines.push('');
|
|
63
|
+
lines.push(`### Tool calls (${session.totalToolCalls})`);
|
|
64
|
+
const toolSummary = session.toolCalls
|
|
65
|
+
.slice(0, 8)
|
|
66
|
+
.map((tc) => `${tc.name}: ${tc.count}`)
|
|
67
|
+
.join(', ');
|
|
68
|
+
lines.push(toolSummary);
|
|
69
|
+
}
|
|
70
|
+
if (session && session.recentPrompts.length > 0) {
|
|
71
|
+
lines.push('');
|
|
72
|
+
lines.push('### Recent prompts');
|
|
73
|
+
for (const prompt of session.recentPrompts) {
|
|
74
|
+
const truncated = prompt.length > 150 ? prompt.slice(0, 150) + '...' : prompt;
|
|
75
|
+
lines.push(`> ${truncated}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (session && session.errors.length > 0) {
|
|
79
|
+
lines.push('');
|
|
80
|
+
lines.push('### Errors encountered');
|
|
81
|
+
for (const err of session.errors) {
|
|
82
|
+
lines.push(`- ${err}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return lines.join('\n');
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Build the context field (max 200 chars).
|
|
89
|
+
* Format: "commit:<sha> branch:<branch> agent:<agent>"
|
|
90
|
+
*/
|
|
91
|
+
function buildContextField(git, session) {
|
|
92
|
+
const agent = session?.agent || 'unknown';
|
|
93
|
+
const field = `commit:${git.shortSha} branch:${git.branch} agent:${agent}`;
|
|
94
|
+
return field.slice(0, 200);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Summarize a commit into a CommitContextData structure.
|
|
98
|
+
*/
|
|
99
|
+
function summarizeCommit(git, session) {
|
|
100
|
+
const { trivial, reason } = isTrivialCommit(git);
|
|
101
|
+
if (trivial) {
|
|
102
|
+
return {
|
|
103
|
+
git,
|
|
104
|
+
session,
|
|
105
|
+
content: '',
|
|
106
|
+
contextField: '',
|
|
107
|
+
topics: ['commit-context'],
|
|
108
|
+
skipped: true,
|
|
109
|
+
skipReason: reason,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const content = buildContent(git, session);
|
|
113
|
+
const contextField = buildContextField(git, session);
|
|
114
|
+
const topics = ['commit-context'];
|
|
115
|
+
return {
|
|
116
|
+
git,
|
|
117
|
+
session,
|
|
118
|
+
content,
|
|
119
|
+
contextField,
|
|
120
|
+
topics,
|
|
121
|
+
skipped: false,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=heuristic-summarizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heuristic-summarizer.js","sourceRoot":"","sources":["../../../src/lib/commit-context/heuristic-summarizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface HookInstallResult {
|
|
2
|
+
hookPath: string;
|
|
3
|
+
action: 'created' | 'appended' | 'already-installed';
|
|
4
|
+
gitignoreUpdated: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Install the post-commit hook for CommitContext.
|
|
8
|
+
*
|
|
9
|
+
* @param projectRoot - Root of the git project
|
|
10
|
+
* @param dryRun - If true, don't write files
|
|
11
|
+
* @returns Install result
|
|
12
|
+
*/
|
|
13
|
+
export declare function installHook(projectRoot: string, dryRun?: boolean): HookInstallResult;
|
|
14
|
+
/**
|
|
15
|
+
* Check if the post-commit hook is already installed.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isHookInstalled(projectRoot: string): boolean;
|
|
18
|
+
//# sourceMappingURL=hook-installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-installer.d.ts","sourceRoot":"","sources":["../../../src/lib/commit-context/hook-installer.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,mBAAmB,CAAC;IACrD,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,GAAE,OAAe,GAAG,iBAAiB,CA0B3F;AA+CD;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAQ5D"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.installHook = installHook;
|
|
37
|
+
exports.isHookInstalled = isHookInstalled;
|
|
38
|
+
/**
|
|
39
|
+
* Hook Installer — installs post-commit git hook for CommitContext capture.
|
|
40
|
+
*
|
|
41
|
+
* Detection order:
|
|
42
|
+
* 1. .husky/ directory → create/append .husky/post-commit
|
|
43
|
+
* 2. .git/hooks/ fallback → create/append .git/hooks/post-commit
|
|
44
|
+
*
|
|
45
|
+
* Always idempotent — checks for existing `mx hook post-commit` line.
|
|
46
|
+
* Also adds .mx/ to .gitignore.
|
|
47
|
+
*/
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const HOOK_MARKER = 'mx hook post-commit';
|
|
51
|
+
const HOOK_SCRIPT = `#!/bin/sh
|
|
52
|
+
# MemNexus CommitContext — capture commit reasoning automatically
|
|
53
|
+
mx hook post-commit &
|
|
54
|
+
`;
|
|
55
|
+
/**
|
|
56
|
+
* Install the post-commit hook for CommitContext.
|
|
57
|
+
*
|
|
58
|
+
* @param projectRoot - Root of the git project
|
|
59
|
+
* @param dryRun - If true, don't write files
|
|
60
|
+
* @returns Install result
|
|
61
|
+
*/
|
|
62
|
+
function installHook(projectRoot, dryRun = false) {
|
|
63
|
+
const hookPath = resolveHookPath(projectRoot);
|
|
64
|
+
const gitignoreUpdated = ensureGitignore(projectRoot, dryRun);
|
|
65
|
+
// Check if already installed
|
|
66
|
+
if (fs.existsSync(hookPath)) {
|
|
67
|
+
const existing = fs.readFileSync(hookPath, 'utf8');
|
|
68
|
+
if (existing.includes(HOOK_MARKER)) {
|
|
69
|
+
return { hookPath, action: 'already-installed', gitignoreUpdated };
|
|
70
|
+
}
|
|
71
|
+
// Append to existing hook
|
|
72
|
+
if (!dryRun) {
|
|
73
|
+
const appendContent = `\n# MemNexus CommitContext — capture commit reasoning automatically\nmx hook post-commit &\n`;
|
|
74
|
+
fs.appendFileSync(hookPath, appendContent, 'utf8');
|
|
75
|
+
}
|
|
76
|
+
return { hookPath, action: 'appended', gitignoreUpdated };
|
|
77
|
+
}
|
|
78
|
+
// Create new hook file
|
|
79
|
+
if (!dryRun) {
|
|
80
|
+
const dir = path.dirname(hookPath);
|
|
81
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
82
|
+
fs.writeFileSync(hookPath, HOOK_SCRIPT, { mode: 0o755, encoding: 'utf8' });
|
|
83
|
+
}
|
|
84
|
+
return { hookPath, action: 'created', gitignoreUpdated };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolve the hook file path (husky or .git/hooks).
|
|
88
|
+
*/
|
|
89
|
+
function resolveHookPath(projectRoot) {
|
|
90
|
+
// Check for husky directory
|
|
91
|
+
const huskyDir = path.join(projectRoot, '.husky');
|
|
92
|
+
if (fs.existsSync(huskyDir) && fs.statSync(huskyDir).isDirectory()) {
|
|
93
|
+
return path.join(huskyDir, 'post-commit');
|
|
94
|
+
}
|
|
95
|
+
// Fall back to .git/hooks
|
|
96
|
+
return path.join(projectRoot, '.git', 'hooks', 'post-commit');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Ensure .mx/ is in .gitignore.
|
|
100
|
+
* Returns true if .gitignore was updated.
|
|
101
|
+
*/
|
|
102
|
+
function ensureGitignore(projectRoot, dryRun) {
|
|
103
|
+
const gitignorePath = path.join(projectRoot, '.gitignore');
|
|
104
|
+
const entry = '.mx/';
|
|
105
|
+
try {
|
|
106
|
+
if (fs.existsSync(gitignorePath)) {
|
|
107
|
+
const content = fs.readFileSync(gitignorePath, 'utf8');
|
|
108
|
+
if (content.includes(entry)) {
|
|
109
|
+
return false; // Already present
|
|
110
|
+
}
|
|
111
|
+
if (!dryRun) {
|
|
112
|
+
const separator = content.endsWith('\n') ? '' : '\n';
|
|
113
|
+
fs.appendFileSync(gitignorePath, `${separator}${entry}\n`, 'utf8');
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
// No .gitignore — create one
|
|
118
|
+
if (!dryRun) {
|
|
119
|
+
fs.writeFileSync(gitignorePath, `${entry}\n`, 'utf8');
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Check if the post-commit hook is already installed.
|
|
129
|
+
*/
|
|
130
|
+
function isHookInstalled(projectRoot) {
|
|
131
|
+
const hookPath = resolveHookPath(projectRoot);
|
|
132
|
+
try {
|
|
133
|
+
const content = fs.readFileSync(hookPath, 'utf8');
|
|
134
|
+
return content.includes(HOOK_MARKER);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=hook-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-installer.js","sourceRoot":"","sources":["../../../src/lib/commit-context/hook-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CommitContext — automatic commit context capture.
|
|
3
|
+
*
|
|
4
|
+
* Barrel exports for all commit-context modules.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types';
|
|
7
|
+
export { readGitContext, parseShortStat, readDiffContent } from './git-reader';
|
|
8
|
+
export { readSessionContext, findClaudeProjectDir, findLatestSession, parseSessionTail, deriveProjectDirName, getTranscriptExcerpt, } from './session-reader';
|
|
9
|
+
export { summarizeCommit, isTrivialCommit } from './heuristic-summarizer';
|
|
10
|
+
export { summarizeWithLLM } from './llm-summarizer';
|
|
11
|
+
export { sanitize } from './privacy-filter';
|
|
12
|
+
export { enrichCommitFacts } from './fact-enricher';
|
|
13
|
+
export { writeCache, readCache, listCache, markSynced, markSyncError, getCacheDir, findProjectRoot, } from './local-cache';
|
|
14
|
+
export { installHook, isHookInstalled } from './hook-installer';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/commit-context/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,UAAU,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,aAAa,EACb,WAAW,EACX,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.isHookInstalled = exports.installHook = exports.findProjectRoot = exports.getCacheDir = exports.markSyncError = exports.markSynced = exports.listCache = exports.readCache = exports.writeCache = exports.enrichCommitFacts = exports.sanitize = exports.summarizeWithLLM = exports.isTrivialCommit = exports.summarizeCommit = exports.getTranscriptExcerpt = exports.deriveProjectDirName = exports.parseSessionTail = exports.findLatestSession = exports.findClaudeProjectDir = exports.readSessionContext = exports.readDiffContent = exports.parseShortStat = exports.readGitContext = void 0;
|
|
18
|
+
/**
|
|
19
|
+
* CommitContext — automatic commit context capture.
|
|
20
|
+
*
|
|
21
|
+
* Barrel exports for all commit-context modules.
|
|
22
|
+
*/
|
|
23
|
+
__exportStar(require("./types"), exports);
|
|
24
|
+
var git_reader_1 = require("./git-reader");
|
|
25
|
+
Object.defineProperty(exports, "readGitContext", { enumerable: true, get: function () { return git_reader_1.readGitContext; } });
|
|
26
|
+
Object.defineProperty(exports, "parseShortStat", { enumerable: true, get: function () { return git_reader_1.parseShortStat; } });
|
|
27
|
+
Object.defineProperty(exports, "readDiffContent", { enumerable: true, get: function () { return git_reader_1.readDiffContent; } });
|
|
28
|
+
var session_reader_1 = require("./session-reader");
|
|
29
|
+
Object.defineProperty(exports, "readSessionContext", { enumerable: true, get: function () { return session_reader_1.readSessionContext; } });
|
|
30
|
+
Object.defineProperty(exports, "findClaudeProjectDir", { enumerable: true, get: function () { return session_reader_1.findClaudeProjectDir; } });
|
|
31
|
+
Object.defineProperty(exports, "findLatestSession", { enumerable: true, get: function () { return session_reader_1.findLatestSession; } });
|
|
32
|
+
Object.defineProperty(exports, "parseSessionTail", { enumerable: true, get: function () { return session_reader_1.parseSessionTail; } });
|
|
33
|
+
Object.defineProperty(exports, "deriveProjectDirName", { enumerable: true, get: function () { return session_reader_1.deriveProjectDirName; } });
|
|
34
|
+
Object.defineProperty(exports, "getTranscriptExcerpt", { enumerable: true, get: function () { return session_reader_1.getTranscriptExcerpt; } });
|
|
35
|
+
var heuristic_summarizer_1 = require("./heuristic-summarizer");
|
|
36
|
+
Object.defineProperty(exports, "summarizeCommit", { enumerable: true, get: function () { return heuristic_summarizer_1.summarizeCommit; } });
|
|
37
|
+
Object.defineProperty(exports, "isTrivialCommit", { enumerable: true, get: function () { return heuristic_summarizer_1.isTrivialCommit; } });
|
|
38
|
+
var llm_summarizer_1 = require("./llm-summarizer");
|
|
39
|
+
Object.defineProperty(exports, "summarizeWithLLM", { enumerable: true, get: function () { return llm_summarizer_1.summarizeWithLLM; } });
|
|
40
|
+
var privacy_filter_1 = require("./privacy-filter");
|
|
41
|
+
Object.defineProperty(exports, "sanitize", { enumerable: true, get: function () { return privacy_filter_1.sanitize; } });
|
|
42
|
+
var fact_enricher_1 = require("./fact-enricher");
|
|
43
|
+
Object.defineProperty(exports, "enrichCommitFacts", { enumerable: true, get: function () { return fact_enricher_1.enrichCommitFacts; } });
|
|
44
|
+
var local_cache_1 = require("./local-cache");
|
|
45
|
+
Object.defineProperty(exports, "writeCache", { enumerable: true, get: function () { return local_cache_1.writeCache; } });
|
|
46
|
+
Object.defineProperty(exports, "readCache", { enumerable: true, get: function () { return local_cache_1.readCache; } });
|
|
47
|
+
Object.defineProperty(exports, "listCache", { enumerable: true, get: function () { return local_cache_1.listCache; } });
|
|
48
|
+
Object.defineProperty(exports, "markSynced", { enumerable: true, get: function () { return local_cache_1.markSynced; } });
|
|
49
|
+
Object.defineProperty(exports, "markSyncError", { enumerable: true, get: function () { return local_cache_1.markSyncError; } });
|
|
50
|
+
Object.defineProperty(exports, "getCacheDir", { enumerable: true, get: function () { return local_cache_1.getCacheDir; } });
|
|
51
|
+
Object.defineProperty(exports, "findProjectRoot", { enumerable: true, get: function () { return local_cache_1.findProjectRoot; } });
|
|
52
|
+
var hook_installer_1 = require("./hook-installer");
|
|
53
|
+
Object.defineProperty(exports, "installHook", { enumerable: true, get: function () { return hook_installer_1.installHook; } });
|
|
54
|
+
Object.defineProperty(exports, "isHookInstalled", { enumerable: true, get: function () { return hook_installer_1.isHookInstalled; } });
|
|
55
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/commit-context/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA;;;;GAIG;AACH,0CAAwB;AACxB,2CAA+E;AAAtE,4GAAA,cAAc,OAAA;AAAE,4GAAA,cAAc,OAAA;AAAE,6GAAA,eAAe,OAAA;AACxD,mDAO0B;AANxB,oHAAA,kBAAkB,OAAA;AAClB,sHAAA,oBAAoB,OAAA;AACpB,mHAAA,iBAAiB,OAAA;AACjB,kHAAA,gBAAgB,OAAA;AAChB,sHAAA,oBAAoB,OAAA;AACpB,sHAAA,oBAAoB,OAAA;AAEtB,+DAA0E;AAAjE,uHAAA,eAAe,OAAA;AAAE,uHAAA,eAAe,OAAA;AACzC,mDAAoD;AAA3C,kHAAA,gBAAgB,OAAA;AACzB,mDAA4C;AAAnC,0GAAA,QAAQ,OAAA;AACjB,iDAAoD;AAA3C,kHAAA,iBAAiB,OAAA;AAC1B,6CAQuB;AAPrB,yGAAA,UAAU,OAAA;AACV,wGAAA,SAAS,OAAA;AACT,wGAAA,SAAS,OAAA;AACT,yGAAA,UAAU,OAAA;AACV,4GAAA,aAAa,OAAA;AACb,0GAAA,WAAW,OAAA;AACX,8GAAA,eAAe,OAAA;AAEjB,mDAAgE;AAAvD,6GAAA,WAAW,OAAA;AAAE,iHAAA,eAAe,OAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GitContext, SessionContext, CommitContextData } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Summarize a commit using the Anthropic LLM API.
|
|
4
|
+
*
|
|
5
|
+
* @throws Error if ANTHROPIC_API_KEY is not set
|
|
6
|
+
* @throws Error if the API call fails
|
|
7
|
+
*/
|
|
8
|
+
export declare function summarizeWithLLM(git: GitContext, session: SessionContext | undefined, diffContent: string, transcriptExcerpt: string, sessionMemories?: string): Promise<CommitContextData>;
|
|
9
|
+
//# sourceMappingURL=llm-summarizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-summarizer.d.ts","sourceRoot":"","sources":["../../../src/lib/commit-context/llm-summarizer.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAuD7E;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,GAAG,SAAS,EACnC,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,iBAAiB,CAAC,CAwF5B"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.summarizeWithLLM = summarizeWithLLM;
|
|
7
|
+
/**
|
|
8
|
+
* LLM Summarizer — calls Anthropic Haiku to produce rich distilled commit context.
|
|
9
|
+
*
|
|
10
|
+
* Requires ANTHROPIC_API_KEY. Fails with clear error if not set.
|
|
11
|
+
* Use --summarizer heuristic to opt into heuristic-only mode (no key required).
|
|
12
|
+
*/
|
|
13
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
14
|
+
const privacy_filter_1 = require("./privacy-filter");
|
|
15
|
+
const MODEL = 'claude-haiku-4-5-20251001';
|
|
16
|
+
const MAX_OUTPUT_TOKENS = 1024;
|
|
17
|
+
const DISTILLATION_PROMPT = `You are a commit context analyzer. Given git metadata, a diff, and optionally an AI agent transcript, produce a structured markdown summary of what was done and why.
|
|
18
|
+
|
|
19
|
+
Output format (use only sections that have content):
|
|
20
|
+
|
|
21
|
+
## CommitContext: <commit message> (<short sha>)
|
|
22
|
+
|
|
23
|
+
<!-- commit-metadata
|
|
24
|
+
sha: <full sha>
|
|
25
|
+
short_sha: <short sha>
|
|
26
|
+
branch: <branch>
|
|
27
|
+
author: <author>
|
|
28
|
+
timestamp: <timestamp>
|
|
29
|
+
message: <commit message>
|
|
30
|
+
files:
|
|
31
|
+
<file list, one per line with " - " prefix>
|
|
32
|
+
insertions: <number>
|
|
33
|
+
deletions: <number>
|
|
34
|
+
parent_sha: <if available>
|
|
35
|
+
agent: <agent or "none">
|
|
36
|
+
model: <model or "none">
|
|
37
|
+
-->
|
|
38
|
+
|
|
39
|
+
**Branch:** <branch>
|
|
40
|
+
**Files changed** (<count>): +<insertions> -<deletions>
|
|
41
|
+
<file list as bullet points>
|
|
42
|
+
|
|
43
|
+
### What changed
|
|
44
|
+
<1-3 sentence summary of the actual code changes>
|
|
45
|
+
|
|
46
|
+
### Key decisions
|
|
47
|
+
<Bullet points of important technical decisions made, if evident from the diff or transcript>
|
|
48
|
+
|
|
49
|
+
### Debugging path
|
|
50
|
+
<If there was debugging involved, summarize the path from problem to solution>
|
|
51
|
+
|
|
52
|
+
### Patterns used
|
|
53
|
+
<Notable design patterns, conventions, or approaches used>
|
|
54
|
+
|
|
55
|
+
### Gotchas
|
|
56
|
+
<Any pitfalls, edge cases, or non-obvious things to watch out for>
|
|
57
|
+
|
|
58
|
+
Rules:
|
|
59
|
+
- Be concise — this is a reference document, not a narrative
|
|
60
|
+
- Only include sections that have actual content
|
|
61
|
+
- Focus on the "why" more than the "what" when possible
|
|
62
|
+
- If no transcript is available, focus on what the diff tells you
|
|
63
|
+
- Include file paths in backticks
|
|
64
|
+
- Strip any secrets or API keys from the output`;
|
|
65
|
+
/**
|
|
66
|
+
* Summarize a commit using the Anthropic LLM API.
|
|
67
|
+
*
|
|
68
|
+
* @throws Error if ANTHROPIC_API_KEY is not set
|
|
69
|
+
* @throws Error if the API call fails
|
|
70
|
+
*/
|
|
71
|
+
async function summarizeWithLLM(git, session, diffContent, transcriptExcerpt, sessionMemories) {
|
|
72
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
73
|
+
if (!apiKey) {
|
|
74
|
+
throw new Error('ANTHROPIC_API_KEY is not set. LLM summarization requires an Anthropic API key.\n' +
|
|
75
|
+
'Set it with: export ANTHROPIC_API_KEY=your-key\n' +
|
|
76
|
+
'Or use --summarizer heuristic to skip LLM summarization.');
|
|
77
|
+
}
|
|
78
|
+
const client = new sdk_1.default({ apiKey });
|
|
79
|
+
// Build the user message with all available context
|
|
80
|
+
const parts = [];
|
|
81
|
+
parts.push('## Git Metadata');
|
|
82
|
+
parts.push(`- SHA: ${git.sha}`);
|
|
83
|
+
parts.push(`- Short SHA: ${git.shortSha}`);
|
|
84
|
+
parts.push(`- Branch: ${git.branch}`);
|
|
85
|
+
parts.push(`- Message: ${git.message}`);
|
|
86
|
+
parts.push(`- Author: ${git.author}`);
|
|
87
|
+
parts.push(`- Timestamp: ${git.timestamp}`);
|
|
88
|
+
parts.push(`- Files (${git.filesChanged.length}): ${git.filesChanged.slice(0, 20).join(', ')}`);
|
|
89
|
+
parts.push(`- Changes: +${git.insertions} -${git.deletions}`);
|
|
90
|
+
if (diffContent) {
|
|
91
|
+
parts.push('\n## Diff Content');
|
|
92
|
+
parts.push(diffContent);
|
|
93
|
+
}
|
|
94
|
+
if (session) {
|
|
95
|
+
parts.push('\n## AI Agent Session');
|
|
96
|
+
parts.push(`- Agent: ${session.agent}`);
|
|
97
|
+
if (session.model)
|
|
98
|
+
parts.push(`- Model: ${session.model}`);
|
|
99
|
+
if (session.totalToolCalls > 0) {
|
|
100
|
+
const tools = session.toolCalls
|
|
101
|
+
.slice(0, 8)
|
|
102
|
+
.map((t) => `${t.name}:${t.count}`)
|
|
103
|
+
.join(', ');
|
|
104
|
+
parts.push(`- Tool calls (${session.totalToolCalls}): ${tools}`);
|
|
105
|
+
}
|
|
106
|
+
if (session.errors.length > 0) {
|
|
107
|
+
parts.push(`- Errors: ${session.errors.join('; ')}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (transcriptExcerpt) {
|
|
111
|
+
parts.push('\n## Transcript Excerpt');
|
|
112
|
+
parts.push(transcriptExcerpt);
|
|
113
|
+
}
|
|
114
|
+
if (sessionMemories) {
|
|
115
|
+
parts.push('\n## Recent Session Memories');
|
|
116
|
+
parts.push(sessionMemories);
|
|
117
|
+
}
|
|
118
|
+
const userMessage = (0, privacy_filter_1.sanitize)(parts.join('\n'));
|
|
119
|
+
const response = await client.messages.create({
|
|
120
|
+
model: MODEL,
|
|
121
|
+
max_tokens: MAX_OUTPUT_TOKENS,
|
|
122
|
+
system: DISTILLATION_PROMPT,
|
|
123
|
+
messages: [{ role: 'user', content: userMessage }],
|
|
124
|
+
});
|
|
125
|
+
// Extract text from response
|
|
126
|
+
const content = response.content
|
|
127
|
+
.filter((block) => block.type === 'text')
|
|
128
|
+
.map((block) => block.text)
|
|
129
|
+
.join('\n');
|
|
130
|
+
const sanitizedContent = (0, privacy_filter_1.sanitize)(content);
|
|
131
|
+
// Build context field
|
|
132
|
+
const agent = session?.agent || 'unknown';
|
|
133
|
+
const contextField = `commit:${git.shortSha} branch:${git.branch} agent:${agent}`.slice(0, 200);
|
|
134
|
+
// Build topics
|
|
135
|
+
const topics = ['commit-context', `branch:${git.branch}`];
|
|
136
|
+
return {
|
|
137
|
+
git,
|
|
138
|
+
session,
|
|
139
|
+
content: sanitizedContent,
|
|
140
|
+
contextField,
|
|
141
|
+
topics,
|
|
142
|
+
skipped: false,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=llm-summarizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-summarizer.js","sourceRoot":"","sources":["../../../src/lib/commit-context/llm-summarizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CacheEntry } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Get the cache directory path for a project root.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getCacheDir(projectRoot: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Write a cache entry to disk.
|
|
8
|
+
*/
|
|
9
|
+
export declare function writeCache(projectRoot: string, entry: CacheEntry): void;
|
|
10
|
+
/**
|
|
11
|
+
* Read a cache entry by short SHA.
|
|
12
|
+
* Returns undefined if not found.
|
|
13
|
+
*/
|
|
14
|
+
export declare function readCache(projectRoot: string, shortSha: string): CacheEntry | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* List all cached entries, optionally filtered by sync status.
|
|
17
|
+
* Returns entries sorted by timestamp (newest first).
|
|
18
|
+
*/
|
|
19
|
+
export declare function listCache(projectRoot: string, options?: {
|
|
20
|
+
unsynced?: boolean;
|
|
21
|
+
limit?: number;
|
|
22
|
+
}): CacheEntry[];
|
|
23
|
+
/**
|
|
24
|
+
* Mark a cache entry as synced with a memory ID.
|
|
25
|
+
*/
|
|
26
|
+
export declare function markSynced(projectRoot: string, shortSha: string, memoryId: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Mark a cache entry with a sync error.
|
|
29
|
+
*/
|
|
30
|
+
export declare function markSyncError(projectRoot: string, shortSha: string, error: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Find the git project root by looking for .git directory.
|
|
33
|
+
*/
|
|
34
|
+
export declare function findProjectRoot(cwd?: string): string | undefined;
|
|
35
|
+
//# sourceMappingURL=local-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-cache.d.ts","sourceRoot":"","sources":["../../../src/lib/commit-context/local-cache.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1C;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEvD;AAkBD;;GAEG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAIvE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAQvF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,UAAU,EAAE,CA4Bd;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQxF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAOxF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,SAAS,CAS/E"}
|