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/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# @promptkaizen/agent
|
|
2
|
+
|
|
3
|
+
PromptKaizen のローカル常駐エージェント。`~/.claude/projects/*.jsonl` を監視し、
|
|
4
|
+
差分パース・PII マスキング・バッチング後に PromptKaizen Cloud へ送信する。
|
|
5
|
+
|
|
6
|
+
## なぜローカルエージェントなのか
|
|
7
|
+
|
|
8
|
+
Phase 0 初期実装で proxy 方式(リバースプロキシ経由で Anthropic API を中継)を試したが、
|
|
9
|
+
ユーザーが Anthropic Max プラン契約済みの場合、proxy 経由で使うと API 従量課金が
|
|
10
|
+
**追加**で発生する二重課金問題があり、個人開発者層には経済合理性がない。
|
|
11
|
+
|
|
12
|
+
ローカルエージェント方式 (Bプラン) なら:
|
|
13
|
+
|
|
14
|
+
- Claude Code は Max プラン直結のまま使い続けられる (追加課金ゼロ)
|
|
15
|
+
- 観測データだけクラウドに送信
|
|
16
|
+
- Anthropic 利用規約的にもクリーン(OAuth トークン中継なし)
|
|
17
|
+
- 観測遅延は 30秒〜数分(事後分析用途には十分)
|
|
18
|
+
|
|
19
|
+
詳細は `../proxy/README.md` の凍結ノートと `docs/architecture.md`(追って整備)を参照。
|
|
20
|
+
|
|
21
|
+
## ステータス
|
|
22
|
+
|
|
23
|
+
✅ **Phase A〜G 完了**。SAKAMA 内本格運用 (Phase H) 開始可能。
|
|
24
|
+
|
|
25
|
+
実装フェーズ:
|
|
26
|
+
|
|
27
|
+
- [x] Phase A: proxy 凍結 + agent/ サブディレクトリ初期化
|
|
28
|
+
- [x] Phase B: Claude Code ログ構造調査
|
|
29
|
+
- [x] Phase C: PoC エージェント実装 (watcher / parser / offset-store)
|
|
30
|
+
- [x] Phase D: PII マスキング実装
|
|
31
|
+
- [x] Phase E: クラウド側受信 API (Cloud Functions + Firestore)
|
|
32
|
+
- [x] Phase F: ダッシュボード MVP (/settings 設定 + /events 観測一覧 + 詳細 + 集計グラフ)
|
|
33
|
+
- [x] Phase G: 配布パッケージング (CLI + macOS launchd + シェルスクリプト一発インストーラ)
|
|
34
|
+
- [ ] Phase H: SAKAMA 内本格運用検証 (6 週間)
|
|
35
|
+
|
|
36
|
+
## インストール (Mac, ワンショット)
|
|
37
|
+
|
|
38
|
+
前提: Node.js 20+。`nvm install 20 && nvm use 20`。
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
git clone https://github.com/SAKAMA-INC/promptkaizen-mvp.git
|
|
42
|
+
cd promptkaizen-mvp
|
|
43
|
+
./scripts/install-agent.sh
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
apiKey は dashboard `/settings` のセットアップガイドから 1 度発行してコピー。
|
|
47
|
+
スクリプトの中で promptkaizen-agent init が起動し apiKey をペーストすると
|
|
48
|
+
`~/.promptkaizen/agent.config.json` が生成され、macOS launchd に登録されて
|
|
49
|
+
自動起動 + 落ちても自動再起動するようになります。
|
|
50
|
+
|
|
51
|
+
完全非対話モード (CI / dotfiles 用):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
PK_API_KEY=pk_xxxxx PK_ENV=stg ./scripts/install-agent.sh
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
環境変数:
|
|
58
|
+
|
|
59
|
+
| 変数 | デフォルト | 用途 |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `PK_API_KEY` | (空) | 設定すると init を非対話で実行 |
|
|
62
|
+
| `PK_ENV` | `stg` | `stg` / `prod` / `custom` |
|
|
63
|
+
| `PK_NO_LAUNCHD` | `0` | `1` で launchd 登録をスキップ (foreground 運用) |
|
|
64
|
+
|
|
65
|
+
## CLI コマンド
|
|
66
|
+
|
|
67
|
+
`npm link` 後、グローバルに `promptkaizen-agent` コマンドが入ります。
|
|
68
|
+
|
|
69
|
+
| サブコマンド | 用途 |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `init` | 対話 or `--api-key K --env stg --yes` で config.json 生成 |
|
|
72
|
+
| `start` | foreground 起動 (launchd が裏で叩いているのと同じ) |
|
|
73
|
+
| `status` | config / plist / プロセス / offsets / endpoint の診断 |
|
|
74
|
+
| `install-launchd` | macOS launchd に登録 (自動起動 + 落ちたら再起動) |
|
|
75
|
+
| `uninstall-launchd` | launchd 登録を解除 (config/offsets は残す) |
|
|
76
|
+
| `version` | バージョン表示 |
|
|
77
|
+
| `help` | ヘルプ |
|
|
78
|
+
|
|
79
|
+
## アンインストール
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
promptkaizen-agent uninstall-launchd # 自動起動を止める
|
|
83
|
+
rm -rf ~/.promptkaizen # config + offsets + logs を削除
|
|
84
|
+
cd promptkaizen-mvp/agent && npm unlink # グローバル CLI を削除 (任意)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## トラブルシューティング
|
|
88
|
+
|
|
89
|
+
| 症状 | 対処 |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `promptkaizen-agent: command not found` | install 時の Node version と現 shell の Node version が違う (nvm) ことが多い。 一時対応: `source ~/.nvm/nvm.sh && nvm use 20 && promptkaizen-agent status`。 恒久対応: `~/.zshrc` 末尾に `alias promptkaizen-agent='source ~/.nvm/nvm.sh && nvm use 20 >/dev/null && command promptkaizen-agent'` を追記。 launchd 経由の agent 本体は plist で Node 20 絶対パス指定のため、 CLI が PATH になくても agent 自体は動く |
|
|
92
|
+
| status で `endpoint unreachable` | dashboard /settings で発行した apiKey が正しいか / ネットワークを確認 |
|
|
93
|
+
| status で `process not running` | `tail -100 ~/.promptkaizen/agent.error.log` でエラーを確認 |
|
|
94
|
+
| `agent.error.log` に `POST failed 401: Invalid apiKey` | **apiKey と endpoint の環境がズレている**。dashboard が STG なら PROD apiKey は使えない (逆も同様)。`promptkaizen-agent init --api-key '<key>' --env stg\|prod --yes` で再 init → `launchctl kickstart -k gui/$(id -u)/ai.promptkaizen.agent` で再起動 |
|
|
95
|
+
| 過去の Claude Code セッションが `/events` に出ない | 起動以前の entries は default で送らない (`agent.skipInitialBacklog: true`)。過去も送りたい場合は `~/.promptkaizen/agent.config.json` の `agent.skipInitialBacklog` を `false` にして `launchctl kickstart` で再起動 |
|
|
96
|
+
| `Firebase CLI v15.x is incompatible with Node.js v18` | `nvm use 20` に切り替え (install-agent.sh は自動で試みる) |
|
|
97
|
+
| Mac 再起動後に動かない | `launchctl list \| grep promptkaizen` で plist が active か確認 |
|
|
98
|
+
|
|
99
|
+
## 想定アーキテクチャ
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
~/.claude/projects/*.jsonl
|
|
103
|
+
↓ (chokidar による fs watch)
|
|
104
|
+
PromptKaizen Agent (Node.js 常駐, ~10MB)
|
|
105
|
+
↓ (差分パース、オフセット管理)
|
|
106
|
+
↓ (PII マスキング)
|
|
107
|
+
↓ (バッチング: 5秒 or 50エントリ)
|
|
108
|
+
PromptKaizen Cloud API (HTTPS POST)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## ディレクトリ構造
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
agent/
|
|
115
|
+
├── package.json
|
|
116
|
+
├── tsconfig.json
|
|
117
|
+
├── src/ # 実装本体 (Phase C で追加)
|
|
118
|
+
├── tests/ # vitest テスト
|
|
119
|
+
├── docs/ # 設計ドキュメント
|
|
120
|
+
└── scripts/ # 調査・運用スクリプト
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 開発
|
|
124
|
+
|
|
125
|
+
ルートで `npm install` 後:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npm run build --workspace=agent
|
|
129
|
+
npm run dev --workspace=agent # tsx watch
|
|
130
|
+
npm run test --workspace=agent # vitest
|
|
131
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Sender } from './sender';
|
|
2
|
+
import type { ParsedEntry } from './types';
|
|
3
|
+
export interface BatcherOptions {
|
|
4
|
+
intervalMs: number;
|
|
5
|
+
maxEntries: number;
|
|
6
|
+
}
|
|
7
|
+
/** flush 成功時に呼ばれる callback (offset 更新用) */
|
|
8
|
+
export type OnFlushed = (flushedCount: number, filepath: string) => Promise<void> | void;
|
|
9
|
+
export declare class Batcher {
|
|
10
|
+
private opts;
|
|
11
|
+
private sender;
|
|
12
|
+
private onFlushed;
|
|
13
|
+
private queues;
|
|
14
|
+
private timer;
|
|
15
|
+
private flushing;
|
|
16
|
+
private pendingFlush;
|
|
17
|
+
constructor(opts: BatcherOptions, sender: Sender, onFlushed: OnFlushed);
|
|
18
|
+
add(filepath: string, entries: ParsedEntry[], consumed: number): void;
|
|
19
|
+
/** 即時 flush (graceful shutdown / maxEntries 超過時) */
|
|
20
|
+
flush(): Promise<void>;
|
|
21
|
+
private doFlush;
|
|
22
|
+
private totalEntries;
|
|
23
|
+
private scheduleIfNeeded;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=batcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batcher.d.ts","sourceRoot":"","sources":["../src/batcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,2CAA2C;AAC3C,MAAM,MAAM,SAAS,GAAG,CACtB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;AAQzB,qBAAa,OAAO;IAOhB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IARnB,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,YAAY,CAA6B;gBAGvC,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS;IAG9B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAerE,oDAAoD;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAYd,OAAO;IAiDrB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,gBAAgB;CAOzB"}
|
package/dist/batcher.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Batcher = void 0;
|
|
4
|
+
const logger_1 = require("./logger");
|
|
5
|
+
class Batcher {
|
|
6
|
+
opts;
|
|
7
|
+
sender;
|
|
8
|
+
onFlushed;
|
|
9
|
+
queues = new Map();
|
|
10
|
+
timer = null;
|
|
11
|
+
flushing = false;
|
|
12
|
+
pendingFlush = null;
|
|
13
|
+
constructor(opts, sender, onFlushed) {
|
|
14
|
+
this.opts = opts;
|
|
15
|
+
this.sender = sender;
|
|
16
|
+
this.onFlushed = onFlushed;
|
|
17
|
+
}
|
|
18
|
+
add(filepath, entries, consumed) {
|
|
19
|
+
if (entries.length === 0 && consumed === 0)
|
|
20
|
+
return;
|
|
21
|
+
const existing = this.queues.get(filepath);
|
|
22
|
+
if (existing) {
|
|
23
|
+
existing.entries.push(...entries);
|
|
24
|
+
existing.consumed += consumed;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
this.queues.set(filepath, { filepath, entries: [...entries], consumed });
|
|
28
|
+
}
|
|
29
|
+
this.scheduleIfNeeded();
|
|
30
|
+
if (this.totalEntries() >= this.opts.maxEntries) {
|
|
31
|
+
void this.flush();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** 即時 flush (graceful shutdown / maxEntries 超過時) */
|
|
35
|
+
async flush() {
|
|
36
|
+
if (this.pendingFlush) {
|
|
37
|
+
return this.pendingFlush;
|
|
38
|
+
}
|
|
39
|
+
this.pendingFlush = this.doFlush();
|
|
40
|
+
try {
|
|
41
|
+
await this.pendingFlush;
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
this.pendingFlush = null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async doFlush() {
|
|
48
|
+
if (this.flushing)
|
|
49
|
+
return;
|
|
50
|
+
this.flushing = true;
|
|
51
|
+
try {
|
|
52
|
+
if (this.timer) {
|
|
53
|
+
clearTimeout(this.timer);
|
|
54
|
+
this.timer = null;
|
|
55
|
+
}
|
|
56
|
+
const snapshot = Array.from(this.queues.values());
|
|
57
|
+
this.queues.clear();
|
|
58
|
+
if (snapshot.length === 0)
|
|
59
|
+
return;
|
|
60
|
+
const allEntries = snapshot.flatMap((q) => q.entries);
|
|
61
|
+
if (allEntries.length === 0) {
|
|
62
|
+
// entry はないが consumed (skip 行) はあるかも → offset 進める
|
|
63
|
+
for (const q of snapshot) {
|
|
64
|
+
if (q.consumed > 0)
|
|
65
|
+
await this.onFlushed(q.consumed, q.filepath);
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
// Cloud 側 (receiveObservations) は Firestore batch limit に合わせて
|
|
71
|
+
// 1 リクエスト 500 entries 上限。同 limit に合わせて分割送信。
|
|
72
|
+
const CHUNK = 500;
|
|
73
|
+
let totalReceived = 0;
|
|
74
|
+
for (let i = 0; i < allEntries.length; i += CHUNK) {
|
|
75
|
+
const slice = allEntries.slice(i, i + CHUNK);
|
|
76
|
+
const ack = await this.sender.send(slice);
|
|
77
|
+
totalReceived += ack.received;
|
|
78
|
+
}
|
|
79
|
+
logger_1.logger.info('Batcher flush ok', {
|
|
80
|
+
sent: allEntries.length,
|
|
81
|
+
received: totalReceived,
|
|
82
|
+
chunks: Math.ceil(allEntries.length / CHUNK),
|
|
83
|
+
});
|
|
84
|
+
for (const q of snapshot) {
|
|
85
|
+
if (q.consumed > 0)
|
|
86
|
+
await this.onFlushed(q.consumed, q.filepath);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
// 送信失敗 → エントリは破棄 (Phase 1 で persistent queue 対応)
|
|
91
|
+
logger_1.logger.error('Batcher flush failed (entries dropped)', {
|
|
92
|
+
dropped: allEntries.length,
|
|
93
|
+
error: e.message,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
this.flushing = false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
totalEntries() {
|
|
102
|
+
let total = 0;
|
|
103
|
+
for (const q of this.queues.values())
|
|
104
|
+
total += q.entries.length;
|
|
105
|
+
return total;
|
|
106
|
+
}
|
|
107
|
+
scheduleIfNeeded() {
|
|
108
|
+
if (this.timer)
|
|
109
|
+
return;
|
|
110
|
+
this.timer = setTimeout(() => {
|
|
111
|
+
this.timer = null;
|
|
112
|
+
void this.flush();
|
|
113
|
+
}, this.opts.intervalMs);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.Batcher = Batcher;
|
|
117
|
+
//# sourceMappingURL=batcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batcher.js","sourceRoot":"","sources":["../src/batcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `promptkaizen-agent init [--api-key KEY] [--env stg|prod] [--mask-emails] [--yes]`
|
|
3
|
+
*
|
|
4
|
+
* インタラクティブ または 非対話 (フラグ + env var) で ~/.promptkaizen/agent.config.json を生成。
|
|
5
|
+
* install-agent.sh から PK_API_KEY 環境変数経由で呼ばれるケースも想定。
|
|
6
|
+
*
|
|
7
|
+
* 対話: promptkaizen-agent init
|
|
8
|
+
* 非対話: PK_API_KEY=pk_xxx promptkaizen-agent init --env stg --yes
|
|
9
|
+
* 非対話: promptkaizen-agent init --api-key pk_xxx --env prod --yes
|
|
10
|
+
*/
|
|
11
|
+
export declare function runInit(argv: string[]): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkG3D"}
|
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
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.runInit = runInit;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const readline_1 = __importDefault(require("readline"));
|
|
11
|
+
const CONFIG_PATH = path_1.default.join(os_1.default.homedir(), '.promptkaizen', 'agent.config.json');
|
|
12
|
+
const ENDPOINTS = {
|
|
13
|
+
stg: 'https://asia-northeast1-promptkaizen-stg.cloudfunctions.net/receiveObservations',
|
|
14
|
+
prod: 'https://asia-northeast1-promptkaizen-prod.cloudfunctions.net/receiveObservations',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* `promptkaizen-agent init [--api-key KEY] [--env stg|prod] [--mask-emails] [--yes]`
|
|
18
|
+
*
|
|
19
|
+
* インタラクティブ または 非対話 (フラグ + env var) で ~/.promptkaizen/agent.config.json を生成。
|
|
20
|
+
* install-agent.sh から PK_API_KEY 環境変数経由で呼ばれるケースも想定。
|
|
21
|
+
*
|
|
22
|
+
* 対話: promptkaizen-agent init
|
|
23
|
+
* 非対話: PK_API_KEY=pk_xxx promptkaizen-agent init --env stg --yes
|
|
24
|
+
* 非対話: promptkaizen-agent init --api-key pk_xxx --env prod --yes
|
|
25
|
+
*/
|
|
26
|
+
async function runInit(argv) {
|
|
27
|
+
const flags = parseFlags(argv);
|
|
28
|
+
const isYes = flags.yes;
|
|
29
|
+
const envApiKey = process.env.PK_API_KEY?.trim() || '';
|
|
30
|
+
const apiKeyFromFlag = (flags.apiKey ?? envApiKey).trim();
|
|
31
|
+
const envFromFlag = (flags.env ?? '').trim().toLowerCase();
|
|
32
|
+
const maskEmailsFromFlag = flags.maskEmails;
|
|
33
|
+
const nonInteractive = isYes || (apiKeyFromFlag && envFromFlag);
|
|
34
|
+
const rl = nonInteractive
|
|
35
|
+
? null
|
|
36
|
+
: readline_1.default.createInterface({ input: process.stdin, output: process.stdout });
|
|
37
|
+
const ask = (q, fallback = '') => nonInteractive || !rl
|
|
38
|
+
? Promise.resolve(fallback)
|
|
39
|
+
: new Promise((resolve) => rl.question(q, (a) => resolve(a.trim())));
|
|
40
|
+
try {
|
|
41
|
+
if (!nonInteractive)
|
|
42
|
+
console.log('PromptKaizen Agent — initial setup\n');
|
|
43
|
+
// 既存 config の確認
|
|
44
|
+
const exists = await fileExists(CONFIG_PATH);
|
|
45
|
+
if (exists && !isYes) {
|
|
46
|
+
const ans = await ask(`Config already exists at ${CONFIG_PATH}. Overwrite? [y/N]: `, 'n');
|
|
47
|
+
if (ans.toLowerCase() !== 'y') {
|
|
48
|
+
console.log('Aborted. Existing config preserved.');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// 1. environment
|
|
53
|
+
const envAns = envFromFlag ||
|
|
54
|
+
(await ask('Environment? [stg / prod / custom] (default: stg): ', 'stg')) ||
|
|
55
|
+
'stg';
|
|
56
|
+
let apiEndpoint;
|
|
57
|
+
if (envAns === 'prod') {
|
|
58
|
+
apiEndpoint = ENDPOINTS.prod;
|
|
59
|
+
}
|
|
60
|
+
else if (envAns === 'custom') {
|
|
61
|
+
apiEndpoint = await ask('apiEndpoint URL: ', '');
|
|
62
|
+
if (!apiEndpoint.startsWith('http')) {
|
|
63
|
+
throw new Error('apiEndpoint must start with http:// or https://');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
apiEndpoint = ENDPOINTS.stg;
|
|
68
|
+
}
|
|
69
|
+
// 2. apiKey
|
|
70
|
+
let apiKey = apiKeyFromFlag ||
|
|
71
|
+
(await ask('apiKey (paste pk_xxx... — issue at dashboard /settings): ', ''));
|
|
72
|
+
if (!apiKey) {
|
|
73
|
+
throw new Error('apiKey is required. Pass --api-key, set PK_API_KEY, or issue one at https://promptkaizen-stg.web.app/settings');
|
|
74
|
+
}
|
|
75
|
+
if (!apiKey.startsWith('pk_') && !isYes) {
|
|
76
|
+
const warn = await ask('apiKey does not start with pk_. Continue anyway? [y/N]: ', 'n');
|
|
77
|
+
if (warn.toLowerCase() !== 'y') {
|
|
78
|
+
console.log('Aborted.');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// 3. mask emails (opt-in)
|
|
83
|
+
const maskEmails = maskEmailsFromFlag ||
|
|
84
|
+
(await ask('Mask email addresses too? [y/N]: ', 'n')).toLowerCase() === 'y';
|
|
85
|
+
const config = {
|
|
86
|
+
apiEndpoint,
|
|
87
|
+
apiKey,
|
|
88
|
+
watchPaths: ['~/.claude/projects/**/*.jsonl', '~/.codex/sessions/**/*.jsonl'],
|
|
89
|
+
exclude: [],
|
|
90
|
+
batch: { intervalMs: 5000, maxEntries: 50 },
|
|
91
|
+
agent: { skipInitialBacklog: true },
|
|
92
|
+
pii: {
|
|
93
|
+
maskFilePaths: true,
|
|
94
|
+
maskApiKeys: true,
|
|
95
|
+
maskEmails,
|
|
96
|
+
customPatterns: [],
|
|
97
|
+
},
|
|
98
|
+
telemetry: { level: 'info' },
|
|
99
|
+
};
|
|
100
|
+
await promises_1.default.mkdir(path_1.default.dirname(CONFIG_PATH), { recursive: true });
|
|
101
|
+
await promises_1.default.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
102
|
+
console.log(`✅ Config written to ${CONFIG_PATH}`);
|
|
103
|
+
if (!nonInteractive) {
|
|
104
|
+
console.log('\nNext steps:');
|
|
105
|
+
console.log(' promptkaizen-agent install-launchd # auto-start on macOS');
|
|
106
|
+
console.log(' promptkaizen-agent start # manual foreground run');
|
|
107
|
+
console.log(' promptkaizen-agent status # health check');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
rl?.close();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function parseFlags(argv) {
|
|
115
|
+
const out = { maskEmails: false, yes: false };
|
|
116
|
+
for (let i = 0; i < argv.length; i++) {
|
|
117
|
+
const a = argv[i];
|
|
118
|
+
if (a === '--api-key' && i + 1 < argv.length)
|
|
119
|
+
out.apiKey = argv[++i];
|
|
120
|
+
else if (a === '--env' && i + 1 < argv.length)
|
|
121
|
+
out.env = argv[++i];
|
|
122
|
+
else if (a === '--mask-emails')
|
|
123
|
+
out.maskEmails = true;
|
|
124
|
+
else if (a === '--yes' || a === '-y')
|
|
125
|
+
out.yes = true;
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
async function fileExists(p) {
|
|
130
|
+
try {
|
|
131
|
+
await promises_1.default.access(p);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const LAUNCH_AGENT_LABEL = "ai.promptkaizen.agent";
|
|
2
|
+
export declare function plistPath(): string;
|
|
3
|
+
export interface PlistOptions {
|
|
4
|
+
nodeBin: string;
|
|
5
|
+
agentScript: string;
|
|
6
|
+
logDir: string;
|
|
7
|
+
}
|
|
8
|
+
/** plist 内容を組み立て。テスト容易性のため引数で外部依存を受ける */
|
|
9
|
+
export declare function buildPlist(opts: PlistOptions): string;
|
|
10
|
+
/**
|
|
11
|
+
* `promptkaizen-agent install-launchd`
|
|
12
|
+
*
|
|
13
|
+
* Mac の launchd に agent を登録して、ログイン時に自動起動 + 落ちたら自動再起動。
|
|
14
|
+
* 既存 plist があれば一度 unload してから上書き → load し直す。
|
|
15
|
+
*/
|
|
16
|
+
export declare function runInstallLaunchd(_argv: string[]): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=install-launchd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-launchd.d.ts","sourceRoot":"","sources":["../../src/cli/install-launchd.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,kBAAkB,0BAA0B,CAAA;AAGzD,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,yCAAyC;AACzC,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA0BrD;AASD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDtE"}
|
|
@@ -0,0 +1,128 @@
|
|
|
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.LAUNCH_AGENT_LABEL = void 0;
|
|
7
|
+
exports.plistPath = plistPath;
|
|
8
|
+
exports.buildPlist = buildPlist;
|
|
9
|
+
exports.runInstallLaunchd = runInstallLaunchd;
|
|
10
|
+
const child_process_1 = require("child_process");
|
|
11
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
12
|
+
const os_1 = __importDefault(require("os"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
exports.LAUNCH_AGENT_LABEL = 'ai.promptkaizen.agent';
|
|
15
|
+
const PLIST_FILENAME = `${exports.LAUNCH_AGENT_LABEL}.plist`;
|
|
16
|
+
function plistPath() {
|
|
17
|
+
return path_1.default.join(os_1.default.homedir(), 'Library', 'LaunchAgents', PLIST_FILENAME);
|
|
18
|
+
}
|
|
19
|
+
/** plist 内容を組み立て。テスト容易性のため引数で外部依存を受ける */
|
|
20
|
+
function buildPlist(opts) {
|
|
21
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
22
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
23
|
+
<plist version="1.0">
|
|
24
|
+
<dict>
|
|
25
|
+
<key>Label</key>
|
|
26
|
+
<string>${exports.LAUNCH_AGENT_LABEL}</string>
|
|
27
|
+
<key>ProgramArguments</key>
|
|
28
|
+
<array>
|
|
29
|
+
<string>${escapeXml(opts.nodeBin)}</string>
|
|
30
|
+
<string>${escapeXml(opts.agentScript)}</string>
|
|
31
|
+
<string>start</string>
|
|
32
|
+
</array>
|
|
33
|
+
<key>RunAtLoad</key>
|
|
34
|
+
<true/>
|
|
35
|
+
<key>KeepAlive</key>
|
|
36
|
+
<true/>
|
|
37
|
+
<key>StandardOutPath</key>
|
|
38
|
+
<string>${escapeXml(path_1.default.join(opts.logDir, 'agent.log'))}</string>
|
|
39
|
+
<key>StandardErrorPath</key>
|
|
40
|
+
<string>${escapeXml(path_1.default.join(opts.logDir, 'agent.error.log'))}</string>
|
|
41
|
+
<key>ProcessType</key>
|
|
42
|
+
<string>Background</string>
|
|
43
|
+
</dict>
|
|
44
|
+
</plist>
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
function escapeXml(s) {
|
|
48
|
+
return s
|
|
49
|
+
.replaceAll('&', '&')
|
|
50
|
+
.replaceAll('<', '<')
|
|
51
|
+
.replaceAll('>', '>');
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* `promptkaizen-agent install-launchd`
|
|
55
|
+
*
|
|
56
|
+
* Mac の launchd に agent を登録して、ログイン時に自動起動 + 落ちたら自動再起動。
|
|
57
|
+
* 既存 plist があれば一度 unload してから上書き → load し直す。
|
|
58
|
+
*/
|
|
59
|
+
async function runInstallLaunchd(_argv) {
|
|
60
|
+
if (process.platform !== 'darwin') {
|
|
61
|
+
console.error('install-launchd is macOS only. Use systemd on Linux / Task Scheduler on Windows.');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
// dist/cli/install-launchd.js から見て dist/index.js を絶対パスで指す
|
|
65
|
+
const agentScript = path_1.default.resolve(__dirname, '..', 'index.js');
|
|
66
|
+
await assertExists(agentScript, 'Agent script not found. Did you run `npm run build`?');
|
|
67
|
+
const logDir = path_1.default.join(os_1.default.homedir(), '.promptkaizen');
|
|
68
|
+
await promises_1.default.mkdir(logDir, { recursive: true });
|
|
69
|
+
const plist = buildPlist({
|
|
70
|
+
nodeBin: process.execPath,
|
|
71
|
+
agentScript,
|
|
72
|
+
logDir,
|
|
73
|
+
});
|
|
74
|
+
const dst = plistPath();
|
|
75
|
+
await promises_1.default.mkdir(path_1.default.dirname(dst), { recursive: true });
|
|
76
|
+
// 既存 plist は unload して上書き
|
|
77
|
+
const exists = await fileExists(dst);
|
|
78
|
+
if (exists) {
|
|
79
|
+
try {
|
|
80
|
+
(0, child_process_1.execSync)(`launchctl unload ${shellEscape(dst)}`, { stdio: 'ignore' });
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
/* 未 load なら無視 */
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
await promises_1.default.writeFile(dst, plist, 'utf8');
|
|
87
|
+
console.log(`✅ Wrote plist: ${dst}`);
|
|
88
|
+
// load + 即起動
|
|
89
|
+
try {
|
|
90
|
+
(0, child_process_1.execSync)(`launchctl load -w ${shellEscape(dst)}`, { stdio: 'inherit' });
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
console.error(`launchctl load failed: ${e.message}`);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
// kickstart で即時起動 (load だけだと RunAtLoad の発火が遅れる場合がある)
|
|
97
|
+
try {
|
|
98
|
+
const uid = process.getuid?.() ?? 501;
|
|
99
|
+
(0, child_process_1.execSync)(`launchctl kickstart -k gui/${uid}/${exports.LAUNCH_AGENT_LABEL}`, { stdio: 'ignore' });
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
/* kickstart は best-effort */
|
|
103
|
+
}
|
|
104
|
+
console.log(`✅ launchd agent registered: ${exports.LAUNCH_AGENT_LABEL}`);
|
|
105
|
+
console.log('\nVerify with:');
|
|
106
|
+
console.log(` launchctl list | grep ${exports.LAUNCH_AGENT_LABEL}`);
|
|
107
|
+
console.log(` tail -f ~/.promptkaizen/agent.log`);
|
|
108
|
+
console.log(` promptkaizen-agent status`);
|
|
109
|
+
}
|
|
110
|
+
async function fileExists(p) {
|
|
111
|
+
try {
|
|
112
|
+
await promises_1.default.access(p);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async function assertExists(p, msg) {
|
|
120
|
+
if (!(await fileExists(p))) {
|
|
121
|
+
console.error(`${msg} (looked for ${p})`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function shellEscape(s) {
|
|
126
|
+
return `'${s.replaceAll("'", "'\\''")}'`;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=install-launchd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-launchd.js","sourceRoot":"","sources":["../../src/cli/install-launchd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmF5D"}
|