@nocoo/pew 0.6.0 → 0.7.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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +179 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts +38 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +73 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/notify.d.ts +11 -0
- package/dist/commands/notify.d.ts.map +1 -0
- package/dist/commands/notify.js +28 -0
- package/dist/commands/notify.js.map +1 -0
- package/dist/commands/session-upload.d.ts +6 -22
- package/dist/commands/session-upload.d.ts.map +1 -1
- package/dist/commands/session-upload.js +12 -144
- package/dist/commands/session-upload.js.map +1 -1
- package/dist/commands/status.d.ts +4 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +1 -0
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/uninstall.d.ts +39 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +107 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/upload-engine.d.ts +63 -0
- package/dist/commands/upload-engine.d.ts.map +1 -0
- package/dist/commands/upload-engine.js +164 -0
- package/dist/commands/upload-engine.js.map +1 -0
- package/dist/commands/upload.d.ts +5 -21
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +11 -144
- package/dist/commands/upload.js.map +1 -1
- package/dist/notifier/claude-hook.d.ts +18 -0
- package/dist/notifier/claude-hook.d.ts.map +1 -0
- package/dist/notifier/claude-hook.js +226 -0
- package/dist/notifier/claude-hook.js.map +1 -0
- package/dist/notifier/codex-notifier.d.ts +19 -0
- package/dist/notifier/codex-notifier.d.ts.map +1 -0
- package/dist/notifier/codex-notifier.js +258 -0
- package/dist/notifier/codex-notifier.js.map +1 -0
- package/dist/notifier/coordinator.d.ts +29 -0
- package/dist/notifier/coordinator.d.ts.map +1 -0
- package/dist/notifier/coordinator.js +176 -0
- package/dist/notifier/coordinator.js.map +1 -0
- package/dist/notifier/gemini-hook.d.ts +18 -0
- package/dist/notifier/gemini-hook.d.ts.map +1 -0
- package/dist/notifier/gemini-hook.js +243 -0
- package/dist/notifier/gemini-hook.js.map +1 -0
- package/dist/notifier/notify-handler.d.ts +41 -0
- package/dist/notifier/notify-handler.d.ts.map +1 -0
- package/dist/notifier/notify-handler.js +172 -0
- package/dist/notifier/notify-handler.js.map +1 -0
- package/dist/notifier/openclaw-hook.d.ts +28 -0
- package/dist/notifier/openclaw-hook.d.ts.map +1 -0
- package/dist/notifier/openclaw-hook.js +272 -0
- package/dist/notifier/openclaw-hook.js.map +1 -0
- package/dist/notifier/opencode-plugin.d.ts +20 -0
- package/dist/notifier/opencode-plugin.d.ts.map +1 -0
- package/dist/notifier/opencode-plugin.js +106 -0
- package/dist/notifier/opencode-plugin.js.map +1 -0
- package/dist/notifier/paths.d.ts +21 -0
- package/dist/notifier/paths.d.ts.map +1 -0
- package/dist/notifier/paths.js +36 -0
- package/dist/notifier/paths.js.map +1 -0
- package/dist/notifier/registry.d.ts +21 -0
- package/dist/notifier/registry.d.ts.map +1 -0
- package/dist/notifier/registry.js +145 -0
- package/dist/notifier/registry.js.map +1 -0
- package/dist/storage/base-queue.d.ts +40 -0
- package/dist/storage/base-queue.d.ts.map +1 -0
- package/dist/storage/base-queue.js +89 -0
- package/dist/storage/base-queue.js.map +1 -0
- package/dist/storage/local-queue.d.ts +4 -24
- package/dist/storage/local-queue.d.ts.map +1 -1
- package/dist/storage/local-queue.js +5 -64
- package/dist/storage/local-queue.js.map +1 -1
- package/dist/storage/session-queue.d.ts +3 -21
- package/dist/storage/session-queue.d.ts.map +1 -1
- package/dist/storage/session-queue.js +4 -58
- package/dist/storage/session-queue.js.map +1 -1
- package/dist/utils/paths.d.ts +4 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +4 -0
- package/dist/utils/paths.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI upload command — sends local queue records to the Pew SaaS.
|
|
2
|
+
* CLI upload command — sends local token queue records to the Pew SaaS.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 2. Read un-uploaded records from queue (using saved offset)
|
|
7
|
-
* 3. Split into batches of ≤50 (D1 Free plan: 50 queries/Worker invocation)
|
|
8
|
-
* 4. POST each batch to /api/ingest with Bearer token
|
|
9
|
-
* 5. Persist offset after each successful batch (for resume on failure)
|
|
10
|
-
* 6. Retry on 5xx with exponential backoff
|
|
4
|
+
* Thin wrapper around the generic upload engine with token-specific
|
|
5
|
+
* preprocessing (aggregation by source/model/hour_start).
|
|
11
6
|
*/
|
|
7
|
+
import type { UploadResult, UploadProgressEvent } from "./upload-engine.js";
|
|
12
8
|
import type { QueueRecord } from "@pew/core";
|
|
13
9
|
export interface UploadOptions {
|
|
14
10
|
/** Directory for config file and queue state */
|
|
@@ -28,19 +24,7 @@ export interface UploadOptions {
|
|
|
28
24
|
/** Progress callback */
|
|
29
25
|
onProgress?: (event: UploadProgressEvent) => void;
|
|
30
26
|
}
|
|
31
|
-
export
|
|
32
|
-
phase: "uploading" | "done";
|
|
33
|
-
batch?: number;
|
|
34
|
-
totalBatches?: number;
|
|
35
|
-
total?: number;
|
|
36
|
-
message?: string;
|
|
37
|
-
}
|
|
38
|
-
export interface UploadResult {
|
|
39
|
-
success: boolean;
|
|
40
|
-
uploaded: number;
|
|
41
|
-
batches: number;
|
|
42
|
-
error?: string;
|
|
43
|
-
}
|
|
27
|
+
export type { UploadResult, UploadProgressEvent };
|
|
44
28
|
/**
|
|
45
29
|
* Aggregate QueueRecords by (source, model, hour_start), summing token fields.
|
|
46
30
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EAEpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAM7C,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,mCAAmC;IACnC,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAC/B,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wBAAwB;IACxB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACnD;AAED,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAMlD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAoBtE;AAMD,wBAAsB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAW9E"}
|
package/dist/commands/upload.js
CHANGED
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI upload command — sends local queue records to the Pew SaaS.
|
|
2
|
+
* CLI upload command — sends local token queue records to the Pew SaaS.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 2. Read un-uploaded records from queue (using saved offset)
|
|
7
|
-
* 3. Split into batches of ≤50 (D1 Free plan: 50 queries/Worker invocation)
|
|
8
|
-
* 4. POST each batch to /api/ingest with Bearer token
|
|
9
|
-
* 5. Persist offset after each successful batch (for resume on failure)
|
|
10
|
-
* 6. Retry on 5xx with exponential backoff
|
|
4
|
+
* Thin wrapper around the generic upload engine with token-specific
|
|
5
|
+
* preprocessing (aggregation by source/model/hour_start).
|
|
11
6
|
*/
|
|
12
|
-
import { ConfigManager } from "../config/manager.js";
|
|
13
7
|
import { LocalQueue } from "../storage/local-queue.js";
|
|
14
|
-
|
|
15
|
-
// Constants
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
const DEFAULT_BATCH_SIZE = 50;
|
|
18
|
-
const DEFAULT_MAX_RETRIES = 2;
|
|
19
|
-
const DEFAULT_RETRY_DELAY_MS = 1000;
|
|
8
|
+
import { createUploadEngine } from "./upload-engine.js";
|
|
20
9
|
// ---------------------------------------------------------------------------
|
|
21
10
|
// Pre-aggregation — merge QueueRecords with the same (source, model, hour_start)
|
|
22
11
|
// ---------------------------------------------------------------------------
|
|
@@ -51,135 +40,13 @@ export function aggregateRecords(records) {
|
|
|
51
40
|
// Implementation
|
|
52
41
|
// ---------------------------------------------------------------------------
|
|
53
42
|
export async function executeUpload(opts) {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
success: false,
|
|
61
|
-
uploaded: 0,
|
|
62
|
-
batches: 0,
|
|
63
|
-
error: "Not logged in. Run `pew login` first.",
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
// 2. Read un-uploaded records
|
|
67
|
-
const queue = new LocalQueue(stateDir);
|
|
68
|
-
const currentOffset = await queue.loadOffset();
|
|
69
|
-
const { records: rawRecords, newOffset } = await queue.readFromOffset(currentOffset);
|
|
70
|
-
if (rawRecords.length === 0) {
|
|
71
|
-
return { success: true, uploaded: 0, batches: 0 };
|
|
72
|
-
}
|
|
73
|
-
// 2b. Pre-aggregate by (source, model, hour_start) for idempotent upsert
|
|
74
|
-
const records = aggregateRecords(rawRecords);
|
|
75
|
-
// 3. Split into batches
|
|
76
|
-
const batches = [];
|
|
77
|
-
for (let i = 0; i < records.length; i += batchSize) {
|
|
78
|
-
batches.push(records.slice(i, i + batchSize));
|
|
79
|
-
}
|
|
80
|
-
// 4. Upload each batch
|
|
81
|
-
const endpoint = `${apiUrl}/api/ingest`;
|
|
82
|
-
let totalUploaded = 0;
|
|
83
|
-
let batchesCompleted = 0;
|
|
84
|
-
for (let batchIdx = 0; batchIdx < batches.length; batchIdx++) {
|
|
85
|
-
const batch = batches[batchIdx];
|
|
86
|
-
onProgress?.({
|
|
87
|
-
phase: "uploading",
|
|
88
|
-
batch: batchIdx + 1,
|
|
89
|
-
totalBatches: batches.length,
|
|
90
|
-
total: records.length,
|
|
91
|
-
message: `Uploading batch ${batchIdx + 1}/${batches.length} (${batch.length} records)...`,
|
|
92
|
-
});
|
|
93
|
-
const result = await sendBatchWithRetry({
|
|
94
|
-
endpoint,
|
|
95
|
-
token: config.token,
|
|
96
|
-
batch,
|
|
97
|
-
fetchFn,
|
|
98
|
-
maxRetries,
|
|
99
|
-
retryDelayMs,
|
|
100
|
-
});
|
|
101
|
-
if (!result.ok) {
|
|
102
|
-
// With idempotent overwrite upsert, don't save partial offset.
|
|
103
|
-
// Next retry will re-aggregate and re-send everything safely.
|
|
104
|
-
return {
|
|
105
|
-
success: false,
|
|
106
|
-
uploaded: totalUploaded,
|
|
107
|
-
batches: batchesCompleted,
|
|
108
|
-
error: result.error,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
totalUploaded += batch.length;
|
|
112
|
-
batchesCompleted++;
|
|
113
|
-
}
|
|
114
|
-
// 5. All batches succeeded — save final offset
|
|
115
|
-
await queue.saveOffset(newOffset);
|
|
116
|
-
onProgress?.({
|
|
117
|
-
phase: "done",
|
|
118
|
-
total: totalUploaded,
|
|
119
|
-
message: `Uploaded ${totalUploaded} records in ${batchesCompleted} batch(es).`,
|
|
43
|
+
const queue = new LocalQueue(opts.stateDir);
|
|
44
|
+
const engine = createUploadEngine({
|
|
45
|
+
queue,
|
|
46
|
+
endpoint: "/api/ingest",
|
|
47
|
+
entityName: "records",
|
|
48
|
+
preprocess: aggregateRecords,
|
|
120
49
|
});
|
|
121
|
-
return
|
|
122
|
-
success: true,
|
|
123
|
-
uploaded: totalUploaded,
|
|
124
|
-
batches: batchesCompleted,
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
async function sendBatchWithRetry(opts) {
|
|
128
|
-
const { endpoint, token, batch, fetchFn, maxRetries, retryDelayMs } = opts;
|
|
129
|
-
let lastError = "";
|
|
130
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
131
|
-
if (attempt > 0 && retryDelayMs > 0) {
|
|
132
|
-
await sleep(retryDelayMs * 2 ** (attempt - 1));
|
|
133
|
-
}
|
|
134
|
-
try {
|
|
135
|
-
const resp = await fetchFn(endpoint, {
|
|
136
|
-
method: "POST",
|
|
137
|
-
headers: {
|
|
138
|
-
"Content-Type": "application/json",
|
|
139
|
-
Authorization: `Bearer ${token}`,
|
|
140
|
-
},
|
|
141
|
-
body: JSON.stringify(batch),
|
|
142
|
-
});
|
|
143
|
-
if (resp.ok) {
|
|
144
|
-
return { ok: true };
|
|
145
|
-
}
|
|
146
|
-
// 429 — rate limited, retry with Retry-After if available
|
|
147
|
-
if (resp.status === 429) {
|
|
148
|
-
const retryAfter = resp.headers.get("Retry-After");
|
|
149
|
-
const retryMs = retryAfter
|
|
150
|
-
? Math.max(Number(retryAfter) * 1000, retryDelayMs)
|
|
151
|
-
: retryDelayMs * 2 ** attempt;
|
|
152
|
-
if (attempt < maxRetries && retryMs > 0) {
|
|
153
|
-
await sleep(retryMs);
|
|
154
|
-
}
|
|
155
|
-
const body = await resp.json().catch(() => ({}));
|
|
156
|
-
lastError = `429: ${body.error ?? "Too Many Requests"}`;
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
// 4xx — client error, don't retry
|
|
160
|
-
if (resp.status >= 400 && resp.status < 500) {
|
|
161
|
-
const body = await resp.json().catch(() => ({}));
|
|
162
|
-
const msg = body.error ?? `HTTP ${resp.status}`;
|
|
163
|
-
return { ok: false, error: `${resp.status}: ${msg}` };
|
|
164
|
-
}
|
|
165
|
-
// 5xx — server error, retry
|
|
166
|
-
const body = await resp.json().catch(() => ({}));
|
|
167
|
-
lastError = `${resp.status}: ${body.error ?? "Server Error"}`;
|
|
168
|
-
}
|
|
169
|
-
catch (err) {
|
|
170
|
-
lastError = String(err.message ?? err);
|
|
171
|
-
// Network errors — don't retry if maxRetries is 0
|
|
172
|
-
if (attempt >= maxRetries) {
|
|
173
|
-
return { ok: false, error: lastError };
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return {
|
|
178
|
-
ok: false,
|
|
179
|
-
error: `Upload failed after ${maxRetries + 1} attempts: ${lastError}`,
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
function sleep(ms) {
|
|
183
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
50
|
+
return engine.execute(opts);
|
|
184
51
|
}
|
|
185
52
|
//# sourceMappingURL=upload.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAiCxD,8EAA8E;AAC9E,iFAAiF;AACjF,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAsB;IACrD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuB,CAAC;IAE3C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;QACrD,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC,YAAY,CAAC;YACxC,QAAQ,CAAC,mBAAmB,IAAI,CAAC,CAAC,mBAAmB,CAAC;YACtD,QAAQ,CAAC,aAAa,IAAI,CAAC,CAAC,aAAa,CAAC;YAC1C,QAAQ,CAAC,uBAAuB,IAAI,CAAC,CAAC,uBAAuB,CAAC;YAC9D,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC,YAAY,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAmB;IACrD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE5C,MAAM,MAAM,GAAG,kBAAkB,CAAc;QAC7C,KAAK;QACL,QAAQ,EAAE,aAAa;QACvB,UAAU,EAAE,SAAS;QACrB,UAAU,EAAE,gBAAgB;KAC7B,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { NotifierOperationResult, NotifierStatus } from "@pew/core";
|
|
2
|
+
interface ClaudeHookFs {
|
|
3
|
+
readFile: (path: string, encoding: BufferEncoding) => Promise<string>;
|
|
4
|
+
writeFile: (path: string, data: string, encoding: BufferEncoding) => Promise<unknown>;
|
|
5
|
+
mkdir: (path: string, options: {
|
|
6
|
+
recursive: boolean;
|
|
7
|
+
}) => Promise<unknown>;
|
|
8
|
+
}
|
|
9
|
+
export interface ClaudeHookOptions {
|
|
10
|
+
settingsPath: string;
|
|
11
|
+
notifyPath: string;
|
|
12
|
+
fs?: ClaudeHookFs;
|
|
13
|
+
}
|
|
14
|
+
export declare function installClaudeHook(opts: ClaudeHookOptions): Promise<NotifierOperationResult>;
|
|
15
|
+
export declare function uninstallClaudeHook(opts: ClaudeHookOptions): Promise<NotifierOperationResult>;
|
|
16
|
+
export declare function getClaudeHookStatus(opts: ClaudeHookOptions): Promise<NotifierStatus>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=claude-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-hook.d.ts","sourceRoot":"","sources":["../../src/notifier/claude-hook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEzE,UAAU,YAAY;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtF,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5E;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,YAAY,CAAC;CACnB;AAKD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,uBAAuB,CAAC,CAwDlC;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,uBAAuB,CAAC,CA2DlC;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAW1F"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
const EVENT_NAME = "SessionEnd";
|
|
3
|
+
const SOURCE = "claude-code";
|
|
4
|
+
export async function installClaudeHook(opts) {
|
|
5
|
+
const fs = opts.fs ?? { readFile, writeFile, mkdir };
|
|
6
|
+
const command = buildClaudeHookCommand(opts.notifyPath);
|
|
7
|
+
const loaded = await loadSettings(opts.settingsPath, fs);
|
|
8
|
+
if (loaded.status === "invalid") {
|
|
9
|
+
return {
|
|
10
|
+
source: SOURCE,
|
|
11
|
+
action: "skip",
|
|
12
|
+
changed: false,
|
|
13
|
+
detail: "Invalid Claude settings.json",
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const settings = loaded.settings ?? {};
|
|
17
|
+
const hooks = normalizeObject(settings.hooks);
|
|
18
|
+
const entries = normalizeArray(hooks[EVENT_NAME]);
|
|
19
|
+
let changed = false;
|
|
20
|
+
const nextEntries = entries.map((entry) => {
|
|
21
|
+
const normalized = normalizeEntry(entry, command);
|
|
22
|
+
if (normalized !== entry)
|
|
23
|
+
changed = true;
|
|
24
|
+
return normalized;
|
|
25
|
+
});
|
|
26
|
+
if (!hasCommand(nextEntries, command)) {
|
|
27
|
+
nextEntries.push({
|
|
28
|
+
hooks: [{ type: "command", command }],
|
|
29
|
+
});
|
|
30
|
+
changed = true;
|
|
31
|
+
}
|
|
32
|
+
if (!changed) {
|
|
33
|
+
return {
|
|
34
|
+
source: SOURCE,
|
|
35
|
+
action: "install",
|
|
36
|
+
changed: false,
|
|
37
|
+
detail: "Claude hook already installed",
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const nextSettings = {
|
|
41
|
+
...settings,
|
|
42
|
+
hooks: {
|
|
43
|
+
...hooks,
|
|
44
|
+
[EVENT_NAME]: nextEntries,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
const backupPath = await writeSettings(opts.settingsPath, nextSettings, loaded.raw, fs);
|
|
48
|
+
return {
|
|
49
|
+
source: SOURCE,
|
|
50
|
+
action: "install",
|
|
51
|
+
changed: true,
|
|
52
|
+
detail: "Claude hook installed",
|
|
53
|
+
backupPath: backupPath ?? undefined,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export async function uninstallClaudeHook(opts) {
|
|
57
|
+
const fs = opts.fs ?? { readFile, writeFile, mkdir };
|
|
58
|
+
const command = buildClaudeHookCommand(opts.notifyPath);
|
|
59
|
+
const loaded = await loadSettings(opts.settingsPath, fs);
|
|
60
|
+
if (loaded.status === "missing") {
|
|
61
|
+
return {
|
|
62
|
+
source: SOURCE,
|
|
63
|
+
action: "skip",
|
|
64
|
+
changed: false,
|
|
65
|
+
detail: "Claude settings.json not found",
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (loaded.status === "invalid" || !loaded.settings) {
|
|
69
|
+
return {
|
|
70
|
+
source: SOURCE,
|
|
71
|
+
action: "skip",
|
|
72
|
+
changed: false,
|
|
73
|
+
detail: "Invalid Claude settings.json",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const settings = loaded.settings;
|
|
77
|
+
const hooks = normalizeObject(settings.hooks);
|
|
78
|
+
const entries = normalizeArray(hooks[EVENT_NAME]);
|
|
79
|
+
let removed = false;
|
|
80
|
+
const nextEntries = entries
|
|
81
|
+
.map((entry) => {
|
|
82
|
+
const stripped = stripCommand(entry, command);
|
|
83
|
+
if (stripped !== entry)
|
|
84
|
+
removed = true;
|
|
85
|
+
return stripped;
|
|
86
|
+
})
|
|
87
|
+
.filter(Boolean);
|
|
88
|
+
if (!removed) {
|
|
89
|
+
return {
|
|
90
|
+
source: SOURCE,
|
|
91
|
+
action: "skip",
|
|
92
|
+
changed: false,
|
|
93
|
+
detail: "Claude hook not installed",
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const nextHooks = { ...hooks };
|
|
97
|
+
if (nextEntries.length > 0)
|
|
98
|
+
nextHooks[EVENT_NAME] = nextEntries;
|
|
99
|
+
else
|
|
100
|
+
delete nextHooks[EVENT_NAME];
|
|
101
|
+
const nextSettings = { ...settings };
|
|
102
|
+
if (Object.keys(nextHooks).length > 0)
|
|
103
|
+
nextSettings.hooks = nextHooks;
|
|
104
|
+
else
|
|
105
|
+
delete nextSettings.hooks;
|
|
106
|
+
const backupPath = await writeSettings(opts.settingsPath, nextSettings, loaded.raw, fs);
|
|
107
|
+
return {
|
|
108
|
+
source: SOURCE,
|
|
109
|
+
action: "uninstall",
|
|
110
|
+
changed: true,
|
|
111
|
+
detail: "Claude hook removed",
|
|
112
|
+
backupPath: backupPath ?? undefined,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
export async function getClaudeHookStatus(opts) {
|
|
116
|
+
const fs = opts.fs ?? { readFile, writeFile, mkdir };
|
|
117
|
+
const loaded = await loadSettings(opts.settingsPath, fs);
|
|
118
|
+
if (loaded.status === "missing")
|
|
119
|
+
return "not-installed";
|
|
120
|
+
if (loaded.status === "invalid" || !loaded.settings)
|
|
121
|
+
return "error";
|
|
122
|
+
return hasCommand(normalizeArray(normalizeObject(loaded.settings.hooks)[EVENT_NAME]), buildClaudeHookCommand(opts.notifyPath))
|
|
123
|
+
? "installed"
|
|
124
|
+
: "not-installed";
|
|
125
|
+
}
|
|
126
|
+
function buildClaudeHookCommand(notifyPath) {
|
|
127
|
+
return `/usr/bin/env node ${quoteArg(notifyPath)} --source=${SOURCE}`;
|
|
128
|
+
}
|
|
129
|
+
async function loadSettings(settingsPath, fs) {
|
|
130
|
+
try {
|
|
131
|
+
const raw = await fs.readFile(settingsPath, "utf8");
|
|
132
|
+
try {
|
|
133
|
+
const parsed = JSON.parse(raw);
|
|
134
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
135
|
+
return { status: "invalid", settings: null, raw };
|
|
136
|
+
}
|
|
137
|
+
return { status: "ok", settings: parsed, raw };
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return { status: "invalid", settings: null, raw };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
if (err?.code === "ENOENT") {
|
|
145
|
+
return { status: "missing", settings: null, raw: null };
|
|
146
|
+
}
|
|
147
|
+
throw err;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function normalizeObject(value) {
|
|
151
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
152
|
+
? { ...value }
|
|
153
|
+
: {};
|
|
154
|
+
}
|
|
155
|
+
function normalizeArray(value) {
|
|
156
|
+
return Array.isArray(value)
|
|
157
|
+
? value.filter((entry) => Boolean(entry && typeof entry === "object"))
|
|
158
|
+
: [];
|
|
159
|
+
}
|
|
160
|
+
function normalizeEntry(entry, command) {
|
|
161
|
+
const hooks = Array.isArray(entry.hooks) ? entry.hooks : null;
|
|
162
|
+
if (!hooks)
|
|
163
|
+
return entry;
|
|
164
|
+
let changed = false;
|
|
165
|
+
const nextHooks = hooks.map((hook) => {
|
|
166
|
+
if (!hook || typeof hook !== "object")
|
|
167
|
+
return hook;
|
|
168
|
+
const hookObject = hook;
|
|
169
|
+
if (!commandMatches(hookObject.command, command))
|
|
170
|
+
return hookObject;
|
|
171
|
+
if (hookObject.type === "command")
|
|
172
|
+
return hookObject;
|
|
173
|
+
changed = true;
|
|
174
|
+
return { ...hookObject, type: "command" };
|
|
175
|
+
});
|
|
176
|
+
return changed ? { ...entry, hooks: nextHooks } : entry;
|
|
177
|
+
}
|
|
178
|
+
function stripCommand(entry, command) {
|
|
179
|
+
const hooks = Array.isArray(entry.hooks) ? entry.hooks : null;
|
|
180
|
+
if (!hooks)
|
|
181
|
+
return entry;
|
|
182
|
+
const nextHooks = hooks.filter((hook) => {
|
|
183
|
+
if (!hook || typeof hook !== "object")
|
|
184
|
+
return true;
|
|
185
|
+
return !commandMatches(hook.command, command);
|
|
186
|
+
});
|
|
187
|
+
if (nextHooks.length === hooks.length)
|
|
188
|
+
return entry;
|
|
189
|
+
if (nextHooks.length === 0)
|
|
190
|
+
return null;
|
|
191
|
+
return { ...entry, hooks: nextHooks };
|
|
192
|
+
}
|
|
193
|
+
function hasCommand(entries, command) {
|
|
194
|
+
return entries.some((entry) => {
|
|
195
|
+
const hooks = Array.isArray(entry.hooks) ? entry.hooks : [];
|
|
196
|
+
return hooks.some((hook) => {
|
|
197
|
+
if (!hook || typeof hook !== "object")
|
|
198
|
+
return false;
|
|
199
|
+
return commandMatches(hook.command, command);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function commandMatches(value, command) {
|
|
204
|
+
return value === command;
|
|
205
|
+
}
|
|
206
|
+
async function writeSettings(settingsPath, settings, previousRaw, fs) {
|
|
207
|
+
const backupPath = previousRaw !== null
|
|
208
|
+
? `${settingsPath}.bak.${new Date().toISOString().replace(/[:.]/g, "-")}`
|
|
209
|
+
: null;
|
|
210
|
+
await fs.mkdir(new URL(".", `file://${settingsPath}`).pathname, { recursive: true }).catch(async () => {
|
|
211
|
+
const lastSlash = settingsPath.lastIndexOf("/");
|
|
212
|
+
const dir = lastSlash >= 0 ? settingsPath.slice(0, lastSlash) : ".";
|
|
213
|
+
await fs.mkdir(dir, { recursive: true });
|
|
214
|
+
});
|
|
215
|
+
if (backupPath && previousRaw !== null) {
|
|
216
|
+
await fs.writeFile(backupPath, previousRaw, "utf8");
|
|
217
|
+
}
|
|
218
|
+
await fs.writeFile(settingsPath, `${JSON.stringify(settings, null, 2)}\n`, "utf8");
|
|
219
|
+
return backupPath;
|
|
220
|
+
}
|
|
221
|
+
function quoteArg(value) {
|
|
222
|
+
if (/^[A-Za-z0-9_\-./:@]+$/.test(value))
|
|
223
|
+
return value;
|
|
224
|
+
return `"${value.replace(/"/g, '\\"')}"`;
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=claude-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-hook.js","sourceRoot":"","sources":["../../src/notifier/claude-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { NotifierOperationResult, NotifierStatus } from "@pew/core";
|
|
2
|
+
interface CodexNotifierFs {
|
|
3
|
+
readFile: (path: string, encoding: BufferEncoding) => Promise<string>;
|
|
4
|
+
writeFile: (path: string, data: string, encoding: BufferEncoding) => Promise<unknown>;
|
|
5
|
+
mkdir: (path: string, options: {
|
|
6
|
+
recursive: boolean;
|
|
7
|
+
}) => Promise<unknown>;
|
|
8
|
+
}
|
|
9
|
+
export interface CodexNotifierOptions {
|
|
10
|
+
configPath: string;
|
|
11
|
+
notifyPath: string;
|
|
12
|
+
originalBackupPath: string;
|
|
13
|
+
fs?: CodexNotifierFs;
|
|
14
|
+
}
|
|
15
|
+
export declare function installCodexNotifier(opts: CodexNotifierOptions): Promise<NotifierOperationResult>;
|
|
16
|
+
export declare function uninstallCodexNotifier(opts: CodexNotifierOptions): Promise<NotifierOperationResult>;
|
|
17
|
+
export declare function getCodexNotifierStatus(opts: CodexNotifierOptions): Promise<NotifierStatus>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=codex-notifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-notifier.d.ts","sourceRoot":"","sources":["../../src/notifier/codex-notifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEzE,UAAU,eAAe;IACvB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtF,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5E;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,EAAE,CAAC,EAAE,eAAe,CAAC;CACtB;AAID,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,uBAAuB,CAAC,CA+ClC;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,uBAAuB,CAAC,CAwClC;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,cAAc,CAAC,CAOzB"}
|