promptkaizen-agent 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/README.md +131 -0
- package/dist/batcher.d.ts +25 -0
- package/dist/batcher.d.ts.map +1 -0
- package/dist/batcher.js +117 -0
- package/dist/batcher.js.map +1 -0
- package/dist/cli/init.d.ts +12 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +138 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/install-launchd.d.ts +17 -0
- package/dist/cli/install-launchd.d.ts.map +1 -0
- package/dist/cli/install-launchd.js +128 -0
- package/dist/cli/install-launchd.js.map +1 -0
- package/dist/cli/start.d.ts +8 -0
- package/dist/cli/start.d.ts.map +1 -0
- package/dist/cli/start.js +170 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/cli/status.d.ts +12 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +172 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/uninstall-launchd.d.ts +8 -0
- package/dist/cli/uninstall-launchd.d.ts.map +1 -0
- package/dist/cli/uninstall-launchd.js +55 -0
- package/dist/cli/uninstall-launchd.js.map +1 -0
- package/dist/config.d.ts +114 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +78 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +71 -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 +33 -0
- package/dist/logger.js.map +1 -0
- package/dist/offset-store.d.ts +22 -0
- package/dist/offset-store.d.ts.map +1 -0
- package/dist/offset-store.js +76 -0
- package/dist/offset-store.js.map +1 -0
- package/dist/parser.d.ts +20 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +118 -0
- package/dist/parser.js.map +1 -0
- package/dist/pii-masker.d.ts +19 -0
- package/dist/pii-masker.d.ts.map +1 -0
- package/dist/pii-masker.js +136 -0
- package/dist/pii-masker.js.map +1 -0
- package/dist/sender.d.ts +21 -0
- package/dist/sender.d.ts.map +1 -0
- package/dist/sender.js +69 -0
- package/dist/sender.js.map +1 -0
- package/dist/source.d.ts +3 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +31 -0
- package/dist/source.js.map +1 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/dist/watcher.d.ts +22 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +63 -0
- package/dist/watcher.js.map +1 -0
- package/package.json +39 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const init_1 = require("./cli/init");
|
|
5
|
+
const install_launchd_1 = require("./cli/install-launchd");
|
|
6
|
+
const start_1 = require("./cli/start");
|
|
7
|
+
const status_1 = require("./cli/status");
|
|
8
|
+
const uninstall_launchd_1 = require("./cli/uninstall-launchd");
|
|
9
|
+
const version_1 = require("./version");
|
|
10
|
+
const HELP = `promptkaizen-agent v${version_1.AGENT_VERSION}
|
|
11
|
+
|
|
12
|
+
Local observability agent for Claude Code & OpenAI Codex CLI (Bプラン).
|
|
13
|
+
Watches ~/.claude/projects/*.jsonl and ~/.codex/sessions/**/rollout-*.jsonl
|
|
14
|
+
and ships observations to PromptKaizen Cloud.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
promptkaizen-agent <subcommand>
|
|
18
|
+
|
|
19
|
+
Subcommands:
|
|
20
|
+
init Interactive setup — write ~/.promptkaizen/agent.config.json
|
|
21
|
+
start Run the agent in the foreground (used by launchd too)
|
|
22
|
+
status Health check: config, plist, process, offsets, endpoint
|
|
23
|
+
install-launchd Register a macOS LaunchAgent — auto-start on login + auto-restart
|
|
24
|
+
uninstall-launchd Remove the LaunchAgent (config/offsets preserved)
|
|
25
|
+
version Print agent version
|
|
26
|
+
help Print this message
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
npm link # one-time, from repo root after build
|
|
30
|
+
promptkaizen-agent init
|
|
31
|
+
promptkaizen-agent install-launchd
|
|
32
|
+
promptkaizen-agent status
|
|
33
|
+
`;
|
|
34
|
+
async function main() {
|
|
35
|
+
const [sub, ...rest] = process.argv.slice(2);
|
|
36
|
+
switch (sub) {
|
|
37
|
+
case 'init':
|
|
38
|
+
return (0, init_1.runInit)(rest);
|
|
39
|
+
case 'start':
|
|
40
|
+
return (0, start_1.runStart)(rest);
|
|
41
|
+
case 'status':
|
|
42
|
+
return (0, status_1.runStatus)(rest);
|
|
43
|
+
case 'install-launchd':
|
|
44
|
+
return (0, install_launchd_1.runInstallLaunchd)(rest);
|
|
45
|
+
case 'uninstall-launchd':
|
|
46
|
+
return (0, uninstall_launchd_1.runUninstallLaunchd)(rest);
|
|
47
|
+
case 'version':
|
|
48
|
+
case '--version':
|
|
49
|
+
case '-v':
|
|
50
|
+
console.log(version_1.AGENT_VERSION);
|
|
51
|
+
return;
|
|
52
|
+
case undefined:
|
|
53
|
+
case 'help':
|
|
54
|
+
case '--help':
|
|
55
|
+
case '-h':
|
|
56
|
+
console.log(HELP);
|
|
57
|
+
return;
|
|
58
|
+
default:
|
|
59
|
+
console.error(`Unknown subcommand: ${sub}\n`);
|
|
60
|
+
console.error(HELP);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
main().catch((err) => {
|
|
65
|
+
console.error(`Fatal: ${err.message}`);
|
|
66
|
+
if (process.env.PROMPTKAIZEN_AGENT_DEBUG === '1' && err.stack) {
|
|
67
|
+
console.error(err.stack);
|
|
68
|
+
}
|
|
69
|
+
process.exit(1);
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,qCAAoC;AACpC,2DAAyD;AACzD,uCAAsC;AACtC,yCAAwC;AACxC,+DAA6D;AAC7D,uCAAyC;AAEzC,MAAM,IAAI,GAAG,uBAAuB,uBAAa;;;;;;;;;;;;;;;;;;;;;;;CAuBhD,CAAA;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC5C,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,MAAM;YACT,OAAO,IAAA,cAAO,EAAC,IAAI,CAAC,CAAA;QACtB,KAAK,OAAO;YACV,OAAO,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAA;QACvB,KAAK,QAAQ;YACX,OAAO,IAAA,kBAAS,EAAC,IAAI,CAAC,CAAA;QACxB,KAAK,iBAAiB;YACpB,OAAO,IAAA,mCAAiB,EAAC,IAAI,CAAC,CAAA;QAChC,KAAK,mBAAmB;YACtB,OAAO,IAAA,uCAAmB,EAAC,IAAI,CAAC,CAAA;QAClC,KAAK,SAAS,CAAC;QACf,KAAK,WAAW,CAAC;QACjB,KAAK,IAAI;YACP,OAAO,CAAC,GAAG,CAAC,uBAAa,CAAC,CAAA;YAC1B,OAAM;QACR,KAAK,SAAS,CAAC;QACf,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI;YACP,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACjB,OAAM;QACR;YACE,OAAO,CAAC,KAAK,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAA;YAC7C,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IAC1B,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;IACtC,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QAC9D,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const logger: {
|
|
2
|
+
debug: (msg: string, meta?: Record<string, unknown>) => void;
|
|
3
|
+
info: (msg: string, meta?: Record<string, unknown>) => void;
|
|
4
|
+
warn: (msg: string, meta?: Record<string, unknown>) => void;
|
|
5
|
+
error: (msg: string, meta?: Record<string, unknown>) => void;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,MAAM;iBACJ,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBACvC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBACtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;iBACrC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CACpD,CAAA"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
const LEVELS = { debug: 10, info: 20, warn: 30, error: 40 };
|
|
5
|
+
function currentThreshold() {
|
|
6
|
+
const env = (process.env.PROMPTKAIZEN_AGENT_LOG_LEVEL ?? 'info').toLowerCase();
|
|
7
|
+
return LEVELS[env] ?? LEVELS.info;
|
|
8
|
+
}
|
|
9
|
+
function emit(level, msg, meta) {
|
|
10
|
+
if (LEVELS[level] < currentThreshold())
|
|
11
|
+
return;
|
|
12
|
+
const record = {
|
|
13
|
+
ts: new Date().toISOString(),
|
|
14
|
+
level,
|
|
15
|
+
msg,
|
|
16
|
+
};
|
|
17
|
+
if (meta)
|
|
18
|
+
Object.assign(record, meta);
|
|
19
|
+
const line = JSON.stringify(record);
|
|
20
|
+
if (level === 'error' || level === 'warn') {
|
|
21
|
+
process.stderr.write(line + '\n');
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
process.stdout.write(line + '\n');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.logger = {
|
|
28
|
+
debug: (msg, meta) => emit('debug', msg, meta),
|
|
29
|
+
info: (msg, meta) => emit('info', msg, meta),
|
|
30
|
+
warn: (msg, meta) => emit('warn', msg, meta),
|
|
31
|
+
error: (msg, meta) => emit('error', msg, meta),
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;;AAEA,MAAM,MAAM,GAA6B,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;AAErF,SAAS,gBAAgB;IACvB,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,MAAM,CAAC,CAAC,WAAW,EAAc,CAAA;IAC1F,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAA;AACnC,CAAC;AAED,SAAS,IAAI,CAAC,KAAe,EAAE,GAAW,EAAE,IAA8B;IACxE,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,gBAAgB,EAAE;QAAE,OAAM;IAC9C,MAAM,MAAM,GAA4B;QACtC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,KAAK;QACL,GAAG;KACJ,CAAA;IACD,IAAI,IAAI;QAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACnC,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;IACnC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;IACnC,CAAC;AACH,CAAC;AAEY,QAAA,MAAM,GAAG;IACpB,KAAK,EAAE,CAAC,GAAW,EAAE,IAA8B,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC;IAChF,IAAI,EAAE,CAAC,GAAW,EAAE,IAA8B,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC;IAC9E,IAAI,EAAE,CAAC,GAAW,EAAE,IAA8B,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC;IAC9E,KAAK,EAAE,CAAC,GAAW,EAAE,IAA8B,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC;CACjF,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface OffsetStoreOptions {
|
|
2
|
+
filepath?: string;
|
|
3
|
+
debounceMs?: number;
|
|
4
|
+
}
|
|
5
|
+
export declare class OffsetStore {
|
|
6
|
+
private offsets;
|
|
7
|
+
private readonly filepath;
|
|
8
|
+
private readonly debounceMs;
|
|
9
|
+
private saveTimer;
|
|
10
|
+
constructor(opts?: OffsetStoreOptions);
|
|
11
|
+
load(): Promise<void>;
|
|
12
|
+
get(filepath: string): number;
|
|
13
|
+
set(filepath: string, offset: number): void;
|
|
14
|
+
advance(filepath: string, delta: number): number;
|
|
15
|
+
/** scheduled save 待ち合わせ用 (主にテスト + graceful shutdown) */
|
|
16
|
+
flush(): Promise<void>;
|
|
17
|
+
/** 内部状態のスナップショット (テスト用) */
|
|
18
|
+
snapshot(): Record<string, number>;
|
|
19
|
+
private scheduleSave;
|
|
20
|
+
private saveNow;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=offset-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"offset-store.d.ts","sourceRoot":"","sources":["../src/offset-store.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,SAAS,CAA8B;gBAEnC,IAAI,GAAE,kBAAuB;IAKnC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAe3B,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAI7B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAK3C,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAMhD,wDAAwD;IAClD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,2BAA2B;IAC3B,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAIlC,OAAO,CAAC,YAAY;YAQN,OAAO;CAOtB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
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.OffsetStore = void 0;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const DEFAULT_OFFSET_FILE = path_1.default.join(os_1.default.homedir(), '.promptkaizen', 'offsets.json');
|
|
11
|
+
class OffsetStore {
|
|
12
|
+
offsets = new Map();
|
|
13
|
+
filepath;
|
|
14
|
+
debounceMs;
|
|
15
|
+
saveTimer = null;
|
|
16
|
+
constructor(opts = {}) {
|
|
17
|
+
this.filepath = opts.filepath ?? DEFAULT_OFFSET_FILE;
|
|
18
|
+
this.debounceMs = opts.debounceMs ?? 1000;
|
|
19
|
+
}
|
|
20
|
+
async load() {
|
|
21
|
+
try {
|
|
22
|
+
const raw = await promises_1.default.readFile(this.filepath, 'utf8');
|
|
23
|
+
const obj = JSON.parse(raw);
|
|
24
|
+
this.offsets = new Map(Object.entries(obj));
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
const code = e.code;
|
|
28
|
+
if (code === 'ENOENT') {
|
|
29
|
+
this.offsets = new Map();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
throw e;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
get(filepath) {
|
|
36
|
+
return this.offsets.get(filepath) ?? 0;
|
|
37
|
+
}
|
|
38
|
+
set(filepath, offset) {
|
|
39
|
+
this.offsets.set(filepath, offset);
|
|
40
|
+
this.scheduleSave();
|
|
41
|
+
}
|
|
42
|
+
advance(filepath, delta) {
|
|
43
|
+
const next = this.get(filepath) + delta;
|
|
44
|
+
this.set(filepath, next);
|
|
45
|
+
return next;
|
|
46
|
+
}
|
|
47
|
+
/** scheduled save 待ち合わせ用 (主にテスト + graceful shutdown) */
|
|
48
|
+
async flush() {
|
|
49
|
+
if (this.saveTimer) {
|
|
50
|
+
clearTimeout(this.saveTimer);
|
|
51
|
+
this.saveTimer = null;
|
|
52
|
+
}
|
|
53
|
+
await this.saveNow();
|
|
54
|
+
}
|
|
55
|
+
/** 内部状態のスナップショット (テスト用) */
|
|
56
|
+
snapshot() {
|
|
57
|
+
return Object.fromEntries(this.offsets);
|
|
58
|
+
}
|
|
59
|
+
scheduleSave() {
|
|
60
|
+
if (this.saveTimer)
|
|
61
|
+
return;
|
|
62
|
+
this.saveTimer = setTimeout(() => {
|
|
63
|
+
this.saveTimer = null;
|
|
64
|
+
void this.saveNow();
|
|
65
|
+
}, this.debounceMs);
|
|
66
|
+
}
|
|
67
|
+
async saveNow() {
|
|
68
|
+
const obj = Object.fromEntries(this.offsets);
|
|
69
|
+
const tmp = `${this.filepath}.tmp`;
|
|
70
|
+
await promises_1.default.mkdir(path_1.default.dirname(this.filepath), { recursive: true });
|
|
71
|
+
await promises_1.default.writeFile(tmp, JSON.stringify(obj, null, 2));
|
|
72
|
+
await promises_1.default.rename(tmp, this.filepath);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.OffsetStore = OffsetStore;
|
|
76
|
+
//# sourceMappingURL=offset-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"offset-store.js","sourceRoot":"","sources":["../src/offset-store.ts"],"names":[],"mappings":"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"}
|
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OffsetStore } from './offset-store';
|
|
2
|
+
import type { ParsedEntry } from './types';
|
|
3
|
+
export interface ParseResult {
|
|
4
|
+
entries: ParsedEntry[];
|
|
5
|
+
/** offset を進めるべき行数 (成功 + 中間の skip 失敗) */
|
|
6
|
+
consumed: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class JsonlParser {
|
|
9
|
+
private offsetStore;
|
|
10
|
+
constructor(offsetStore: OffsetStore);
|
|
11
|
+
parseDelta(filepath: string): Promise<ParseResult>;
|
|
12
|
+
/**
|
|
13
|
+
* filepath を 1 行ずつ streaming で読み、0-based 行番号が startOffset 以上の行だけを返す。
|
|
14
|
+
* readline は末尾改行のみの空行を emit しない (= 旧実装の trailing pop と等価) し、
|
|
15
|
+
* 改行で終わっていない書き込み途中の最終行はそのまま emit するため、呼び出し側の
|
|
16
|
+
* 「末尾の parse 失敗は incomplete とみなして break」ロジックがそのまま機能する。
|
|
17
|
+
*/
|
|
18
|
+
private readNewLines;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAOD,qBAAa,WAAW;IACV,OAAO,CAAC,WAAW;gBAAX,WAAW,EAAE,WAAW;IAEtC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA2ExD;;;;;OAKG;IACH,OAAO,CAAC,YAAY;CAiBrB"}
|
package/dist/parser.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
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.JsonlParser = void 0;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
|
+
const readline_1 = __importDefault(require("readline"));
|
|
10
|
+
const logger_1 = require("./logger");
|
|
11
|
+
const source_1 = require("./source");
|
|
12
|
+
// Codex の rollout JSONL は compaction 履歴の重複で数百MB〜数GB に肥大化する実例がある。
|
|
13
|
+
// 全文を 1 つの文字列として読むとメモリが破綻するため、(1) 1 行ずつの streaming 読み、
|
|
14
|
+
// (2) この上限を超えるファイルは安全のためスキップ、の二段で守る。
|
|
15
|
+
const MAX_FILE_BYTES = 512 * 1024 * 1024; // 512MB
|
|
16
|
+
class JsonlParser {
|
|
17
|
+
offsetStore;
|
|
18
|
+
constructor(offsetStore) {
|
|
19
|
+
this.offsetStore = offsetStore;
|
|
20
|
+
}
|
|
21
|
+
async parseDelta(filepath) {
|
|
22
|
+
const source = (0, source_1.detectSource)(filepath);
|
|
23
|
+
let size;
|
|
24
|
+
try {
|
|
25
|
+
size = (await promises_1.default.stat(filepath)).size;
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
logger_1.logger.warn('parseDelta: failed to stat file', {
|
|
29
|
+
filepath,
|
|
30
|
+
error: e.message,
|
|
31
|
+
});
|
|
32
|
+
return { entries: [], consumed: 0 };
|
|
33
|
+
}
|
|
34
|
+
if (size > MAX_FILE_BYTES) {
|
|
35
|
+
// サイズガード: 肥大化した rollout はスキップ (offset は進めない)。
|
|
36
|
+
logger_1.logger.warn('parseDelta: file exceeds size guard, skipping', {
|
|
37
|
+
filepath,
|
|
38
|
+
sizeMb: Math.round(size / (1024 * 1024)),
|
|
39
|
+
limitMb: MAX_FILE_BYTES / (1024 * 1024),
|
|
40
|
+
});
|
|
41
|
+
return { entries: [], consumed: 0 };
|
|
42
|
+
}
|
|
43
|
+
const startOffset = this.offsetStore.get(filepath);
|
|
44
|
+
// streaming で startOffset 以降の行のみ収集する。全文文字列は保持しない。
|
|
45
|
+
let newLines;
|
|
46
|
+
try {
|
|
47
|
+
newLines = await this.readNewLines(filepath, startOffset);
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
logger_1.logger.warn('parseDelta: failed to read file', {
|
|
51
|
+
filepath,
|
|
52
|
+
error: e.message,
|
|
53
|
+
});
|
|
54
|
+
return { entries: [], consumed: 0 };
|
|
55
|
+
}
|
|
56
|
+
const entries = [];
|
|
57
|
+
const parsedAt = new Date().toISOString();
|
|
58
|
+
let consumed = 0;
|
|
59
|
+
for (let i = 0; i < newLines.length; i++) {
|
|
60
|
+
const line = newLines[i];
|
|
61
|
+
if (line.trim().length === 0) {
|
|
62
|
+
consumed = i + 1;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const raw = JSON.parse(line);
|
|
67
|
+
entries.push({
|
|
68
|
+
filepath,
|
|
69
|
+
lineNumber: startOffset + i,
|
|
70
|
+
raw,
|
|
71
|
+
parsedAt,
|
|
72
|
+
source,
|
|
73
|
+
});
|
|
74
|
+
consumed = i + 1;
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
if (i === newLines.length - 1) {
|
|
78
|
+
// 末尾の不完全行: 書き込み途中とみなして次回 change を待つ
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
// 中間の失敗: ファイル破損の可能性。warn して飛ばす
|
|
82
|
+
logger_1.logger.warn('parseDelta: skip unparseable line', {
|
|
83
|
+
filepath,
|
|
84
|
+
lineNumber: startOffset + i,
|
|
85
|
+
snippet: line.slice(0, 120),
|
|
86
|
+
});
|
|
87
|
+
consumed = i + 1;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { entries, consumed };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* filepath を 1 行ずつ streaming で読み、0-based 行番号が startOffset 以上の行だけを返す。
|
|
94
|
+
* readline は末尾改行のみの空行を emit しない (= 旧実装の trailing pop と等価) し、
|
|
95
|
+
* 改行で終わっていない書き込み途中の最終行はそのまま emit するため、呼び出し側の
|
|
96
|
+
* 「末尾の parse 失敗は incomplete とみなして break」ロジックがそのまま機能する。
|
|
97
|
+
*/
|
|
98
|
+
readNewLines(filepath, startOffset) {
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
const out = [];
|
|
101
|
+
let index = -1;
|
|
102
|
+
const stream = (0, fs_1.createReadStream)(filepath, { encoding: 'utf8' });
|
|
103
|
+
const rl = readline_1.default.createInterface({ input: stream, crlfDelay: Infinity });
|
|
104
|
+
rl.on('line', (line) => {
|
|
105
|
+
index++;
|
|
106
|
+
if (index >= startOffset)
|
|
107
|
+
out.push(line);
|
|
108
|
+
});
|
|
109
|
+
rl.on('close', () => resolve(out));
|
|
110
|
+
stream.on('error', (e) => {
|
|
111
|
+
rl.close();
|
|
112
|
+
reject(e);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.JsonlParser = JsonlParser;
|
|
118
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":";;;;;;AAAA,2BAAqC;AACrC,2DAA4B;AAC5B,wDAA+B;AAC/B,qCAAiC;AAEjC,qCAAuC;AASvC,iEAAiE;AACjE,uDAAuD;AACvD,qCAAqC;AACrC,MAAM,cAAc,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAA,CAAC,QAAQ;AAEjD,MAAa,WAAW;IACF;IAApB,YAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAEhD,KAAK,CAAC,UAAU,CAAC,QAAgB;QAC/B,MAAM,MAAM,GAAG,IAAA,qBAAY,EAAC,QAAQ,CAAC,CAAA;QAErC,IAAI,IAAY,CAAA;QAChB,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,MAAM,kBAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA;QACvC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,eAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE;gBAC7C,QAAQ;gBACR,KAAK,EAAG,CAAW,CAAC,OAAO;aAC5B,CAAC,CAAA;YACF,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAA;QACrC,CAAC;QACD,IAAI,IAAI,GAAG,cAAc,EAAE,CAAC;YAC1B,8CAA8C;YAC9C,eAAM,CAAC,IAAI,CAAC,+CAA+C,EAAE;gBAC3D,QAAQ;gBACR,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;gBACxC,OAAO,EAAE,cAAc,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;aACxC,CAAC,CAAA;YACF,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAA;QACrC,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAElD,kDAAkD;QAClD,IAAI,QAAkB,CAAA;QACtB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;QAC3D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,eAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE;gBAC7C,QAAQ;gBACR,KAAK,EAAG,CAAW,CAAC,OAAO;aAC5B,CAAC,CAAA;YACF,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAA;QACrC,CAAC;QAED,MAAM,OAAO,GAAkB,EAAE,CAAA;QACjC,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QACzC,IAAI,QAAQ,GAAG,CAAC,CAAA;QAEhB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;YACxB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAA;gBAChB,SAAQ;YACV,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAA;gBACvC,OAAO,CAAC,IAAI,CAAC;oBACX,QAAQ;oBACR,UAAU,EAAE,WAAW,GAAG,CAAC;oBAC3B,GAAG;oBACH,QAAQ;oBACR,MAAM;iBACP,CAAC,CAAA;gBACF,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAA;YAClB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9B,oCAAoC;oBACpC,MAAK;gBACP,CAAC;gBACD,+BAA+B;gBAC/B,eAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE;oBAC/C,QAAQ;oBACR,UAAU,EAAE,WAAW,GAAG,CAAC;oBAC3B,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;iBAC5B,CAAC,CAAA;gBACF,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAA;IAC9B,CAAC;IAED;;;;;OAKG;IACK,YAAY,CAAC,QAAgB,EAAE,WAAmB;QACxD,OAAO,IAAI,OAAO,CAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC/C,MAAM,GAAG,GAAa,EAAE,CAAA;YACxB,IAAI,KAAK,GAAG,CAAC,CAAC,CAAA;YACd,MAAM,MAAM,GAAG,IAAA,qBAAgB,EAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YAC/D,MAAM,EAAE,GAAG,kBAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;YAC3E,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBACrB,KAAK,EAAE,CAAA;gBACP,IAAI,KAAK,IAAI,WAAW;oBAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC1C,CAAC,CAAC,CAAA;YACF,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;YAClC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gBACvB,EAAE,CAAC,KAAK,EAAE,CAAA;gBACV,MAAM,CAAC,CAAC,CAAC,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AArGD,kCAqGC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AgentConfig } from './config';
|
|
2
|
+
import type { ParsedEntry } from './types';
|
|
3
|
+
export interface PiiMaskerOptions {
|
|
4
|
+
homeDir?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class PiiMasker {
|
|
7
|
+
private readonly config;
|
|
8
|
+
private readonly homeDir;
|
|
9
|
+
private readonly customPatterns;
|
|
10
|
+
constructor(config: AgentConfig['pii'], opts?: PiiMaskerOptions);
|
|
11
|
+
mask(entry: ParsedEntry): ParsedEntry;
|
|
12
|
+
maskAll(entries: ParsedEntry[]): ParsedEntry[];
|
|
13
|
+
/** 任意の値を再帰的に処理。string は pattern 置換、object は structural な特別処理あり */
|
|
14
|
+
private maskValue;
|
|
15
|
+
private maskString;
|
|
16
|
+
private isBase64ImageBlock;
|
|
17
|
+
private summarizeImage;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=pii-masker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pii-masker.d.ts","sourceRoot":"","sources":["../src/pii-masker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AA4C1C,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;gBAE5C,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,IAAI,GAAE,gBAAqB;IAUnE,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW;IAIrC,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE;IAI9C,kEAAkE;IAClE,OAAO,CAAC,SAAS;IAyBjB,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,cAAc;CAevB"}
|
|
@@ -0,0 +1,136 @@
|
|
|
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.PiiMasker = void 0;
|
|
7
|
+
const crypto_1 = require("crypto");
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
/**
|
|
10
|
+
* Built-in PII patterns. Phase B 観測 (`agent/docs/claude-log-structure.md` 第 7 節)
|
|
11
|
+
* で実際に conversation に出現することが確認されたものを優先実装。
|
|
12
|
+
*
|
|
13
|
+
* 注: 検出粒度は false negative より false positive を許容する方針
|
|
14
|
+
* (key 漏洩リスク > 文字列を過剰にマスクするリスク)。
|
|
15
|
+
*/
|
|
16
|
+
const SECRET_PATTERNS = [
|
|
17
|
+
// Anthropic API key (sk-ant-api... / sk-ant-oat... / sk-ant-ort...)
|
|
18
|
+
[/sk-ant-(api|oat|ort)\d+-[A-Za-z0-9_-]{40,}/g, '[MASKED_ANTHROPIC_KEY]'],
|
|
19
|
+
// OpenAI key (sk-proj-... or legacy sk-...) — 40+ 文字に絞って誤検出抑制
|
|
20
|
+
[/sk-(proj-)?[A-Za-z0-9]{40,}/g, '[MASKED_OPENAI_KEY]'],
|
|
21
|
+
// GitHub token (ghp_, gho_, ghu_, ghs_, ghr_)
|
|
22
|
+
[/gh[pousr]_[A-Za-z0-9]{36}/g, '[MASKED_GITHUB_TOKEN]'],
|
|
23
|
+
// Slack token (xoxb-, xoxp-, xoxa-, xoxr-, xoxs-)
|
|
24
|
+
[/xox[baprs]-[A-Za-z0-9-]{10,}/g, '[MASKED_SLACK_TOKEN]'],
|
|
25
|
+
// AWS access key
|
|
26
|
+
[/\bAKIA[0-9A-Z]{16}\b/g, '[MASKED_AWS_KEY]'],
|
|
27
|
+
// GCP API key
|
|
28
|
+
[/\bAIza[0-9A-Za-z_-]{35}\b/g, '[MASKED_GCP_KEY]'],
|
|
29
|
+
// Generic Bearer token (短すぎる文字列は誤検出するので 20+ 文字に絞る)
|
|
30
|
+
[/Bearer\s+[A-Za-z0-9._-]{20,}/g, 'Bearer [MASKED_TOKEN]'],
|
|
31
|
+
];
|
|
32
|
+
// local-part を 2 文字以上にして Flask デコレータ等 (例: `t@app.context_processor`,
|
|
33
|
+
// `n@app.after_request`) の false positive をブロック。1 文字 local-part の実 email は
|
|
34
|
+
// RFC 上 valid だが実運用ではほぼ存在しない (acceptable trade-off)。
|
|
35
|
+
const EMAIL_PATTERN = /[a-zA-Z0-9._%+-]{2,}@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
|
|
36
|
+
/** ファイルパス内のユーザー名を匿名化 */
|
|
37
|
+
function maskFilePathsInString(str, homeDir) {
|
|
38
|
+
let result = str;
|
|
39
|
+
// 自分のホーム → ~
|
|
40
|
+
if (homeDir) {
|
|
41
|
+
result = result.split(homeDir).join('~');
|
|
42
|
+
}
|
|
43
|
+
// 他ユーザー (チーム共有時に他のユーザー名が漏れないように)
|
|
44
|
+
result = result.replace(/\/Users\/[^/\s"'`]+/g, '/Users/[USER]');
|
|
45
|
+
result = result.replace(/\/home\/[^/\s"'`]+/g, '/home/[USER]');
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
class PiiMasker {
|
|
49
|
+
config;
|
|
50
|
+
homeDir;
|
|
51
|
+
customPatterns;
|
|
52
|
+
constructor(config, opts = {}) {
|
|
53
|
+
this.config = config;
|
|
54
|
+
this.homeDir = opts.homeDir ?? os_1.default.homedir();
|
|
55
|
+
this.customPatterns = (config.customPatterns ?? []).map(({ pattern, replacement }) => {
|
|
56
|
+
// ユーザー指定 regex は flag を付けて global にする
|
|
57
|
+
const flags = pattern.startsWith('/') ? '' : 'g';
|
|
58
|
+
return [new RegExp(pattern, flags), replacement];
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
mask(entry) {
|
|
62
|
+
return { ...entry, raw: this.maskValue(entry.raw) };
|
|
63
|
+
}
|
|
64
|
+
maskAll(entries) {
|
|
65
|
+
return entries.map((e) => this.mask(e));
|
|
66
|
+
}
|
|
67
|
+
/** 任意の値を再帰的に処理。string は pattern 置換、object は structural な特別処理あり */
|
|
68
|
+
maskValue(v) {
|
|
69
|
+
if (typeof v === 'string') {
|
|
70
|
+
return this.maskString(v);
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(v)) {
|
|
73
|
+
return v.map((x) => this.maskValue(x));
|
|
74
|
+
}
|
|
75
|
+
if (v !== null && typeof v === 'object') {
|
|
76
|
+
const obj = v;
|
|
77
|
+
// 画像 base64 は構造的に検出して省略 (帯域節約 + 二次的 PII 流出防止)
|
|
78
|
+
if (this.isBase64ImageBlock(obj)) {
|
|
79
|
+
return this.summarizeImage(obj);
|
|
80
|
+
}
|
|
81
|
+
const result = {};
|
|
82
|
+
for (const [k, val] of Object.entries(obj)) {
|
|
83
|
+
// key 自体に絶対パス等が入るケース (例: file-history-snapshot の
|
|
84
|
+
// trackedFileBackups は file path を key にする) があるので key も maskString
|
|
85
|
+
const newKey = this.maskString(k);
|
|
86
|
+
result[newKey] = this.maskValue(val);
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
return v;
|
|
91
|
+
}
|
|
92
|
+
maskString(str) {
|
|
93
|
+
let result = str;
|
|
94
|
+
if (this.config.maskApiKeys) {
|
|
95
|
+
for (const [re, repl] of SECRET_PATTERNS) {
|
|
96
|
+
result = result.replace(re, repl);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (this.config.maskFilePaths) {
|
|
100
|
+
result = maskFilePathsInString(result, this.homeDir);
|
|
101
|
+
}
|
|
102
|
+
if (this.config.maskEmails) {
|
|
103
|
+
result = result.replace(EMAIL_PATTERN, '[MASKED_EMAIL]');
|
|
104
|
+
}
|
|
105
|
+
for (const [re, repl] of this.customPatterns) {
|
|
106
|
+
result = result.replace(re, repl);
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
isBase64ImageBlock(obj) {
|
|
111
|
+
if (obj.type !== 'image')
|
|
112
|
+
return false;
|
|
113
|
+
const src = obj.source;
|
|
114
|
+
if (!src || typeof src !== 'object')
|
|
115
|
+
return false;
|
|
116
|
+
const s = src;
|
|
117
|
+
return s.type === 'base64' && typeof s.data === 'string';
|
|
118
|
+
}
|
|
119
|
+
summarizeImage(obj) {
|
|
120
|
+
const src = obj.source;
|
|
121
|
+
const data = src.data;
|
|
122
|
+
// base64 length × 3/4 ≈ decoded byte length (padding 無視)
|
|
123
|
+
const sizeBytes = Math.floor((data.length * 3) / 4);
|
|
124
|
+
const hash = (0, crypto_1.createHash)('sha256').update(data).digest('hex').slice(0, 12);
|
|
125
|
+
return {
|
|
126
|
+
...obj,
|
|
127
|
+
source: {
|
|
128
|
+
type: 'base64',
|
|
129
|
+
media_type: src.media_type,
|
|
130
|
+
data: `[MASKED_IMAGE size=${sizeBytes}B sha256=${hash}]`,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
exports.PiiMasker = PiiMasker;
|
|
136
|
+
//# sourceMappingURL=pii-masker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pii-masker.js","sourceRoot":"","sources":["../src/pii-masker.ts"],"names":[],"mappings":"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"}
|
package/dist/sender.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ParsedEntry, BatchAck } from './types';
|
|
2
|
+
export interface SenderOptions {
|
|
3
|
+
apiEndpoint: string;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
agentVersion: string;
|
|
6
|
+
/** リトライ回数 (5xx / network error のみ。4xx は即 fail) */
|
|
7
|
+
maxRetries?: number;
|
|
8
|
+
/** 初期バックオフ ms (実際は 2^attempt 倍) */
|
|
9
|
+
initialBackoffMs?: number;
|
|
10
|
+
/** fetch 実装 (テスト差し替え用) */
|
|
11
|
+
fetchImpl?: typeof fetch;
|
|
12
|
+
}
|
|
13
|
+
export declare class Sender {
|
|
14
|
+
private opts;
|
|
15
|
+
private readonly maxRetries;
|
|
16
|
+
private readonly initialBackoffMs;
|
|
17
|
+
private readonly fetchImpl;
|
|
18
|
+
constructor(opts: SenderOptions);
|
|
19
|
+
send(observations: ParsedEntry[]): Promise<BatchAck>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=sender.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sender.d.ts","sourceRoot":"","sources":["../src/sender.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEtE,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB;AAED,qBAAa,MAAM;IAKL,OAAO,CAAC,IAAI;IAJxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;gBAEpB,IAAI,EAAE,aAAa;IAMjC,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;CAiD3D"}
|