@hegel-dev/companion 1.0.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/README.md +84 -0
- package/dist/analyzers/prompt-analyzer.d.ts +7 -0
- package/dist/analyzers/prompt-analyzer.d.ts.map +1 -0
- package/dist/analyzers/prompt-analyzer.js +224 -0
- package/dist/analyzers/prompt-analyzer.js.map +1 -0
- package/dist/analyzers/response-analyzer.d.ts +6 -0
- package/dist/analyzers/response-analyzer.d.ts.map +1 -0
- package/dist/analyzers/response-analyzer.js +218 -0
- package/dist/analyzers/response-analyzer.js.map +1 -0
- package/dist/analyzers/session-analyzer.d.ts +10 -0
- package/dist/analyzers/session-analyzer.d.ts.map +1 -0
- package/dist/analyzers/session-analyzer.js +194 -0
- package/dist/analyzers/session-analyzer.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +27 -0
- package/dist/config.js.map +1 -0
- package/dist/debug-wrapper.d.ts +2 -0
- package/dist/debug-wrapper.d.ts.map +1 -0
- package/dist/debug-wrapper.js +55 -0
- package/dist/debug-wrapper.js.map +1 -0
- package/dist/dev-watch.d.ts +10 -0
- package/dist/dev-watch.d.ts.map +1 -0
- package/dist/dev-watch.js +55 -0
- package/dist/dev-watch.js.map +1 -0
- package/dist/format.d.ts +4 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +38 -0
- package/dist/format.js.map +1 -0
- package/dist/hook.d.ts +8 -0
- package/dist/hook.d.ts.map +1 -0
- package/dist/hook.js +320 -0
- package/dist/hook.js.map +1 -0
- package/dist/hooks-generator.d.ts +45 -0
- package/dist/hooks-generator.d.ts.map +1 -0
- package/dist/hooks-generator.js +120 -0
- package/dist/hooks-generator.js.map +1 -0
- package/dist/mcp.d.ts +10 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +173 -0
- package/dist/mcp.js.map +1 -0
- package/dist/prompts.d.ts +11 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +85 -0
- package/dist/prompts.js.map +1 -0
- package/dist/setup.d.ts +28 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +247 -0
- package/dist/setup.js.map +1 -0
- package/dist/state.d.ts +14 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +77 -0
- package/dist/state.js.map +1 -0
- package/dist/transcript.d.ts +32 -0
- package/dist/transcript.d.ts.map +1 -0
- package/dist/transcript.js +156 -0
- package/dist/transcript.js.map +1 -0
- package/dist/types.d.ts +137 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/hegel-vscode/hegel-companion-1.0.0.vsix +0 -0
- package/hegel.config.schema.json +63 -0
- package/package.json +59 -0
package/dist/state.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const STATE_DIR = ".hegel-state";
|
|
4
|
+
const SAFE_CONVERSATION_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
|
|
5
|
+
function createEmptyState(conversationId) {
|
|
6
|
+
return {
|
|
7
|
+
conversationId,
|
|
8
|
+
startedAt: Date.now(),
|
|
9
|
+
prompts: [],
|
|
10
|
+
responses: [],
|
|
11
|
+
fileEdits: [],
|
|
12
|
+
turnCount: 0,
|
|
13
|
+
compactionCount: 0,
|
|
14
|
+
concerns: [],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function isSafeConversationId(conversationId) {
|
|
18
|
+
return SAFE_CONVERSATION_ID.test(conversationId);
|
|
19
|
+
}
|
|
20
|
+
function statePath(conversationId) {
|
|
21
|
+
if (!isSafeConversationId(conversationId))
|
|
22
|
+
return null;
|
|
23
|
+
return join(STATE_DIR, `${conversationId}.json`);
|
|
24
|
+
}
|
|
25
|
+
export async function loadState(conversationId) {
|
|
26
|
+
const path = statePath(conversationId);
|
|
27
|
+
if (!path)
|
|
28
|
+
return createEmptyState(conversationId);
|
|
29
|
+
try {
|
|
30
|
+
const raw = await readFile(path, "utf-8");
|
|
31
|
+
return JSON.parse(raw);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return createEmptyState(conversationId);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function saveState(state) {
|
|
38
|
+
const path = statePath(state.conversationId);
|
|
39
|
+
if (!path)
|
|
40
|
+
return;
|
|
41
|
+
await mkdir(STATE_DIR, { recursive: true });
|
|
42
|
+
await writeFile(path, JSON.stringify(state, null, 2), "utf-8");
|
|
43
|
+
}
|
|
44
|
+
export function addPrompt(state, record) {
|
|
45
|
+
state.prompts.push(record);
|
|
46
|
+
state.turnCount++;
|
|
47
|
+
}
|
|
48
|
+
export function addResponse(state, record) {
|
|
49
|
+
state.responses.push(record);
|
|
50
|
+
}
|
|
51
|
+
export function addFileEdit(state, record) {
|
|
52
|
+
state.fileEdits.push(record);
|
|
53
|
+
}
|
|
54
|
+
export function addConcern(state, concern) {
|
|
55
|
+
state.concerns.push(concern);
|
|
56
|
+
}
|
|
57
|
+
export function recentPrompts(state, count = 5) {
|
|
58
|
+
return state.prompts.slice(-count);
|
|
59
|
+
}
|
|
60
|
+
export function sessionDurationMinutes(state) {
|
|
61
|
+
return (Date.now() - state.startedAt) / 60_000;
|
|
62
|
+
}
|
|
63
|
+
export function totalFilesEdited(state) {
|
|
64
|
+
const paths = new Set(state.fileEdits.map((e) => e.filePath));
|
|
65
|
+
return paths.size;
|
|
66
|
+
}
|
|
67
|
+
export function totalLinesChanged(state) {
|
|
68
|
+
return state.fileEdits.reduce((sum, e) => sum + e.totalLinesChanged, 0);
|
|
69
|
+
}
|
|
70
|
+
export function recordModel(state, model) {
|
|
71
|
+
if (!state.modelsUsed)
|
|
72
|
+
state.modelsUsed = [];
|
|
73
|
+
if (!state.modelsUsed.includes(model)) {
|
|
74
|
+
state.modelsUsed.push(model);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { TranscriptContext, TranscriptTurn } from "./types.js";
|
|
2
|
+
export declare function isSafeTranscriptPath(transcriptPath: string): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Reads and parses a Cursor transcript JSONL file into structured turns.
|
|
5
|
+
* Returns null if the file is unreadable or empty — callers should
|
|
6
|
+
* treat null as "no transcript available" and fall back to heuristics.
|
|
7
|
+
*
|
|
8
|
+
* The parser is intentionally lenient: malformed lines are skipped,
|
|
9
|
+
* and the hook should never fail because of a transcript issue.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadTranscript(transcriptPath: string | null): Promise<TranscriptContext | null>;
|
|
12
|
+
/**
|
|
13
|
+
* Returns the last N user turns from the transcript.
|
|
14
|
+
*/
|
|
15
|
+
export declare function recentUserTurns(ctx: TranscriptContext, count: number): TranscriptTurn[];
|
|
16
|
+
/**
|
|
17
|
+
* Returns the last N assistant turns from the transcript.
|
|
18
|
+
*/
|
|
19
|
+
export declare function recentAssistantTurns(ctx: TranscriptContext, count: number): TranscriptTurn[];
|
|
20
|
+
/**
|
|
21
|
+
* Checks whether the current prompt appears to be a follow-up that references
|
|
22
|
+
* content from the last assistant response (numbered items, file names, etc.).
|
|
23
|
+
* This is critical for reducing false positives on short directives like
|
|
24
|
+
* "fix #3 and #5" or "do that for utils.ts too".
|
|
25
|
+
*/
|
|
26
|
+
export declare function isContextualFollowUp(prompt: string, ctx: TranscriptContext): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Detects whether the assistant's last response contained a plan, proposal,
|
|
29
|
+
* or question that naturally invites a short directive follow-up.
|
|
30
|
+
*/
|
|
31
|
+
export declare function lastResponseInvitesFollowUp(ctx: TranscriptContext): boolean;
|
|
32
|
+
//# sourceMappingURL=transcript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA6CpE,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,cAAc,EAAE,MAAM,GAAG,IAAI,GAC5B,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CA0CnC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,MAAM,GACZ,cAAc,EAAE,CAIlB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,MAAM,GACZ,cAAc,EAAE,CAIlB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAiCT;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAc3E"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { extname, isAbsolute } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Extracts plain text from a transcript line's content blocks.
|
|
5
|
+
* Strips tool_use blocks, image blocks, and other non-text content.
|
|
6
|
+
* For user messages, strips the <user_query> wrapper tags that Cursor injects.
|
|
7
|
+
*/
|
|
8
|
+
function extractText(line) {
|
|
9
|
+
const blocks = line.message?.content ?? [];
|
|
10
|
+
const textParts = [];
|
|
11
|
+
for (const block of blocks) {
|
|
12
|
+
if (block.type === "text" && block.text) {
|
|
13
|
+
textParts.push(block.text);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
let combined = textParts.join("\n").trim();
|
|
17
|
+
// Cursor wraps user prompts in <user_query>...</user_query> tags
|
|
18
|
+
const queryMatch = combined.match(/<user_query>\s*([\s\S]*?)\s*<\/user_query>/);
|
|
19
|
+
if (queryMatch) {
|
|
20
|
+
combined = queryMatch[1].trim();
|
|
21
|
+
}
|
|
22
|
+
return combined;
|
|
23
|
+
}
|
|
24
|
+
function wordCount(text) {
|
|
25
|
+
if (!text)
|
|
26
|
+
return 0;
|
|
27
|
+
return text.split(/\s+/).filter(Boolean).length;
|
|
28
|
+
}
|
|
29
|
+
export function isSafeTranscriptPath(transcriptPath) {
|
|
30
|
+
return isAbsolute(transcriptPath) && extname(transcriptPath).toLowerCase() === ".jsonl";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Reads and parses a Cursor transcript JSONL file into structured turns.
|
|
34
|
+
* Returns null if the file is unreadable or empty — callers should
|
|
35
|
+
* treat null as "no transcript available" and fall back to heuristics.
|
|
36
|
+
*
|
|
37
|
+
* The parser is intentionally lenient: malformed lines are skipped,
|
|
38
|
+
* and the hook should never fail because of a transcript issue.
|
|
39
|
+
*/
|
|
40
|
+
export async function loadTranscript(transcriptPath) {
|
|
41
|
+
if (!transcriptPath)
|
|
42
|
+
return null;
|
|
43
|
+
if (!isSafeTranscriptPath(transcriptPath))
|
|
44
|
+
return null;
|
|
45
|
+
try {
|
|
46
|
+
const raw = await readFile(transcriptPath, "utf-8");
|
|
47
|
+
const lines = raw.split("\n").filter((l) => l.trim());
|
|
48
|
+
const turns = [];
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(line);
|
|
52
|
+
if (parsed.role !== "user" && parsed.role !== "assistant")
|
|
53
|
+
continue;
|
|
54
|
+
const text = extractText(parsed);
|
|
55
|
+
if (!text)
|
|
56
|
+
continue;
|
|
57
|
+
turns.push({
|
|
58
|
+
role: parsed.role,
|
|
59
|
+
text,
|
|
60
|
+
wordCount: wordCount(text),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Skip malformed lines — don't break the hook
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (turns.length === 0)
|
|
68
|
+
return null;
|
|
69
|
+
const userTurns = turns.filter((t) => t.role === "user");
|
|
70
|
+
const assistantTurns = turns.filter((t) => t.role === "assistant");
|
|
71
|
+
return {
|
|
72
|
+
turns,
|
|
73
|
+
userTurnCount: userTurns.length,
|
|
74
|
+
assistantTurnCount: assistantTurns.length,
|
|
75
|
+
lastAssistantText: assistantTurns.at(-1)?.text ?? "",
|
|
76
|
+
lastUserText: userTurns.at(-1)?.text ?? "",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Returns the last N user turns from the transcript.
|
|
85
|
+
*/
|
|
86
|
+
export function recentUserTurns(ctx, count) {
|
|
87
|
+
return ctx.turns
|
|
88
|
+
.filter((t) => t.role === "user")
|
|
89
|
+
.slice(-count);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Returns the last N assistant turns from the transcript.
|
|
93
|
+
*/
|
|
94
|
+
export function recentAssistantTurns(ctx, count) {
|
|
95
|
+
return ctx.turns
|
|
96
|
+
.filter((t) => t.role === "assistant")
|
|
97
|
+
.slice(-count);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Checks whether the current prompt appears to be a follow-up that references
|
|
101
|
+
* content from the last assistant response (numbered items, file names, etc.).
|
|
102
|
+
* This is critical for reducing false positives on short directives like
|
|
103
|
+
* "fix #3 and #5" or "do that for utils.ts too".
|
|
104
|
+
*/
|
|
105
|
+
export function isContextualFollowUp(prompt, ctx) {
|
|
106
|
+
const lastResponse = ctx.lastAssistantText;
|
|
107
|
+
if (!lastResponse)
|
|
108
|
+
return false;
|
|
109
|
+
const trimmed = prompt.trim().toLowerCase();
|
|
110
|
+
// References to numbered items from the assistant's response
|
|
111
|
+
const numberRefs = trimmed.match(/#(\d+)/g);
|
|
112
|
+
if (numberRefs && numberRefs.length > 0) {
|
|
113
|
+
const responseHasNumbers = /#?\d+[.):]\s/.test(lastResponse);
|
|
114
|
+
if (responseHasNumbers)
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
// References to file/function names that appear in the last response
|
|
118
|
+
const identifiers = trimmed.match(/\b[\w.-]+\.(ts|js|tsx|jsx|py|rs|go|css|html|json|md)\b/gi);
|
|
119
|
+
if (identifiers) {
|
|
120
|
+
for (const id of identifiers) {
|
|
121
|
+
if (lastResponse.includes(id))
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// "that", "those", "the same" referring to something the assistant just listed
|
|
126
|
+
const deicticPatterns = /\b(do that|do those|the same|same thing|like above|as above|mentioned above)\b/i;
|
|
127
|
+
if (deicticPatterns.test(trimmed) && lastResponse.length > 100) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
// Short affirmative after a question or proposal from the assistant
|
|
131
|
+
const assistantAskedQuestion = /\?[\s]*$/.test(lastResponse.trim());
|
|
132
|
+
const isShortAffirmative = /^(yes|yeah|yep|sure|go ahead|do it|proceed|ok|okay|correct|exactly|please|go)[\s.,!]?$/i.test(trimmed);
|
|
133
|
+
if (assistantAskedQuestion && isShortAffirmative)
|
|
134
|
+
return true;
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Detects whether the assistant's last response contained a plan, proposal,
|
|
139
|
+
* or question that naturally invites a short directive follow-up.
|
|
140
|
+
*/
|
|
141
|
+
export function lastResponseInvitesFollowUp(ctx) {
|
|
142
|
+
const text = ctx.lastAssistantText;
|
|
143
|
+
if (!text)
|
|
144
|
+
return false;
|
|
145
|
+
// Ends with a question
|
|
146
|
+
if (/\?\s*$/.test(text.trim()))
|
|
147
|
+
return true;
|
|
148
|
+
// Contains a numbered list (plan/options)
|
|
149
|
+
if (/\n\s*\d+[.)]\s/.test(text))
|
|
150
|
+
return true;
|
|
151
|
+
// Explicit invitation patterns
|
|
152
|
+
if (/\b(which (one|item|option)|ready when you are|want me to|shall I|let me know|would you like)\b/i.test(text))
|
|
153
|
+
return true;
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=transcript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
export interface HookBaseInput {
|
|
2
|
+
conversation_id: string;
|
|
3
|
+
generation_id: string;
|
|
4
|
+
model: string;
|
|
5
|
+
hook_event_name: string;
|
|
6
|
+
cursor_version: string;
|
|
7
|
+
workspace_roots: string[];
|
|
8
|
+
user_email: string | null;
|
|
9
|
+
transcript_path: string | null;
|
|
10
|
+
session_id?: string;
|
|
11
|
+
composer_mode?: "agent" | "ask" | "edit";
|
|
12
|
+
}
|
|
13
|
+
export interface BeforeSubmitPromptInput extends HookBaseInput {
|
|
14
|
+
prompt: string;
|
|
15
|
+
attachments: Array<{
|
|
16
|
+
type: "file" | "rule";
|
|
17
|
+
file_path: string;
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
20
|
+
export interface AfterAgentResponseInput extends HookBaseInput {
|
|
21
|
+
text: string;
|
|
22
|
+
}
|
|
23
|
+
export interface AfterAgentThoughtInput extends HookBaseInput {
|
|
24
|
+
text: string;
|
|
25
|
+
duration_ms?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface AfterFileEditInput extends HookBaseInput {
|
|
28
|
+
file_path: string;
|
|
29
|
+
edits: Array<{
|
|
30
|
+
old_string: string;
|
|
31
|
+
new_string: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
export interface StopInput extends HookBaseInput {
|
|
35
|
+
status: "completed" | "aborted" | "error";
|
|
36
|
+
loop_count: number;
|
|
37
|
+
}
|
|
38
|
+
export interface SessionStartInput extends HookBaseInput {
|
|
39
|
+
is_background_agent: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface SessionEndInput extends HookBaseInput {
|
|
42
|
+
reason: "completed" | "aborted" | "error" | "window_close" | "user_close";
|
|
43
|
+
duration_ms: number;
|
|
44
|
+
is_background_agent: boolean;
|
|
45
|
+
final_status: string;
|
|
46
|
+
error_message?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface PreCompactInput extends HookBaseInput {
|
|
49
|
+
trigger: "auto" | "manual";
|
|
50
|
+
context_usage_percent: number;
|
|
51
|
+
context_tokens: number;
|
|
52
|
+
context_window_size: number;
|
|
53
|
+
message_count: number;
|
|
54
|
+
messages_to_compact: number;
|
|
55
|
+
is_first_compaction: boolean;
|
|
56
|
+
}
|
|
57
|
+
export interface BeforeSubmitPromptOutput {
|
|
58
|
+
continue: boolean;
|
|
59
|
+
user_message?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface AfterAgentResponseOutput {
|
|
62
|
+
}
|
|
63
|
+
export interface StopOutput {
|
|
64
|
+
followup_message?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface SessionStartOutput {
|
|
67
|
+
env?: Record<string, string>;
|
|
68
|
+
additional_context?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface TranscriptTurn {
|
|
71
|
+
role: "user" | "assistant";
|
|
72
|
+
/** Plain text content (tool calls and non-text blocks stripped). */
|
|
73
|
+
text: string;
|
|
74
|
+
wordCount: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Parsed conversation context from the Cursor transcript file.
|
|
78
|
+
* Provides the full dialogue history so analyzers can make
|
|
79
|
+
* context-aware decisions instead of relying on heuristics alone.
|
|
80
|
+
*/
|
|
81
|
+
export interface TranscriptContext {
|
|
82
|
+
turns: TranscriptTurn[];
|
|
83
|
+
/** Number of user messages in the transcript. */
|
|
84
|
+
userTurnCount: number;
|
|
85
|
+
/** Number of assistant messages in the transcript. */
|
|
86
|
+
assistantTurnCount: number;
|
|
87
|
+
/** The last assistant response text (empty string if none). */
|
|
88
|
+
lastAssistantText: string;
|
|
89
|
+
/** The last user message text (empty string if none). */
|
|
90
|
+
lastUserText: string;
|
|
91
|
+
}
|
|
92
|
+
export type Severity = "info" | "warning" | "critical";
|
|
93
|
+
export interface Concern {
|
|
94
|
+
severity: Severity;
|
|
95
|
+
category: string;
|
|
96
|
+
message: string;
|
|
97
|
+
suggestion?: string;
|
|
98
|
+
sourceText?: string;
|
|
99
|
+
sourceType?: "prompt" | "response" | "session";
|
|
100
|
+
}
|
|
101
|
+
export interface PromptRecord {
|
|
102
|
+
timestamp: number;
|
|
103
|
+
prompt: string;
|
|
104
|
+
wordCount: number;
|
|
105
|
+
concerns: Concern[];
|
|
106
|
+
}
|
|
107
|
+
export interface ResponseRecord {
|
|
108
|
+
timestamp: number;
|
|
109
|
+
textLength: number;
|
|
110
|
+
concerns: Concern[];
|
|
111
|
+
/** True when the response had no preceding beforeSubmitPrompt event. */
|
|
112
|
+
unprompted?: boolean;
|
|
113
|
+
}
|
|
114
|
+
export interface FileEditRecord {
|
|
115
|
+
timestamp: number;
|
|
116
|
+
filePath: string;
|
|
117
|
+
editCount: number;
|
|
118
|
+
totalLinesChanged: number;
|
|
119
|
+
}
|
|
120
|
+
export interface SessionState {
|
|
121
|
+
conversationId: string;
|
|
122
|
+
sessionId?: string;
|
|
123
|
+
composerMode?: "agent" | "ask" | "edit";
|
|
124
|
+
startedAt: number;
|
|
125
|
+
prompts: PromptRecord[];
|
|
126
|
+
responses: ResponseRecord[];
|
|
127
|
+
fileEdits: FileEditRecord[];
|
|
128
|
+
turnCount: number;
|
|
129
|
+
compactionCount: number;
|
|
130
|
+
concerns: Concern[];
|
|
131
|
+
lastBlockedPrompt?: string;
|
|
132
|
+
/** turnCount at last session review, used to suppress redundant stop reviews. */
|
|
133
|
+
lastReviewedAtTurn?: number;
|
|
134
|
+
/** Actual model(s) observed on prompt/response events (not sessionStart). */
|
|
135
|
+
modelsUsed?: string[];
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,6BAA6B"}
|
|
Binary file
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Hegel Configuration",
|
|
4
|
+
"description": "Configuration for Hegel dialectical companion",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Path to the JSON schema for this config file."
|
|
10
|
+
},
|
|
11
|
+
"model": {
|
|
12
|
+
"anyOf": [
|
|
13
|
+
{
|
|
14
|
+
"enum": [
|
|
15
|
+
"auto",
|
|
16
|
+
"gpt-5.4",
|
|
17
|
+
"claude-4.6-opus",
|
|
18
|
+
"gemini-3.1-pro",
|
|
19
|
+
"grok-4.20",
|
|
20
|
+
"gemini-3-flash",
|
|
21
|
+
"composer-2",
|
|
22
|
+
"composer-1.5",
|
|
23
|
+
"claude-4.6-sonnet",
|
|
24
|
+
"gpt-5.2",
|
|
25
|
+
"claude-4.5-haiku",
|
|
26
|
+
"gpt-5.1",
|
|
27
|
+
"gemini-2.5-flash"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "Or type any other valid Cursor model name available in your subscription."
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"description": "Model to use for LLM-powered analysis. Use 'auto' for Cursor's default fast model, or specify a model name from your subscription.",
|
|
36
|
+
"default": "auto"
|
|
37
|
+
},
|
|
38
|
+
"enableLlmAnalysis": {
|
|
39
|
+
"type": "boolean",
|
|
40
|
+
"description": "Enable the LLM-powered deep analysis layer (Layer 2). When false, only fast rule-based checks (Layer 1) run. Uses tokens from your Cursor subscription.",
|
|
41
|
+
"default": true
|
|
42
|
+
},
|
|
43
|
+
"timeoutSeconds": {
|
|
44
|
+
"type": "number",
|
|
45
|
+
"description": "Timeout in seconds for LLM-powered hooks.",
|
|
46
|
+
"default": 15,
|
|
47
|
+
"minimum": 5,
|
|
48
|
+
"maximum": 60
|
|
49
|
+
},
|
|
50
|
+
"strictness": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"enum": ["relaxed", "balanced", "strict"],
|
|
53
|
+
"description": "How aggressively Hegel intervenes. 'relaxed' = only obvious issues, 'balanced' = default, 'strict' = questions most prompts.",
|
|
54
|
+
"default": "balanced"
|
|
55
|
+
},
|
|
56
|
+
"observeOnly": {
|
|
57
|
+
"type": "boolean",
|
|
58
|
+
"description": "Observe-Only Mode: When true, both layers still run full analysis and collect stats, but the user never sees any intervention in the chat (no blocking, no messages).",
|
|
59
|
+
"default": false
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"additionalProperties": false
|
|
63
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hegel-dev/companion",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Dialectical companion for AI-assisted development — real-time critical thinking oversight for Cursor IDE sessions",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc -p tsconfig.build.json",
|
|
11
|
+
"dev": "tsc --watch",
|
|
12
|
+
"dev:watch": "node dist/dev-watch.js",
|
|
13
|
+
"hook": "node dist/hook.js",
|
|
14
|
+
"setup": "node dist/setup.js",
|
|
15
|
+
"mcp": "node dist/mcp.js",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:coverage": "vitest run --coverage"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"hegel-companion": "./dist/setup.js",
|
|
21
|
+
"hegel-mcp": "./dist/mcp.js"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"cursor",
|
|
25
|
+
"cursor-plugin",
|
|
26
|
+
"ai-assistant",
|
|
27
|
+
"critical-thinking",
|
|
28
|
+
"code-review",
|
|
29
|
+
"dialectical"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/CreatoR682/hegel.git"
|
|
35
|
+
},
|
|
36
|
+
"author": "Hegel Contributors",
|
|
37
|
+
"files": [
|
|
38
|
+
"dist/**/*.js",
|
|
39
|
+
"dist/**/*.js.map",
|
|
40
|
+
"dist/**/*.d.ts",
|
|
41
|
+
"dist/**/*.d.ts.map",
|
|
42
|
+
"hegel.config.schema.json",
|
|
43
|
+
"hegel-vscode/*.vsix"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@emnapi/core": "^1.9.2",
|
|
50
|
+
"@emnapi/runtime": "^1.9.2",
|
|
51
|
+
"@types/node": "^20.19.39",
|
|
52
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
53
|
+
"typescript": "^5.7",
|
|
54
|
+
"vitest": "^4.1.4"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
58
|
+
}
|
|
59
|
+
}
|