@kintsugi-ai/hook 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/.kintsugi/logs/hook.log +11 -0
- package/dist/agent-detect.d.ts +59 -0
- package/dist/agent-detect.d.ts.map +1 -0
- package/dist/agent-detect.js +123 -0
- package/dist/agent-detect.js.map +1 -0
- package/dist/agent-detect.test.d.ts +2 -0
- package/dist/agent-detect.test.d.ts.map +1 -0
- package/dist/agent-detect.test.js +42 -0
- package/dist/agent-detect.test.js.map +1 -0
- package/dist/context.d.ts +10 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +81 -0
- package/dist/context.js.map +1 -0
- package/dist/escalation.d.ts +28 -0
- package/dist/escalation.d.ts.map +1 -0
- package/dist/escalation.js +48 -0
- package/dist/escalation.js.map +1 -0
- package/dist/flow-matcher.d.ts +9 -0
- package/dist/flow-matcher.d.ts.map +1 -0
- package/dist/flow-matcher.js +12 -0
- package/dist/flow-matcher.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +209 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +58 -0
- package/dist/logger.js.map +1 -0
- package/dist/ui-file-detector.d.ts +9 -0
- package/dist/ui-file-detector.d.ts.map +1 -0
- package/dist/ui-file-detector.js +34 -0
- package/dist/ui-file-detector.js.map +1 -0
- package/package.json +29 -0
- package/src/agent-detect.test.ts +53 -0
- package/src/agent-detect.ts +167 -0
- package/src/context.ts +80 -0
- package/src/escalation.ts +60 -0
- package/src/flow-matcher.ts +13 -0
- package/src/index.ts +269 -0
- package/src/logger.ts +62 -0
- package/src/ui-file-detector.ts +40 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
[2026-09-23T12:36:50.957Z] hook invoked {"argv":["--help"],"cwd":"/Users/munch/Documents/coding/kintsugi/packages/hook","projectDir":"/Users/munch/Documents/coding/kintsugi/packages/hook","stdinBytes":0}
|
|
2
|
+
[2026-09-23T12:36:50.957Z] WARN: stdin was empty — agent sent no hook payload
|
|
3
|
+
[2026-09-23T12:36:50.957Z] agent detected {"agent":"codex","isStopEvent":false,"isExplicitStopEvent":false,"inputKeys":[]}
|
|
4
|
+
[2026-09-23T12:36:50.957Z] non-stop event — deferring visual check to turn end
|
|
5
|
+
[2026-09-23T12:36:53.296Z] hook invoked {"argv":["--event","stop"],"cwd":"/Users/munch/Documents/coding/kintsugi/packages/hook","projectDir":"/Users/munch/Documents/coding/kintsugi/packages/hook","stdinBytes":0}
|
|
6
|
+
[2026-09-23T12:36:53.296Z] agent detected {"agent":"codex","isStopEvent":true,"isExplicitStopEvent":true,"inputKeys":[]}
|
|
7
|
+
[2026-09-23T12:36:53.296Z] config loaded {"devServerUrl":"http://localhost:3000","classifierModel":"kintsugi-hosted"}
|
|
8
|
+
[2026-09-23T12:36:54.063Z] WARN: could not obtain a kintsugi api key: fetch failed
|
|
9
|
+
[2026-09-23T12:36:54.064Z] WARN: no API token found (env KINTSUGI_API_KEY, <project>/.kintsugi/.env, or ~/.kintsugi/.env) — classifier disabled, large diffs will escalate without classification
|
|
10
|
+
[2026-09-23T12:36:54.065Z] flows discovered {"flowsDir":"/Users/munch/Documents/coding/kintsugi/packages/hook/.kintsugi/flows","count":0,"names":[]}
|
|
11
|
+
[2026-09-23T12:36:54.065Z] no recorded flows — nothing to check
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent type detection and protocol helpers for Claude Code, Codex CLI, and Antigravity (agy).
|
|
3
|
+
*/
|
|
4
|
+
export type AgentType = 'claude-code' | 'codex' | 'agy' | 'unknown';
|
|
5
|
+
export interface HookInput {
|
|
6
|
+
conversationId?: string;
|
|
7
|
+
workspacePaths?: string[];
|
|
8
|
+
transcriptPath?: string;
|
|
9
|
+
artifactDirectoryPath?: string;
|
|
10
|
+
terminationReason?: string;
|
|
11
|
+
toolCall?: {
|
|
12
|
+
name: string;
|
|
13
|
+
args?: {
|
|
14
|
+
TargetFile?: string;
|
|
15
|
+
CommandLine?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
hook_event_name?: string;
|
|
20
|
+
tool_input?: {
|
|
21
|
+
file_path?: string;
|
|
22
|
+
path?: string;
|
|
23
|
+
TargetFile?: string;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
};
|
|
26
|
+
tool_name?: string;
|
|
27
|
+
session_id?: string;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Detects the type of agent invoking the hook.
|
|
32
|
+
* @param stdin Optional parsed stdin payload to inspect markers.
|
|
33
|
+
* @returns The detected agent type.
|
|
34
|
+
*/
|
|
35
|
+
export declare function detectAgent(stdin?: HookInput): AgentType;
|
|
36
|
+
/**
|
|
37
|
+
* Extracts the modified file path from the agent context.
|
|
38
|
+
* @param agent The type of agent.
|
|
39
|
+
* @param stdin The input from standard input.
|
|
40
|
+
* @returns The modified file path, if found.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getModifiedFilePath(agent: AgentType, stdin: HookInput): string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Outputs feedback based on the agent type protocols.
|
|
45
|
+
* @param agent The type of agent.
|
|
46
|
+
* @param feedback The formatted feedback string.
|
|
47
|
+
* @param options Additional metadata such as whether this is a Stop event.
|
|
48
|
+
*/
|
|
49
|
+
export declare function outputFeedback(agent: AgentType, feedback: string, options?: {
|
|
50
|
+
isStopEvent?: boolean;
|
|
51
|
+
hasRegression?: boolean;
|
|
52
|
+
}): void;
|
|
53
|
+
/**
|
|
54
|
+
* Exits the process with the appropriate code for the agent.
|
|
55
|
+
* @param agent The type of agent.
|
|
56
|
+
* @param hasRegression Whether a regression was detected.
|
|
57
|
+
*/
|
|
58
|
+
export declare function exitWithResult(agent: AgentType, hasRegression: boolean): never;
|
|
59
|
+
//# sourceMappingURL=agent-detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-detect.d.ts","sourceRoot":"","sources":["../src/agent-detect.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;AAEpE,MAAM,WAAW,SAAS;IAEtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE;YACH,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;SAC1B,CAAC;KACL,CAAC;IAGF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KAC1B,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,CA2BxD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAuB1F;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC1B,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7D,IAAI,CAqCN;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,GAAG,KAAK,CAY9E"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent type detection and protocol helpers for Claude Code, Codex CLI, and Antigravity (agy).
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Detects the type of agent invoking the hook.
|
|
6
|
+
* @param stdin Optional parsed stdin payload to inspect markers.
|
|
7
|
+
* @returns The detected agent type.
|
|
8
|
+
*/
|
|
9
|
+
export function detectAgent(stdin) {
|
|
10
|
+
// 1. Explicit Antigravity (agy) payload markers in stdin
|
|
11
|
+
if (stdin?.conversationId ||
|
|
12
|
+
stdin?.transcriptPath ||
|
|
13
|
+
stdin?.toolCall) {
|
|
14
|
+
return 'agy';
|
|
15
|
+
}
|
|
16
|
+
// 2. Explicit Claude Code markers
|
|
17
|
+
if (process.env.CLAUDE_SESSION_ID || process.env.CLAUDE_FILE_PATH) {
|
|
18
|
+
return 'claude-code';
|
|
19
|
+
}
|
|
20
|
+
// 3. Explicit Codex payload marker (tool_input without agy headers)
|
|
21
|
+
if (stdin?.tool_input && !stdin?.conversationId) {
|
|
22
|
+
return 'codex';
|
|
23
|
+
}
|
|
24
|
+
// 4. Ambient environment markers
|
|
25
|
+
if (process.env.ANTIGRAVITY_AGENT || process.env.GEMINI_CLI) {
|
|
26
|
+
return 'agy';
|
|
27
|
+
}
|
|
28
|
+
// 5. Default fallback
|
|
29
|
+
return 'codex';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Extracts the modified file path from the agent context.
|
|
33
|
+
* @param agent The type of agent.
|
|
34
|
+
* @param stdin The input from standard input.
|
|
35
|
+
* @returns The modified file path, if found.
|
|
36
|
+
*/
|
|
37
|
+
export function getModifiedFilePath(agent, stdin) {
|
|
38
|
+
if (agent === 'agy') {
|
|
39
|
+
return (stdin?.toolCall?.args?.TargetFile ||
|
|
40
|
+
stdin?.toolCall?.args?.['target_file'] ||
|
|
41
|
+
stdin?.tool_input?.TargetFile ||
|
|
42
|
+
stdin?.tool_input?.file_path);
|
|
43
|
+
}
|
|
44
|
+
if (agent === 'claude-code') {
|
|
45
|
+
return (process.env.CLAUDE_FILE_PATH ||
|
|
46
|
+
stdin?.tool_input?.file_path ||
|
|
47
|
+
stdin?.tool_input?.['filePath']);
|
|
48
|
+
}
|
|
49
|
+
return (stdin?.tool_input?.file_path ||
|
|
50
|
+
stdin?.tool_input?.path ||
|
|
51
|
+
stdin?.tool_input?.TargetFile);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Outputs feedback based on the agent type protocols.
|
|
55
|
+
* @param agent The type of agent.
|
|
56
|
+
* @param feedback The formatted feedback string.
|
|
57
|
+
* @param options Additional metadata such as whether this is a Stop event.
|
|
58
|
+
*/
|
|
59
|
+
export function outputFeedback(agent, feedback, options) {
|
|
60
|
+
if (agent === 'agy') {
|
|
61
|
+
if (options?.isStopEvent) {
|
|
62
|
+
if (options.hasRegression) {
|
|
63
|
+
// Antigravity Stop Hook protocol: continue execution loop with reason
|
|
64
|
+
const response = {
|
|
65
|
+
decision: 'continue',
|
|
66
|
+
reason: feedback
|
|
67
|
+
};
|
|
68
|
+
process.stdout.write(JSON.stringify(response, null, 2) + '\n');
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
process.stdout.write('{}\n');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Antigravity PostToolUse contract expects empty JSON {}
|
|
76
|
+
process.stdout.write('{}\n');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (agent === 'claude-code') {
|
|
80
|
+
if (options?.isStopEvent) {
|
|
81
|
+
// Claude Code Stop-hook contract: {"decision":"block"} keeps the
|
|
82
|
+
// agent working with `reason` as the feedback. Plain stdout text
|
|
83
|
+
// would not reach the model on a Stop event.
|
|
84
|
+
if (options.hasRegression) {
|
|
85
|
+
const response = {
|
|
86
|
+
decision: 'block',
|
|
87
|
+
reason: feedback
|
|
88
|
+
};
|
|
89
|
+
process.stdout.write(JSON.stringify(response, null, 2) + '\n');
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
process.stdout.write('{}\n');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
process.stdout.write(feedback + '\n');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
process.stderr.write(feedback + '\n');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Exits the process with the appropriate code for the agent.
|
|
105
|
+
* @param agent The type of agent.
|
|
106
|
+
* @param hasRegression Whether a regression was detected.
|
|
107
|
+
*/
|
|
108
|
+
export function exitWithResult(agent, hasRegression) {
|
|
109
|
+
if (agent === 'agy') {
|
|
110
|
+
// Antigravity communicates decisions via JSON on stdout, with exit code 0
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
113
|
+
else if (agent === 'claude-code') {
|
|
114
|
+
// Claude always expects exit 0; feedback is passed via stdout
|
|
115
|
+
process.exit(0);
|
|
116
|
+
}
|
|
117
|
+
else if (agent === 'codex') {
|
|
118
|
+
// Codex expects exit 2 for failure (reject action)
|
|
119
|
+
process.exit(hasRegression ? 2 : 0);
|
|
120
|
+
}
|
|
121
|
+
process.exit(0);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=agent-detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-detect.js","sourceRoot":"","sources":["../src/agent-detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-detect.test.d.ts","sourceRoot":"","sources":["../src/agent-detect.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { test, describe } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { detectAgent, getModifiedFilePath } from './agent-detect.js';
|
|
4
|
+
describe('Agent Detection & Protocol Adaptation', () => {
|
|
5
|
+
test('detects Antigravity (agy) from stdin payload markers', () => {
|
|
6
|
+
const agyPayload = {
|
|
7
|
+
conversationId: '550e8400-e29b-41d4-a716-446655440000',
|
|
8
|
+
workspacePaths: ['/workspace/kintsugi'],
|
|
9
|
+
toolCall: {
|
|
10
|
+
name: 'write_to_file',
|
|
11
|
+
args: {
|
|
12
|
+
TargetFile: 'src/components/Checkout.tsx',
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const detected = detectAgent(agyPayload);
|
|
17
|
+
assert.equal(detected, 'agy');
|
|
18
|
+
const filePath = getModifiedFilePath(detected, agyPayload);
|
|
19
|
+
assert.equal(filePath, 'src/components/Checkout.tsx');
|
|
20
|
+
});
|
|
21
|
+
test('detects Antigravity from Stop event payload', () => {
|
|
22
|
+
const stopPayload = {
|
|
23
|
+
conversationId: '550e8400-e29b-41d4-a716-446655440000',
|
|
24
|
+
terminationReason: 'model_stop',
|
|
25
|
+
fullyIdle: true
|
|
26
|
+
};
|
|
27
|
+
const detected = detectAgent(stopPayload);
|
|
28
|
+
assert.equal(detected, 'agy');
|
|
29
|
+
});
|
|
30
|
+
test('extracts modified file path from Codex tool input', () => {
|
|
31
|
+
const codexPayload = {
|
|
32
|
+
tool_input: {
|
|
33
|
+
file_path: 'src/Navbar.tsx'
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const detected = detectAgent(codexPayload);
|
|
37
|
+
assert.equal(detected, 'codex');
|
|
38
|
+
const filePath = getModifiedFilePath(detected, codexPayload);
|
|
39
|
+
assert.equal(filePath, 'src/Navbar.tsx');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=agent-detect.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-detect.test.js","sourceRoot":"","sources":["../src/agent-detect.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EACH,WAAW,EACX,mBAAmB,EAEtB,MAAM,mBAAmB,CAAC;AAE3B,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACnD,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,UAAU,GAAc;YAC1B,cAAc,EAAE,sCAAsC;YACtD,cAAc,EAAE,CAAC,qBAAqB,CAAC;YACvC,QAAQ,EAAE;gBACN,IAAI,EAAE,eAAe;gBACrB,IAAI,EAAE;oBACF,UAAU,EAAE,6BAA6B;iBAC5C;aACJ;SACJ,CAAC;QAEF,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAE9B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,WAAW,GAAc;YAC3B,cAAc,EAAE,sCAAsC;YACtD,iBAAiB,EAAE,YAAY;YAC/B,SAAS,EAAE,IAAI;SAClB,CAAC;QAEF,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,YAAY,GAAc;YAC5B,UAAU,EAAE;gBACR,SAAS,EAAE,gBAAgB;aAC9B;SACJ,CAAC;QAEF,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAEhC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HookInput } from './agent-detect.js';
|
|
2
|
+
/**
|
|
3
|
+
* Best-effort extraction of "what was the agent asked to do" from the latest
|
|
4
|
+
* turn, to give the vision classifier intent context. Claude Code Stop
|
|
5
|
+
* payloads carry `transcript_path` (JSONL); Antigravity carries
|
|
6
|
+
* `transcriptPath`. Codex has none — return empty and let the classifier
|
|
7
|
+
* decide without context.
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractTurnContext(input: HookInput): string;
|
|
10
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAInD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAmC3D"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
const MAX_CONTEXT_CHARS = 600;
|
|
3
|
+
/**
|
|
4
|
+
* Best-effort extraction of "what was the agent asked to do" from the latest
|
|
5
|
+
* turn, to give the vision classifier intent context. Claude Code Stop
|
|
6
|
+
* payloads carry `transcript_path` (JSONL); Antigravity carries
|
|
7
|
+
* `transcriptPath`. Codex has none — return empty and let the classifier
|
|
8
|
+
* decide without context.
|
|
9
|
+
*/
|
|
10
|
+
export function extractTurnContext(input) {
|
|
11
|
+
const transcriptPath = (typeof input.transcript_path === 'string' && input.transcript_path) ||
|
|
12
|
+
input.transcriptPath;
|
|
13
|
+
if (!transcriptPath)
|
|
14
|
+
return '';
|
|
15
|
+
try {
|
|
16
|
+
const content = fs.readFileSync(transcriptPath, 'utf-8');
|
|
17
|
+
const userTexts = [];
|
|
18
|
+
for (const line of content.split('\n')) {
|
|
19
|
+
const trimmed = line.trim();
|
|
20
|
+
if (!trimmed)
|
|
21
|
+
continue;
|
|
22
|
+
let entry;
|
|
23
|
+
try {
|
|
24
|
+
entry = JSON.parse(trimmed);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const text = extractUserText(entry);
|
|
30
|
+
if (text)
|
|
31
|
+
userTexts.push(text);
|
|
32
|
+
}
|
|
33
|
+
const context = userTexts.slice(-2).join(' | ');
|
|
34
|
+
return context.length > MAX_CONTEXT_CHARS
|
|
35
|
+
? context.slice(0, MAX_CONTEXT_CHARS) + '…'
|
|
36
|
+
: context;
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
// ENOENT is expected when the agent has no transcript — everything else is unusual
|
|
40
|
+
const isNotFound = typeof err === 'object' && err !== null && 'code' in err && err.code === 'ENOENT';
|
|
41
|
+
if (!isNotFound) {
|
|
42
|
+
console.warn(`kintsugi: failed to read transcript at ${transcriptPath}:`, err);
|
|
43
|
+
}
|
|
44
|
+
return '';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function extractUserText(entry) {
|
|
48
|
+
// Claude Code transcript entries: { type: "user", message: { role: "user", content: string | [{type:"text",text}] } }
|
|
49
|
+
const message = entry?.message ?? entry;
|
|
50
|
+
const role = message?.role ?? entry?.type;
|
|
51
|
+
if (role !== 'user' && role !== 'human')
|
|
52
|
+
return undefined;
|
|
53
|
+
// Skip tool results / interrupt notices — only real instructions help
|
|
54
|
+
if (entry?.type === 'tool_result')
|
|
55
|
+
return undefined;
|
|
56
|
+
const content = message?.content;
|
|
57
|
+
if (typeof content === 'string' && content.trim()) {
|
|
58
|
+
return isNoise(content) ? undefined : content.trim();
|
|
59
|
+
}
|
|
60
|
+
if (Array.isArray(content)) {
|
|
61
|
+
const text = content
|
|
62
|
+
.filter((c) => c?.type === 'text' && typeof c.text === 'string')
|
|
63
|
+
.map((c) => c.text)
|
|
64
|
+
.join(' ')
|
|
65
|
+
.trim();
|
|
66
|
+
return text && !isNoise(text) ? text : undefined;
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
/** Filters transcript noise like system-injected reminders and empty interrupts. */
|
|
71
|
+
function isNoise(text) {
|
|
72
|
+
const t = text.trim();
|
|
73
|
+
if (!t)
|
|
74
|
+
return true;
|
|
75
|
+
if (t.startsWith('<'))
|
|
76
|
+
return true;
|
|
77
|
+
if (t === '[Request interrupted by user]')
|
|
78
|
+
return true;
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ComparisonResult } from '@kintsugi-ai/core';
|
|
2
|
+
export interface EscalationSignal {
|
|
3
|
+
flowName: string;
|
|
4
|
+
result: ComparisonResult;
|
|
5
|
+
oldVideoPath?: string;
|
|
6
|
+
newVideoPath?: string;
|
|
7
|
+
timestamp: string;
|
|
8
|
+
attempt: number;
|
|
9
|
+
maxAttempts: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Writes an escalation signal for the VS Code extension.
|
|
13
|
+
* @param projectDir The project directory.
|
|
14
|
+
* @param signal The escalation signal data.
|
|
15
|
+
*/
|
|
16
|
+
export declare function writeEscalation(projectDir: string, signal: EscalationSignal): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Reads the current escalation signal.
|
|
19
|
+
* @param projectDir The project directory.
|
|
20
|
+
* @returns The current escalation signal or null if not found.
|
|
21
|
+
*/
|
|
22
|
+
export declare function readEscalation(projectDir: string): Promise<EscalationSignal | null>;
|
|
23
|
+
/**
|
|
24
|
+
* Clears the escalation signal.
|
|
25
|
+
* @param projectDir The project directory.
|
|
26
|
+
*/
|
|
27
|
+
export declare function clearEscalation(projectDir: string): Promise<void>;
|
|
28
|
+
//# sourceMappingURL=escalation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escalation.d.ts","sourceRoot":"","sources":["../src/escalation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACvB;AAMD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKjG;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAQzF;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUvE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
function getEscalationFilePath(projectDir) {
|
|
4
|
+
return path.join(projectDir, '.kintsugi', '.escalation.json');
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Writes an escalation signal for the VS Code extension.
|
|
8
|
+
* @param projectDir The project directory.
|
|
9
|
+
* @param signal The escalation signal data.
|
|
10
|
+
*/
|
|
11
|
+
export async function writeEscalation(projectDir, signal) {
|
|
12
|
+
const filePath = getEscalationFilePath(projectDir);
|
|
13
|
+
const dir = path.dirname(filePath);
|
|
14
|
+
await fs.mkdir(dir, { recursive: true });
|
|
15
|
+
await fs.writeFile(filePath, JSON.stringify(signal, null, 2), 'utf-8');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Reads the current escalation signal.
|
|
19
|
+
* @param projectDir The project directory.
|
|
20
|
+
* @returns The current escalation signal or null if not found.
|
|
21
|
+
*/
|
|
22
|
+
export async function readEscalation(projectDir) {
|
|
23
|
+
const filePath = getEscalationFilePath(projectDir);
|
|
24
|
+
try {
|
|
25
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
26
|
+
return JSON.parse(content);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Clears the escalation signal.
|
|
34
|
+
* @param projectDir The project directory.
|
|
35
|
+
*/
|
|
36
|
+
export async function clearEscalation(projectDir) {
|
|
37
|
+
const filePath = getEscalationFilePath(projectDir);
|
|
38
|
+
try {
|
|
39
|
+
await fs.unlink(filePath);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const isNotFound = typeof err === 'object' && err !== null && 'code' in err && err.code === 'ENOENT';
|
|
43
|
+
if (!isNotFound) {
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=escalation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escalation.js","sourceRoot":"","sources":["../src/escalation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAa7B,SAAS,qBAAqB,CAAC,UAAkB;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB,EAAE,MAAwB;IAC9E,MAAM,QAAQ,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAAkB;IACnD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAqB,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB;IACpD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,IAAK,GAAwB,CAAC,IAAI,KAAK,QAAQ,CAAC;QAC3H,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,MAAM,GAAG,CAAC;QACd,CAAC;IACL,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FlowMetadata } from '@kintsugi-ai/core';
|
|
2
|
+
/**
|
|
3
|
+
* Determines which flows are affected by a file change.
|
|
4
|
+
* @param filePath The modified file path.
|
|
5
|
+
* @param flows The list of available flows.
|
|
6
|
+
* @returns Array of affected flow names.
|
|
7
|
+
*/
|
|
8
|
+
export declare function findAffectedFlows(filePath: string, flows: FlowMetadata[]): string[];
|
|
9
|
+
//# sourceMappingURL=flow-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-matcher.d.ts","sourceRoot":"","sources":["../src/flow-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE,CAInF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines which flows are affected by a file change.
|
|
3
|
+
* @param filePath The modified file path.
|
|
4
|
+
* @param flows The list of available flows.
|
|
5
|
+
* @returns Array of affected flow names.
|
|
6
|
+
*/
|
|
7
|
+
export function findAffectedFlows(filePath, flows) {
|
|
8
|
+
// A conservative approach: for now, assume all flows might be affected by the UI change.
|
|
9
|
+
// Future enhancements can check if the file path matches explicit mappings.
|
|
10
|
+
return flows.map(f => f.name);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=flow-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-matcher.js","sourceRoot":"","sources":["../src/flow-matcher.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,KAAqB;IACrE,yFAAyF;IACzF,4EAA4E;IAC5E,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|