promptkaizen-agent 0.2.0 → 0.3.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 +5 -1
- package/dist/backfill/run.d.ts +15 -0
- package/dist/backfill/run.d.ts.map +1 -0
- package/dist/backfill/run.js +33 -0
- package/dist/backfill/run.js.map +1 -0
- package/dist/backfill/scanner.d.ts +82 -0
- package/dist/backfill/scanner.d.ts.map +1 -0
- package/dist/backfill/scanner.js +271 -0
- package/dist/backfill/scanner.js.map +1 -0
- package/dist/cli/detect.d.ts +2 -0
- package/dist/cli/detect.d.ts.map +1 -0
- package/dist/cli/detect.js +40 -0
- package/dist/cli/detect.js.map +1 -0
- package/dist/cli/disable.d.ts +2 -0
- package/dist/cli/disable.d.ts.map +1 -0
- package/dist/cli/disable.js +44 -0
- package/dist/cli/disable.js.map +1 -0
- package/dist/cli/enable.d.ts +2 -0
- package/dist/cli/enable.d.ts.map +1 -0
- package/dist/cli/enable.js +105 -0
- package/dist/cli/enable.js.map +1 -0
- package/dist/cli/hook.d.ts +2 -0
- package/dist/cli/hook.d.ts.map +1 -0
- package/dist/cli/hook.js +406 -0
- package/dist/cli/hook.js.map +1 -0
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +70 -8
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/install-hooks.d.ts +5 -0
- package/dist/cli/install-hooks.d.ts.map +1 -0
- package/dist/cli/install-hooks.js +132 -0
- package/dist/cli/install-hooks.js.map +1 -0
- package/dist/cli/install-task.d.ts +28 -0
- package/dist/cli/install-task.d.ts.map +1 -0
- package/dist/cli/install-task.js +119 -0
- package/dist/cli/install-task.js.map +1 -0
- package/dist/cli/mcp.d.ts +2 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +148 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/metrics.d.ts +2 -0
- package/dist/cli/metrics.d.ts.map +1 -0
- package/dist/cli/metrics.js +103 -0
- package/dist/cli/metrics.js.map +1 -0
- package/dist/cli/report.d.ts +2 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/report.js +211 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/scan.d.ts +2 -0
- package/dist/cli/scan.d.ts.map +1 -0
- package/dist/cli/scan.js +171 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/start.d.ts.map +1 -1
- package/dist/cli/start.js +70 -17
- package/dist/cli/start.js.map +1 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +82 -18
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/uninstall-task.d.ts +8 -0
- package/dist/cli/uninstall-task.d.ts.map +1 -0
- package/dist/cli/uninstall-task.js +44 -0
- package/dist/cli/uninstall-task.js.map +1 -0
- package/dist/config.d.ts +172 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +114 -2
- package/dist/config.js.map +1 -1
- package/dist/console-safe.d.ts +21 -0
- package/dist/console-safe.d.ts.map +1 -0
- package/dist/console-safe.js +71 -0
- package/dist/console-safe.js.map +1 -0
- package/dist/detection-secret.d.ts.map +1 -1
- package/dist/detection-secret.js +12 -0
- package/dist/detection-secret.js.map +1 -1
- package/dist/env-detect.d.ts +44 -0
- package/dist/env-detect.d.ts.map +1 -0
- package/dist/env-detect.js +151 -0
- package/dist/env-detect.js.map +1 -0
- package/dist/exec/executor.d.ts +42 -0
- package/dist/exec/executor.d.ts.map +1 -0
- package/dist/exec/executor.js +135 -0
- package/dist/exec/executor.js.map +1 -0
- package/dist/exec/pk-execute.d.ts +30 -0
- package/dist/exec/pk-execute.d.ts.map +1 -0
- package/dist/exec/pk-execute.js +174 -0
- package/dist/exec/pk-execute.js.map +1 -0
- package/dist/exec/policy-fetcher.d.ts +9 -0
- package/dist/exec/policy-fetcher.d.ts.map +1 -0
- package/dist/exec/policy-fetcher.js +46 -0
- package/dist/exec/policy-fetcher.js.map +1 -0
- package/dist/exec/policy.d.ts +32 -0
- package/dist/exec/policy.d.ts.map +1 -0
- package/dist/exec/policy.js +88 -0
- package/dist/exec/policy.js.map +1 -0
- package/dist/hooks/block-store.d.ts +14 -0
- package/dist/hooks/block-store.d.ts.map +1 -0
- package/dist/hooks/block-store.js +26 -0
- package/dist/hooks/block-store.js.map +1 -0
- package/dist/hooks/claude-hook.d.ts +55 -0
- package/dist/hooks/claude-hook.d.ts.map +1 -0
- package/dist/hooks/claude-hook.js +122 -0
- package/dist/hooks/claude-hook.js.map +1 -0
- package/dist/hooks/continuity.d.ts +48 -0
- package/dist/hooks/continuity.d.ts.map +1 -0
- package/dist/hooks/continuity.js +92 -0
- package/dist/hooks/continuity.js.map +1 -0
- package/dist/hooks/observation.d.ts +27 -0
- package/dist/hooks/observation.d.ts.map +1 -0
- package/dist/hooks/observation.js +0 -0
- package/dist/hooks/observation.js.map +1 -0
- package/dist/hooks/platforms.d.ts +24 -0
- package/dist/hooks/platforms.d.ts.map +1 -0
- package/dist/hooks/platforms.js +57 -0
- package/dist/hooks/platforms.js.map +1 -0
- package/dist/hooks/read-cache.d.ts +71 -0
- package/dist/hooks/read-cache.d.ts.map +1 -0
- package/dist/hooks/read-cache.js +166 -0
- package/dist/hooks/read-cache.js.map +1 -0
- package/dist/hooks/reduction.d.ts +78 -0
- package/dist/hooks/reduction.d.ts.map +1 -0
- package/dist/hooks/reduction.js +111 -0
- package/dist/hooks/reduction.js.map +1 -0
- package/dist/hooks/settings-merge.d.ts +32 -0
- package/dist/hooks/settings-merge.d.ts.map +1 -0
- package/dist/hooks/settings-merge.js +74 -0
- package/dist/hooks/settings-merge.js.map +1 -0
- package/dist/hooks/snapshot.d.ts +37 -0
- package/dist/hooks/snapshot.d.ts.map +1 -0
- package/dist/hooks/snapshot.js +180 -0
- package/dist/hooks/snapshot.js.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +118 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +240 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/onboarding-report.d.ts +66 -0
- package/dist/onboarding-report.d.ts.map +1 -0
- package/dist/onboarding-report.js +152 -0
- package/dist/onboarding-report.js.map +1 -0
- package/dist/onboarding.d.ts +55 -0
- package/dist/onboarding.d.ts.map +1 -0
- package/dist/onboarding.js +98 -0
- package/dist/onboarding.js.map +1 -0
- package/dist/pii-masker.d.ts +7 -0
- package/dist/pii-masker.d.ts.map +1 -1
- package/dist/pii-masker.js +27 -51
- package/dist/pii-masker.js.map +1 -1
- package/dist/privacy.d.ts +13 -0
- package/dist/privacy.d.ts.map +1 -0
- package/dist/privacy.js +67 -0
- package/dist/privacy.js.map +1 -0
- package/dist/residency.d.ts +21 -0
- package/dist/residency.d.ts.map +1 -0
- package/dist/residency.js +68 -0
- package/dist/residency.js.map +1 -0
- package/dist/secret-detector.d.ts +19 -0
- package/dist/secret-detector.d.ts.map +1 -1
- package/dist/secret-detector.js +116 -0
- package/dist/secret-detector.js.map +1 -1
- package/dist/store/local-store.d.ts +167 -0
- package/dist/store/local-store.d.ts.map +1 -0
- package/dist/store/local-store.js +538 -0
- package/dist/store/local-store.js.map +1 -0
- package/dist/store/schema.d.ts +38 -0
- package/dist/store/schema.d.ts.map +1 -0
- package/dist/store/schema.js +189 -0
- package/dist/store/schema.js.map +1 -0
- package/dist/types.d.ts +13 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/watcher.d.ts +6 -0
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +13 -2
- package/dist/watcher.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,57 @@
|
|
|
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.isHookPlatform = isHookPlatform;
|
|
7
|
+
exports.getPlatformConfig = getPlatformConfig;
|
|
8
|
+
exports.platformAcceptsEvent = platformAcceptsEvent;
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
// Read / NotebookRead を含む (#110 R1.5): Read 出力の退避・再読込キャッシュ・連続Read検知の対象。
|
|
12
|
+
// Edit 系は PreToolUse ブロック + 再読込キャッシュ無効化のため引き続き対象。
|
|
13
|
+
const TOOL_MATCHER = 'Bash|Write|Edit|MultiEdit|NotebookEdit|Read|NotebookRead';
|
|
14
|
+
const CLAUDE_CONFIG = {
|
|
15
|
+
id: 'claude-code',
|
|
16
|
+
events: ['PreToolUse', 'PostToolUse', 'UserPromptSubmit', 'SessionStart', 'PreCompact'],
|
|
17
|
+
denyOnly: false,
|
|
18
|
+
settingsFile: path_1.default.join(os_1.default.homedir(), '.claude', 'settings.json'),
|
|
19
|
+
commandMarker: 'promptkaizen-agent hook claude-code',
|
|
20
|
+
registrations: [
|
|
21
|
+
{ event: 'PreToolUse', matcher: TOOL_MATCHER },
|
|
22
|
+
{ event: 'PostToolUse', matcher: TOOL_MATCHER },
|
|
23
|
+
{ event: 'UserPromptSubmit' },
|
|
24
|
+
{ event: 'SessionStart' },
|
|
25
|
+
{ event: 'PreCompact' },
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
const CODEX_CONFIG = {
|
|
29
|
+
id: 'codex',
|
|
30
|
+
// Codex は PreCompact 非対応、代わりに Stop (ターン終了) を持つ。
|
|
31
|
+
events: ['PreToolUse', 'PostToolUse', 'UserPromptSubmit', 'SessionStart', 'Stop'],
|
|
32
|
+
denyOnly: true,
|
|
33
|
+
settingsFile: path_1.default.join(os_1.default.homedir(), '.codex', 'hooks.json'),
|
|
34
|
+
commandMarker: 'promptkaizen-agent hook codex',
|
|
35
|
+
registrations: [
|
|
36
|
+
{ event: 'PreToolUse', matcher: TOOL_MATCHER },
|
|
37
|
+
{ event: 'PostToolUse', matcher: TOOL_MATCHER },
|
|
38
|
+
{ event: 'UserPromptSubmit' },
|
|
39
|
+
{ event: 'SessionStart' },
|
|
40
|
+
{ event: 'Stop' },
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
const PLATFORMS = {
|
|
44
|
+
'claude-code': CLAUDE_CONFIG,
|
|
45
|
+
codex: CODEX_CONFIG,
|
|
46
|
+
};
|
|
47
|
+
function isHookPlatform(v) {
|
|
48
|
+
return v === 'claude-code' || v === 'codex';
|
|
49
|
+
}
|
|
50
|
+
function getPlatformConfig(platform) {
|
|
51
|
+
return PLATFORMS[platform];
|
|
52
|
+
}
|
|
53
|
+
/** プラットフォームがそのイベントを受理するか。 */
|
|
54
|
+
function platformAcceptsEvent(platform, event) {
|
|
55
|
+
return PLATFORMS[platform].events.includes(event);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=platforms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platforms.js","sourceRoot":"","sources":["../../src/hooks/platforms.ts"],"names":[],"mappings":";;;;;AA+EA,wCAEC;AAED,8CAEC;AAGD,oDAEC;AA1FD,4CAAmB;AACnB,gDAAuB;AAsCvB,wEAAwE;AACxE,kDAAkD;AAClD,MAAM,YAAY,GAAG,0DAA0D,CAAA;AAE/E,MAAM,aAAa,GAAmB;IACpC,EAAE,EAAE,aAAa;IACjB,MAAM,EAAE,CAAC,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,cAAc,EAAE,YAAY,CAAC;IACvF,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC;IACjE,aAAa,EAAE,qCAAqC;IACpD,aAAa,EAAE;QACb,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE;QAC9C,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE;QAC/C,EAAE,KAAK,EAAE,kBAAkB,EAAE;QAC7B,EAAE,KAAK,EAAE,cAAc,EAAE;QACzB,EAAE,KAAK,EAAE,YAAY,EAAE;KACxB;CACF,CAAA;AAED,MAAM,YAAY,GAAmB;IACnC,EAAE,EAAE,OAAO;IACX,gDAAgD;IAChD,MAAM,EAAE,CAAC,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,CAAC;IACjF,QAAQ,EAAE,IAAI;IACd,YAAY,EAAE,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,YAAY,CAAC;IAC7D,aAAa,EAAE,+BAA+B;IAC9C,aAAa,EAAE;QACb,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE;QAC9C,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE;QAC/C,EAAE,KAAK,EAAE,kBAAkB,EAAE;QAC7B,EAAE,KAAK,EAAE,cAAc,EAAE;QACzB,EAAE,KAAK,EAAE,MAAM,EAAE;KAClB;CACF,CAAA;AAED,MAAM,SAAS,GAAyC;IACtD,aAAa,EAAE,aAAa;IAC5B,KAAK,EAAE,YAAY;CACpB,CAAA;AAED,SAAgB,cAAc,CAAC,CAAU;IACvC,OAAO,CAAC,KAAK,aAAa,IAAI,CAAC,KAAK,OAAO,CAAA;AAC7C,CAAC;AAED,SAAgB,iBAAiB,CAAC,QAAsB;IACtD,OAAO,SAAS,CAAC,QAAQ,CAAC,CAAA;AAC5B,CAAC;AAED,6BAA6B;AAC7B,SAAgB,oBAAoB,CAAC,QAAsB,EAAE,KAAgB;IAC3E,OAAO,SAAS,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACnD,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { HookInput } from './claude-hook';
|
|
2
|
+
import { type ReductionMeta } from './reduction';
|
|
3
|
+
import type { StoredToolOutputRef } from '../store/local-store';
|
|
4
|
+
/** Read 系ツール (出力の退避・キャッシュ対象)。 */
|
|
5
|
+
export declare const READ_TOOLS: Set<string>;
|
|
6
|
+
/** 編集系ツール (キャッシュ無効化のトリガ)。snapshot.ts:EDIT_TOOLS と同一集合。 */
|
|
7
|
+
export declare const EDIT_TOOLS: Set<string>;
|
|
8
|
+
/** Read/NotebookRead の対象ファイルパスを返す (それ以外・パス不明は null)。 */
|
|
9
|
+
export declare function extractReadFilePath(input: HookInput): string | null;
|
|
10
|
+
/** Edit/Write 系の対象ファイルパスを返す (それ以外・パス不明は null)。 */
|
|
11
|
+
export declare function editedFilePath(input: HookInput): string | null;
|
|
12
|
+
/** マスク後テキストの内容ハッシュ (再読込同一判定キー)。 */
|
|
13
|
+
export declare function hashContent(maskedText: string): string;
|
|
14
|
+
/** キャッシュヒントの差し替えテキストを組み立てる。 */
|
|
15
|
+
export declare function buildCacheHintText(p: {
|
|
16
|
+
filePath: string;
|
|
17
|
+
refId: string;
|
|
18
|
+
originalTokens: number;
|
|
19
|
+
}): string;
|
|
20
|
+
/** キャッシュ判定の入力 (前回状態は呼び出し側が read_cache から取得して渡す)。 */
|
|
21
|
+
export interface ReadCacheInput {
|
|
22
|
+
input: HookInput;
|
|
23
|
+
/** PostToolUse の tool_response から取り出したマスク後テキスト。 */
|
|
24
|
+
maskedContent: string;
|
|
25
|
+
/** 直前の同一 (session, file) の内容ハッシュ (未記録なら null)。 */
|
|
26
|
+
prevHash: string | null;
|
|
27
|
+
/** 直前の退避 ref_id (全文取得用。null ならヒントを出さない)。 */
|
|
28
|
+
prevRefId: string | null;
|
|
29
|
+
/** 直前が Edit/Write で無効化されているか。 */
|
|
30
|
+
invalidated: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** キャッシュヒット時の結果 (差し替え + 削減メタ)。新規 ref は保存しない (前回 ref を指す)。 */
|
|
33
|
+
export interface ReadCacheHit {
|
|
34
|
+
updatedToolOutput: unknown;
|
|
35
|
+
meta: ReductionMeta;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 再読込キャッシュヒットか判定する。ヒット条件:
|
|
39
|
+
* 前回ハッシュと一致 / 無効化されていない / 前回 ref_id がある / 削減になる。
|
|
40
|
+
* いずれか欠ければ null (= ミス。呼び出し側は全文を通し、退避 + キャッシュ seed する)。
|
|
41
|
+
* 副作用なし。
|
|
42
|
+
*/
|
|
43
|
+
export declare function planReadCacheHit(p: ReadCacheInput): ReadCacheHit | null;
|
|
44
|
+
/**
|
|
45
|
+
* ③ 連続 Read 集約誘導 (#110)。transcript tail (JSONL) の末尾から連続する
|
|
46
|
+
* Read tool_use を数え、しきい値を「今ちょうど跨いだ」ときだけ advise=true を返す
|
|
47
|
+
* (跨いだ瞬間に 1 度だけ誘導を出し、以降の連続 Read では出さない)。
|
|
48
|
+
* 非 Read の tool_use が現れた時点で連続は途切れる。副作用なし。
|
|
49
|
+
*/
|
|
50
|
+
export declare function planBatchGuidance(transcriptTail: string, threshold: number): {
|
|
51
|
+
advise: boolean;
|
|
52
|
+
count: number;
|
|
53
|
+
};
|
|
54
|
+
/** 連続 Read 誘導の additionalContext テキスト。 */
|
|
55
|
+
export declare function buildBatchGuidance(count: number): string;
|
|
56
|
+
/**
|
|
57
|
+
* キャッシュミス時に保存する退避レコードを組み立てる (全文 body をマスク後で保持)。
|
|
58
|
+
* 退避は Read 全文 (サイズ問わず) を対象にし、次回の再読込をキャッシュヒットにできるようにする。
|
|
59
|
+
* 呼び出し側が LocalStore.recordToolOutputRef + upsertReadCache で保存する。
|
|
60
|
+
*/
|
|
61
|
+
export declare function buildReadCacheSeed(p: {
|
|
62
|
+
input: HookInput;
|
|
63
|
+
filePath: string;
|
|
64
|
+
maskedContent: string;
|
|
65
|
+
now: string;
|
|
66
|
+
refId?: string;
|
|
67
|
+
}): {
|
|
68
|
+
ref: StoredToolOutputRef;
|
|
69
|
+
contentHash: string;
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=read-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-cache.d.ts","sourceRoot":"","sources":["../../src/hooks/read-cache.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAe/D,iCAAiC;AACjC,eAAO,MAAM,UAAU,aAAoC,CAAA;AAC3D,0DAA0D;AAC1D,eAAO,MAAM,UAAU,aAA0D,CAAA;AAOjF,wDAAwD;AACxD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAKnE;AAED,kDAAkD;AAClD,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAK9D;AAED,mCAAmC;AACnC,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,+BAA+B;AAC/B,wBAAgB,kBAAkB,CAAC,CAAC,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAMzG;AAED,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAA;IAChB,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAA;IACrB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,iCAAiC;IACjC,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,OAAO,CAAA;IAC1B,IAAI,EAAE,aAAa,CAAA;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,cAAc,GAAG,YAAY,GAAG,IAAI,CAkBvE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,GAChB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CA6BpC;AAED,0CAA0C;AAC1C,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE;IACpC,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,GAAG;IAAE,GAAG,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAqBpD"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EDIT_TOOLS = exports.READ_TOOLS = void 0;
|
|
4
|
+
exports.extractReadFilePath = extractReadFilePath;
|
|
5
|
+
exports.editedFilePath = editedFilePath;
|
|
6
|
+
exports.hashContent = hashContent;
|
|
7
|
+
exports.buildCacheHintText = buildCacheHintText;
|
|
8
|
+
exports.planReadCacheHit = planReadCacheHit;
|
|
9
|
+
exports.planBatchGuidance = planBatchGuidance;
|
|
10
|
+
exports.buildBatchGuidance = buildBatchGuidance;
|
|
11
|
+
exports.buildReadCacheSeed = buildReadCacheSeed;
|
|
12
|
+
const crypto_1 = require("crypto");
|
|
13
|
+
const reduction_1 = require("./reduction");
|
|
14
|
+
// =============================================
|
|
15
|
+
// Read 再読込キャッシュ + 連続Read検知 (Issue #110 / Epic #91 R1.5) — 純粋ロジック
|
|
16
|
+
// =============================================
|
|
17
|
+
//
|
|
18
|
+
// ① 同一 file_path の 2 回目以降の Read を、内容ハッシュで前回と同一判定し、
|
|
19
|
+
// 全文の代わりに「前回と同一・ref_id」のキャッシュヒントに差し替える。
|
|
20
|
+
// 内容は既にセッション履歴 (コンテキスト) に居るため、再掲を省くのは純粋削減
|
|
21
|
+
// (pk_fetch の取り戻し相殺がかからない) — レポート上限値割引の対象外。
|
|
22
|
+
// ③ 連続 Read を検知し pk_execute での一括読みへ誘導する (ガイダンス注入)。
|
|
23
|
+
//
|
|
24
|
+
// 不変条件: ハッシュ・退避 body は **マスク後テキスト** を対象にする (生 PII を残さない)。
|
|
25
|
+
// I/O (SQLite・stdout) は cli/hook.ts が担い、本モジュールは判断のみ。
|
|
26
|
+
/** Read 系ツール (出力の退避・キャッシュ対象)。 */
|
|
27
|
+
exports.READ_TOOLS = new Set(['Read', 'NotebookRead']);
|
|
28
|
+
/** 編集系ツール (キャッシュ無効化のトリガ)。snapshot.ts:EDIT_TOOLS と同一集合。 */
|
|
29
|
+
exports.EDIT_TOOLS = new Set(['Edit', 'Write', 'MultiEdit', 'NotebookEdit']);
|
|
30
|
+
function toolInput(input) {
|
|
31
|
+
const ti = input.tool_input;
|
|
32
|
+
return ti && typeof ti === 'object' ? ti : {};
|
|
33
|
+
}
|
|
34
|
+
/** Read/NotebookRead の対象ファイルパスを返す (それ以外・パス不明は null)。 */
|
|
35
|
+
function extractReadFilePath(input) {
|
|
36
|
+
if (typeof input.tool_name !== 'string' || !exports.READ_TOOLS.has(input.tool_name))
|
|
37
|
+
return null;
|
|
38
|
+
const ti = toolInput(input);
|
|
39
|
+
const fp = ti.file_path ?? ti.notebook_path;
|
|
40
|
+
return typeof fp === 'string' && fp.length > 0 ? fp : null;
|
|
41
|
+
}
|
|
42
|
+
/** Edit/Write 系の対象ファイルパスを返す (それ以外・パス不明は null)。 */
|
|
43
|
+
function editedFilePath(input) {
|
|
44
|
+
if (typeof input.tool_name !== 'string' || !exports.EDIT_TOOLS.has(input.tool_name))
|
|
45
|
+
return null;
|
|
46
|
+
const ti = toolInput(input);
|
|
47
|
+
const fp = ti.file_path;
|
|
48
|
+
return typeof fp === 'string' && fp.length > 0 ? fp : null;
|
|
49
|
+
}
|
|
50
|
+
/** マスク後テキストの内容ハッシュ (再読込同一判定キー)。 */
|
|
51
|
+
function hashContent(maskedText) {
|
|
52
|
+
return (0, crypto_1.createHash)('sha256').update(maskedText, 'utf8').digest('hex');
|
|
53
|
+
}
|
|
54
|
+
/** キャッシュヒントの差し替えテキストを組み立てる。 */
|
|
55
|
+
function buildCacheHintText(p) {
|
|
56
|
+
return [
|
|
57
|
+
`[PromptKaizen R1.5] ${p.filePath} はこのセッションで前回読み込んだ内容と同一です (約 ${p.originalTokens.toLocaleString()} tokens)。`,
|
|
58
|
+
`再掲を省略しました。内容は会話履歴に既にあります。`,
|
|
59
|
+
`全文を再取得する場合: pk_fetch(ref_id: "${p.refId}")`,
|
|
60
|
+
].join('\n');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* 再読込キャッシュヒットか判定する。ヒット条件:
|
|
64
|
+
* 前回ハッシュと一致 / 無効化されていない / 前回 ref_id がある / 削減になる。
|
|
65
|
+
* いずれか欠ければ null (= ミス。呼び出し側は全文を通し、退避 + キャッシュ seed する)。
|
|
66
|
+
* 副作用なし。
|
|
67
|
+
*/
|
|
68
|
+
function planReadCacheHit(p) {
|
|
69
|
+
const filePath = extractReadFilePath(p.input);
|
|
70
|
+
if (!filePath)
|
|
71
|
+
return null;
|
|
72
|
+
if (p.invalidated || !p.prevHash || !p.prevRefId)
|
|
73
|
+
return null;
|
|
74
|
+
if (hashContent(p.maskedContent) !== p.prevHash)
|
|
75
|
+
return null;
|
|
76
|
+
const originalTokens = (0, reduction_1.estimateTokensFromText)(p.maskedContent);
|
|
77
|
+
const hint = buildCacheHintText({ filePath, refId: p.prevRefId, originalTokens });
|
|
78
|
+
const replacedTokens = (0, reduction_1.estimateTokensFromText)(hint);
|
|
79
|
+
const savedTokens = originalTokens - replacedTokens;
|
|
80
|
+
if (savedTokens <= 0)
|
|
81
|
+
return null;
|
|
82
|
+
const extracted = (0, reduction_1.extractToolResponse)(p.input);
|
|
83
|
+
if (!extracted)
|
|
84
|
+
return null;
|
|
85
|
+
return {
|
|
86
|
+
updatedToolOutput: extracted.wrap(hint),
|
|
87
|
+
meta: { kind: 'cache_hit', refId: p.prevRefId, originalTokens, replacedTokens, savedTokens },
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* ③ 連続 Read 集約誘導 (#110)。transcript tail (JSONL) の末尾から連続する
|
|
92
|
+
* Read tool_use を数え、しきい値を「今ちょうど跨いだ」ときだけ advise=true を返す
|
|
93
|
+
* (跨いだ瞬間に 1 度だけ誘導を出し、以降の連続 Read では出さない)。
|
|
94
|
+
* 非 Read の tool_use が現れた時点で連続は途切れる。副作用なし。
|
|
95
|
+
*/
|
|
96
|
+
function planBatchGuidance(transcriptTail, threshold) {
|
|
97
|
+
const lines = transcriptTail.split('\n');
|
|
98
|
+
let total = 0;
|
|
99
|
+
let lastTurnReads = 0;
|
|
100
|
+
let turnsSeen = 0;
|
|
101
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
102
|
+
const line = lines[i].trim();
|
|
103
|
+
if (!line)
|
|
104
|
+
continue;
|
|
105
|
+
let d;
|
|
106
|
+
try {
|
|
107
|
+
d = JSON.parse(line);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (d.type !== 'assistant')
|
|
113
|
+
continue;
|
|
114
|
+
const content = d.message?.content;
|
|
115
|
+
if (!Array.isArray(content))
|
|
116
|
+
continue;
|
|
117
|
+
const toolUses = content.filter((b) => !!b && typeof b === 'object' && b.type === 'tool_use');
|
|
118
|
+
if (toolUses.length === 0)
|
|
119
|
+
continue; // text のみのターンは連続を途切れさせない
|
|
120
|
+
const allRead = toolUses.every((b) => typeof b.name === 'string' && exports.READ_TOOLS.has(b.name));
|
|
121
|
+
if (!allRead)
|
|
122
|
+
break;
|
|
123
|
+
total += toolUses.length;
|
|
124
|
+
if (turnsSeen === 0)
|
|
125
|
+
lastTurnReads = toolUses.length;
|
|
126
|
+
turnsSeen++;
|
|
127
|
+
}
|
|
128
|
+
const prev = total - lastTurnReads;
|
|
129
|
+
return { advise: prev < threshold && total >= threshold, count: total };
|
|
130
|
+
}
|
|
131
|
+
/** 連続 Read 誘導の additionalContext テキスト。 */
|
|
132
|
+
function buildBatchGuidance(count) {
|
|
133
|
+
return [
|
|
134
|
+
`[PromptKaizen R1.5] 直近 ${count} 連続で個別の Read を実行しています。`,
|
|
135
|
+
`複数ファイルをまとめて読むと、ツール往復とコンテキスト消費を削減できます。`,
|
|
136
|
+
`pk_execute での一括読み込み (例: 必要ファイルを 1 スクリプトでまとめて出力) を検討してください。`,
|
|
137
|
+
].join('\n');
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* キャッシュミス時に保存する退避レコードを組み立てる (全文 body をマスク後で保持)。
|
|
141
|
+
* 退避は Read 全文 (サイズ問わず) を対象にし、次回の再読込をキャッシュヒットにできるようにする。
|
|
142
|
+
* 呼び出し側が LocalStore.recordToolOutputRef + upsertReadCache で保存する。
|
|
143
|
+
*/
|
|
144
|
+
function buildReadCacheSeed(p) {
|
|
145
|
+
const refId = p.refId ?? (0, reduction_1.generateRefId)();
|
|
146
|
+
const tokens = (0, reduction_1.estimateTokensFromText)(p.maskedContent);
|
|
147
|
+
return {
|
|
148
|
+
contentHash: hashContent(p.maskedContent),
|
|
149
|
+
ref: {
|
|
150
|
+
refId,
|
|
151
|
+
sessionId: typeof p.input.session_id === 'string' ? p.input.session_id : null,
|
|
152
|
+
toolName: typeof p.input.tool_name === 'string' ? p.input.tool_name : null,
|
|
153
|
+
cwd: typeof p.input.cwd === 'string' ? p.input.cwd : null,
|
|
154
|
+
createdAt: p.now,
|
|
155
|
+
originalBytes: Buffer.byteLength(p.maskedContent, 'utf8'),
|
|
156
|
+
originalTokens: tokens,
|
|
157
|
+
replacedTokens: tokens, // seed 時点では差し替えていない (削減は cache_hit/offload 側で計上)
|
|
158
|
+
savedTokens: 0,
|
|
159
|
+
body: p.maskedContent,
|
|
160
|
+
filePath: p.filePath,
|
|
161
|
+
contentHash: hashContent(p.maskedContent),
|
|
162
|
+
kind: 'offload',
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=read-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-cache.js","sourceRoot":"","sources":["../../src/hooks/read-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { HookInput } from './claude-hook';
|
|
2
|
+
import type { StoredToolOutputRef } from '../store/local-store';
|
|
3
|
+
/** ParsedEntry.reduction / cloud 送信に載せる削減実績メタ (#92 actualSavings 互換)。 */
|
|
4
|
+
export interface ReductionMeta {
|
|
5
|
+
/**
|
|
6
|
+
* #92 ReductionEvent.kind と同値。
|
|
7
|
+
* R1=退避(r1_offload) / R2=サンドボックス実行 / R3=復元 /
|
|
8
|
+
* R1.5 Read 特化 (#110): cache_hit=再読込キャッシュ / batch=連続Read集約誘導。
|
|
9
|
+
*/
|
|
10
|
+
kind: 'r1_offload' | 'r2_execute' | 'r3_recall' | 'cache_hit' | 'batch';
|
|
11
|
+
refId: string;
|
|
12
|
+
/** 退避前のツール出力の推定トークン (マスク後本文基準)。 */
|
|
13
|
+
originalTokens: number;
|
|
14
|
+
/** 差し替え後テキストの推定トークン。 */
|
|
15
|
+
replacedTokens: number;
|
|
16
|
+
/** 実際に削減したトークン (original - replaced)。 */
|
|
17
|
+
savedTokens: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ReductionOutcome {
|
|
20
|
+
/**
|
|
21
|
+
* Claude Code に返す差し替え値 (hookSpecificOutput.updatedToolOutput)。
|
|
22
|
+
* 元の tool_response と同じ shape (string ならば string、{stdout,...} ならば
|
|
23
|
+
* stdout だけ差し替えた object)。shape が一致しないと Claude Code 側で
|
|
24
|
+
* 黙って棄却される (2.1.176 実機確認)。
|
|
25
|
+
*/
|
|
26
|
+
updatedToolOutput: unknown;
|
|
27
|
+
/** 退避レコード (呼び出し側が LocalStore.recordToolOutputRef で保存する)。 */
|
|
28
|
+
ref: StoredToolOutputRef;
|
|
29
|
+
meta: ReductionMeta;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 文字数からのトークン概算 (英数 4 文字 / 非 ASCII 1 文字 ≒ 1 token)。
|
|
33
|
+
* extension/src/core/stream-parser.ts・functions/src/org/orgSavings.ts と同一式。
|
|
34
|
+
* agent は @promptkaizen/shared を runtime 依存に持たないためここに移植。
|
|
35
|
+
*/
|
|
36
|
+
export declare function estimateTokensFromText(text: string): number;
|
|
37
|
+
/** tool_response からの抽出結果。wrap は差し替えテキストを元の shape に包み直す。 */
|
|
38
|
+
export interface ExtractedToolResponse {
|
|
39
|
+
text: string;
|
|
40
|
+
wrap: (replacement: string) => unknown;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* PostToolUse の tool_response から退避対象テキストを取り出す。
|
|
44
|
+
* Claude Code は updatedToolOutput を元のツール出力と同じ shape か検証し、
|
|
45
|
+
* 不一致なら適用せず原文を通す (2.1.176 実機確認 — #93 dogfooding)。そのため
|
|
46
|
+
* - string はそのまま差し替え
|
|
47
|
+
* - Bash 等の { stdout: string, ... } は stdout のみ退避し、他フィールドを
|
|
48
|
+
* 保持したまま同じ object 形に包み直す
|
|
49
|
+
* - shape 不明な object は無介入 (差し替えても棄却されるだけのため)
|
|
50
|
+
*/
|
|
51
|
+
export declare function extractToolResponse(input: HookInput): ExtractedToolResponse | null;
|
|
52
|
+
/** 参照ID (置換テキストと SQLite を突き合わせるキー)。 */
|
|
53
|
+
export declare function generateRefId(): string;
|
|
54
|
+
/** 差し替えテキストを組み立てる。previewText はマスク済みであること。 */
|
|
55
|
+
export declare function buildReplacementText(p: {
|
|
56
|
+
refId: string;
|
|
57
|
+
originalTokens: number;
|
|
58
|
+
originalBytes: number;
|
|
59
|
+
totalLines: number;
|
|
60
|
+
previewText: string;
|
|
61
|
+
}): string;
|
|
62
|
+
export interface PlanReductionInput {
|
|
63
|
+
input: HookInput;
|
|
64
|
+
/** マスキング前置パイプライン。退避 body・プレビューは必ずこれを通す。 */
|
|
65
|
+
maskText: (text: string) => string;
|
|
66
|
+
thresholdBytes: number;
|
|
67
|
+
headChars: number;
|
|
68
|
+
now?: string;
|
|
69
|
+
/** テスト注入用。省略時は generateRefId()。 */
|
|
70
|
+
refId?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 退避すべきか判定し、退避レコード + 差し替えテキスト + 削減メタを組み立てる。
|
|
74
|
+
* 閾値未満・テキスト不在・削減にならない場合は null (完全に無介入)。
|
|
75
|
+
* 副作用なし — SQLite への保存と stdout 出力は呼び出し側が行う。
|
|
76
|
+
*/
|
|
77
|
+
export declare function planReduction(p: PlanReductionInput): ReductionOutcome | null;
|
|
78
|
+
//# sourceMappingURL=reduction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reduction.d.ts","sourceRoot":"","sources":["../../src/hooks/reduction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAiB/D,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,IAAI,EAAE,YAAY,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAA;IACvE,KAAK,EAAE,MAAM,CAAA;IACb,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAA;IACtB,wBAAwB;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAA;IAC1B,4DAA4D;IAC5D,GAAG,EAAE,mBAAmB,CAAA;IACxB,IAAI,EAAE,aAAa,CAAA;CACpB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS3D;AAED,2DAA2D;AAC3D,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAA;CACvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,qBAAqB,GAAG,IAAI,CAQlF;AAED,uCAAuC;AACvC,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,8CAA8C;AAC9C,wBAAgB,oBAAoB,CAAC,CAAC,EAAE;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,MAAM,CAYT;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,SAAS,CAAA;IAChB,2CAA2C;IAC3C,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IAClC,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,IAAI,CAyC5E"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.estimateTokensFromText = estimateTokensFromText;
|
|
4
|
+
exports.extractToolResponse = extractToolResponse;
|
|
5
|
+
exports.generateRefId = generateRefId;
|
|
6
|
+
exports.buildReplacementText = buildReplacementText;
|
|
7
|
+
exports.planReduction = planReduction;
|
|
8
|
+
const crypto_1 = require("crypto");
|
|
9
|
+
/**
|
|
10
|
+
* 文字数からのトークン概算 (英数 4 文字 / 非 ASCII 1 文字 ≒ 1 token)。
|
|
11
|
+
* extension/src/core/stream-parser.ts・functions/src/org/orgSavings.ts と同一式。
|
|
12
|
+
* agent は @promptkaizen/shared を runtime 依存に持たないためここに移植。
|
|
13
|
+
*/
|
|
14
|
+
function estimateTokensFromText(text) {
|
|
15
|
+
if (!text)
|
|
16
|
+
return 0;
|
|
17
|
+
let ascii = 0;
|
|
18
|
+
let nonAscii = 0;
|
|
19
|
+
for (const ch of text) {
|
|
20
|
+
if (ch.codePointAt(0) < 128)
|
|
21
|
+
ascii++;
|
|
22
|
+
else
|
|
23
|
+
nonAscii++;
|
|
24
|
+
}
|
|
25
|
+
return Math.ceil(ascii / 4 + nonAscii);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* PostToolUse の tool_response から退避対象テキストを取り出す。
|
|
29
|
+
* Claude Code は updatedToolOutput を元のツール出力と同じ shape か検証し、
|
|
30
|
+
* 不一致なら適用せず原文を通す (2.1.176 実機確認 — #93 dogfooding)。そのため
|
|
31
|
+
* - string はそのまま差し替え
|
|
32
|
+
* - Bash 等の { stdout: string, ... } は stdout のみ退避し、他フィールドを
|
|
33
|
+
* 保持したまま同じ object 形に包み直す
|
|
34
|
+
* - shape 不明な object は無介入 (差し替えても棄却されるだけのため)
|
|
35
|
+
*/
|
|
36
|
+
function extractToolResponse(input) {
|
|
37
|
+
const v = input.tool_response;
|
|
38
|
+
if (typeof v === 'string')
|
|
39
|
+
return { text: v, wrap: (r) => r };
|
|
40
|
+
if (v && typeof v === 'object' && typeof v.stdout === 'string') {
|
|
41
|
+
const obj = v;
|
|
42
|
+
return { text: obj.stdout, wrap: (r) => ({ ...obj, stdout: r }) };
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/** 参照ID (置換テキストと SQLite を突き合わせるキー)。 */
|
|
47
|
+
function generateRefId() {
|
|
48
|
+
return `pk-${(0, crypto_1.randomBytes)(6).toString('hex')}`;
|
|
49
|
+
}
|
|
50
|
+
/** 差し替えテキストを組み立てる。previewText はマスク済みであること。 */
|
|
51
|
+
function buildReplacementText(p) {
|
|
52
|
+
const kb = (p.originalBytes / 1024).toFixed(1);
|
|
53
|
+
return [
|
|
54
|
+
`[PromptKaizen R1] このツール出力 (約 ${p.originalTokens.toLocaleString()} tokens / ${kb} KB / ${p.totalLines} 行) は閾値超過のためローカルへ退避されました。`,
|
|
55
|
+
`ref_id: ${p.refId}`,
|
|
56
|
+
`取り出し方法: MCP ツール pk_fetch を使用してください。`,
|
|
57
|
+
` - 全文: pk_fetch(ref_id: "${p.refId}")`,
|
|
58
|
+
` - 絞り込み (推奨): pk_fetch(ref_id: "${p.refId}", query: "検索語") — 該当行と前後の文脈を返します`,
|
|
59
|
+
`--- 先頭プレビュー (マスク済み) ---`,
|
|
60
|
+
p.previewText,
|
|
61
|
+
`--- プレビューここまで ---`,
|
|
62
|
+
].join('\n');
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 退避すべきか判定し、退避レコード + 差し替えテキスト + 削減メタを組み立てる。
|
|
66
|
+
* 閾値未満・テキスト不在・削減にならない場合は null (完全に無介入)。
|
|
67
|
+
* 副作用なし — SQLite への保存と stdout 出力は呼び出し側が行う。
|
|
68
|
+
*/
|
|
69
|
+
function planReduction(p) {
|
|
70
|
+
const extracted = extractToolResponse(p.input);
|
|
71
|
+
if (!extracted || !extracted.text)
|
|
72
|
+
return null;
|
|
73
|
+
const text = extracted.text;
|
|
74
|
+
// 閾値判定は生テキストのバイト長 (マスクは超過時のみ実行してコストを抑える)。
|
|
75
|
+
if (Buffer.byteLength(text, 'utf8') <= p.thresholdBytes)
|
|
76
|
+
return null;
|
|
77
|
+
const masked = p.maskText(text);
|
|
78
|
+
const originalBytes = Buffer.byteLength(masked, 'utf8');
|
|
79
|
+
const originalTokens = estimateTokensFromText(masked);
|
|
80
|
+
const refId = p.refId ?? generateRefId();
|
|
81
|
+
const now = p.now ?? new Date().toISOString();
|
|
82
|
+
const replacementText = buildReplacementText({
|
|
83
|
+
refId,
|
|
84
|
+
originalTokens,
|
|
85
|
+
originalBytes,
|
|
86
|
+
totalLines: masked.split('\n').length,
|
|
87
|
+
previewText: masked.slice(0, p.headChars),
|
|
88
|
+
});
|
|
89
|
+
const replacedTokens = estimateTokensFromText(replacementText);
|
|
90
|
+
const savedTokens = originalTokens - replacedTokens;
|
|
91
|
+
// 差し替えで削減にならないなら介入しない (閾値が極端に小さい場合の保険)。
|
|
92
|
+
if (savedTokens <= 0)
|
|
93
|
+
return null;
|
|
94
|
+
return {
|
|
95
|
+
updatedToolOutput: extracted.wrap(replacementText),
|
|
96
|
+
ref: {
|
|
97
|
+
refId,
|
|
98
|
+
sessionId: typeof p.input.session_id === 'string' ? p.input.session_id : null,
|
|
99
|
+
toolName: typeof p.input.tool_name === 'string' ? p.input.tool_name : null,
|
|
100
|
+
cwd: typeof p.input.cwd === 'string' ? p.input.cwd : null,
|
|
101
|
+
createdAt: now,
|
|
102
|
+
originalBytes,
|
|
103
|
+
originalTokens,
|
|
104
|
+
replacedTokens,
|
|
105
|
+
savedTokens,
|
|
106
|
+
body: masked,
|
|
107
|
+
},
|
|
108
|
+
meta: { kind: 'r1_offload', refId, originalTokens, replacedTokens, savedTokens },
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=reduction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reduction.js","sourceRoot":"","sources":["../../src/hooks/reduction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { HookRegistration } from './platforms';
|
|
2
|
+
/** PromptKaizen hook command の既定識別子 (Claude Code、後方互換)。 */
|
|
3
|
+
export declare const HOOK_COMMAND_MARKER = "promptkaizen-agent hook claude-code";
|
|
4
|
+
/** 既定の登録 (Claude Code)。PreToolUse/PostToolUse は Bash 等のツール実行に限定。 */
|
|
5
|
+
export declare const HOOK_REGISTRATIONS: HookRegistration[];
|
|
6
|
+
interface HookCommand {
|
|
7
|
+
type: 'command';
|
|
8
|
+
command: string;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
}
|
|
11
|
+
interface HookMatcherGroup {
|
|
12
|
+
matcher?: string;
|
|
13
|
+
hooks: HookCommand[];
|
|
14
|
+
}
|
|
15
|
+
interface Settings {
|
|
16
|
+
hooks?: Record<string, HookMatcherGroup[]>;
|
|
17
|
+
[k: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* settings に PromptKaizen の hooks をマージする (既存は保持)。
|
|
21
|
+
* 同一イベントに当社 hook が既にあれば command/matcher を最新に更新し重複を作らない。
|
|
22
|
+
*/
|
|
23
|
+
export declare function mergeHooks(settings: Settings, registrations?: HookRegistration[], marker?: string): Settings;
|
|
24
|
+
/**
|
|
25
|
+
* settings から PromptKaizen の hooks のみ除去する (他の hooks は保持)。
|
|
26
|
+
* 当社 hook を除いた結果 matcher group が空になったイベントキーは削除する。
|
|
27
|
+
*/
|
|
28
|
+
export declare function removeHooks(settings: Settings, marker?: string): Settings;
|
|
29
|
+
/** settings に当社 hook が登録済みか。 */
|
|
30
|
+
export declare function hasOurHooks(settings: Settings, marker?: string): boolean;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=settings-merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-merge.d.ts","sourceRoot":"","sources":["../../src/hooks/settings-merge.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEnD,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB,wCAAwC,CAAA;AAExE,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAMhD,CAAA;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,SAAS,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AACD,UAAU,gBAAgB;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,WAAW,EAAE,CAAA;CACrB;AACD,UAAU,QAAQ;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAA;IAC1C,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAMD;;;GAGG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,QAAQ,EAClB,aAAa,GAAE,gBAAgB,EAAuB,EACtD,MAAM,GAAE,MAA4B,GACnC,QAAQ,CAeV;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAE,MAA4B,GAAG,QAAQ,CAW9F;AAED,gCAAgC;AAChC,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAE,MAA4B,GAAG,OAAO,CAE7F"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// =============================================
|
|
3
|
+
// settings/hooks.json への hooks 登録/解除 (Issue #67 Claude / #70 Codex) — 純粋ロジック
|
|
4
|
+
// =============================================
|
|
5
|
+
//
|
|
6
|
+
// Claude Code (~/.claude/settings.json) と Codex CLI (~/.codex/hooks.json) は同構造で、
|
|
7
|
+
// hooks をイベント名ごとの配列で持つ:
|
|
8
|
+
// { "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ {type,command} ] } ] } }
|
|
9
|
+
//
|
|
10
|
+
// ファイル I/O から切り離した純粋関数で既存設定を壊さずにマージ/除去する (テスト容易性)。
|
|
11
|
+
// PromptKaizen の hook は command に固定マーカー (commandMarker) を持たせ、解除時はその
|
|
12
|
+
// マーカーを含む entry だけを取り除く (他の hooks を破壊しない)。プラットフォーム差は
|
|
13
|
+
// marker / registrations を引数で渡すことで吸収する (既定は Claude Code、後方互換)。
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.HOOK_REGISTRATIONS = exports.HOOK_COMMAND_MARKER = void 0;
|
|
16
|
+
exports.mergeHooks = mergeHooks;
|
|
17
|
+
exports.removeHooks = removeHooks;
|
|
18
|
+
exports.hasOurHooks = hasOurHooks;
|
|
19
|
+
/** PromptKaizen hook command の既定識別子 (Claude Code、後方互換)。 */
|
|
20
|
+
exports.HOOK_COMMAND_MARKER = 'promptkaizen-agent hook claude-code';
|
|
21
|
+
/** 既定の登録 (Claude Code)。PreToolUse/PostToolUse は Bash 等のツール実行に限定。 */
|
|
22
|
+
exports.HOOK_REGISTRATIONS = [
|
|
23
|
+
{ event: 'PreToolUse', matcher: 'Bash|Write|Edit|MultiEdit|NotebookEdit|Read|NotebookRead' },
|
|
24
|
+
{ event: 'PostToolUse', matcher: 'Bash|Write|Edit|MultiEdit|NotebookEdit|Read|NotebookRead' },
|
|
25
|
+
{ event: 'UserPromptSubmit' },
|
|
26
|
+
{ event: 'SessionStart' },
|
|
27
|
+
{ event: 'PreCompact' },
|
|
28
|
+
];
|
|
29
|
+
function isOurGroup(group, marker) {
|
|
30
|
+
return group.hooks?.some((h) => typeof h.command === 'string' && h.command.includes(marker));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* settings に PromptKaizen の hooks をマージする (既存は保持)。
|
|
34
|
+
* 同一イベントに当社 hook が既にあれば command/matcher を最新に更新し重複を作らない。
|
|
35
|
+
*/
|
|
36
|
+
function mergeHooks(settings, registrations = exports.HOOK_REGISTRATIONS, marker = exports.HOOK_COMMAND_MARKER) {
|
|
37
|
+
const next = { ...settings };
|
|
38
|
+
const hooks = { ...(settings.hooks ?? {}) };
|
|
39
|
+
for (const reg of registrations) {
|
|
40
|
+
const existing = (hooks[reg.event] ?? []).filter((g) => !isOurGroup(g, marker)); // 当社分は一旦除去
|
|
41
|
+
const ourGroup = {
|
|
42
|
+
...(reg.matcher ? { matcher: reg.matcher } : {}),
|
|
43
|
+
hooks: [{ type: 'command', command: `${marker} ${reg.event}`, timeout: 10 }],
|
|
44
|
+
};
|
|
45
|
+
hooks[reg.event] = [...existing, ourGroup];
|
|
46
|
+
}
|
|
47
|
+
next.hooks = hooks;
|
|
48
|
+
return next;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* settings から PromptKaizen の hooks のみ除去する (他の hooks は保持)。
|
|
52
|
+
* 当社 hook を除いた結果 matcher group が空になったイベントキーは削除する。
|
|
53
|
+
*/
|
|
54
|
+
function removeHooks(settings, marker = exports.HOOK_COMMAND_MARKER) {
|
|
55
|
+
const next = { ...settings };
|
|
56
|
+
if (!settings.hooks)
|
|
57
|
+
return next;
|
|
58
|
+
const hooks = {};
|
|
59
|
+
for (const [event, groups] of Object.entries(settings.hooks)) {
|
|
60
|
+
const kept = (groups ?? []).filter((g) => !isOurGroup(g, marker));
|
|
61
|
+
if (kept.length > 0)
|
|
62
|
+
hooks[event] = kept;
|
|
63
|
+
}
|
|
64
|
+
if (Object.keys(hooks).length > 0)
|
|
65
|
+
next.hooks = hooks;
|
|
66
|
+
else
|
|
67
|
+
delete next.hooks;
|
|
68
|
+
return next;
|
|
69
|
+
}
|
|
70
|
+
/** settings に当社 hook が登録済みか。 */
|
|
71
|
+
function hasOurHooks(settings, marker = exports.HOOK_COMMAND_MARKER) {
|
|
72
|
+
return Object.values(settings.hooks ?? {}).some((groups) => groups.some((g) => isOurGroup(g, marker)));
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=settings-merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-merge.js","sourceRoot":"","sources":["../../src/hooks/settings-merge.ts"],"names":[],"mappings":"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"}
|