hippo-memory 1.2.1 → 1.3.1
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 +17 -0
- package/dist/cli.js +10 -0
- package/dist/cli.js.map +1 -1
- package/dist/connectors/github/backfill.d.ts +48 -0
- package/dist/connectors/github/backfill.d.ts.map +1 -0
- package/dist/connectors/github/backfill.js +272 -0
- package/dist/connectors/github/backfill.js.map +1 -0
- package/dist/connectors/github/cli-impl.d.ts +24 -0
- package/dist/connectors/github/cli-impl.d.ts.map +1 -0
- package/dist/connectors/github/cli-impl.js +192 -0
- package/dist/connectors/github/cli-impl.js.map +1 -0
- package/dist/connectors/github/deletion.d.ts +43 -0
- package/dist/connectors/github/deletion.d.ts.map +1 -0
- package/dist/connectors/github/deletion.js +83 -0
- package/dist/connectors/github/deletion.js.map +1 -0
- package/dist/connectors/github/dlq.d.ts +108 -0
- package/dist/connectors/github/dlq.d.ts.map +1 -0
- package/dist/connectors/github/dlq.js +182 -0
- package/dist/connectors/github/dlq.js.map +1 -0
- package/dist/connectors/github/idempotency.d.ts +19 -0
- package/dist/connectors/github/idempotency.d.ts.map +1 -0
- package/dist/connectors/github/idempotency.js +25 -0
- package/dist/connectors/github/idempotency.js.map +1 -0
- package/dist/connectors/github/ingest.d.ts +67 -0
- package/dist/connectors/github/ingest.d.ts.map +1 -0
- package/dist/connectors/github/ingest.js +138 -0
- package/dist/connectors/github/ingest.js.map +1 -0
- package/dist/connectors/github/octokit-client.d.ts +36 -0
- package/dist/connectors/github/octokit-client.d.ts.map +1 -0
- package/dist/connectors/github/octokit-client.js +65 -0
- package/dist/connectors/github/octokit-client.js.map +1 -0
- package/dist/connectors/github/ratelimit.d.ts +20 -0
- package/dist/connectors/github/ratelimit.d.ts.map +1 -0
- package/dist/connectors/github/ratelimit.js +31 -0
- package/dist/connectors/github/ratelimit.js.map +1 -0
- package/dist/connectors/github/scope.d.ts +8 -0
- package/dist/connectors/github/scope.d.ts.map +1 -0
- package/dist/connectors/github/scope.js +13 -0
- package/dist/connectors/github/scope.js.map +1 -0
- package/dist/connectors/github/signature.d.ts +47 -0
- package/dist/connectors/github/signature.d.ts.map +1 -0
- package/dist/connectors/github/signature.js +58 -0
- package/dist/connectors/github/signature.js.map +1 -0
- package/dist/connectors/github/tenant-routing.d.ts +33 -0
- package/dist/connectors/github/tenant-routing.d.ts.map +1 -0
- package/dist/connectors/github/tenant-routing.js +61 -0
- package/dist/connectors/github/tenant-routing.js.map +1 -0
- package/dist/connectors/github/transform.d.ts +7 -0
- package/dist/connectors/github/transform.d.ts.map +1 -0
- package/dist/connectors/github/transform.js +103 -0
- package/dist/connectors/github/transform.js.map +1 -0
- package/dist/connectors/github/types.d.ts +87 -0
- package/dist/connectors/github/types.d.ts.map +1 -0
- package/dist/connectors/github/types.js +94 -0
- package/dist/connectors/github/types.js.map +1 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +94 -1
- package/dist/db.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +5 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +313 -2
- package/dist/server.js.map +1 -1
- package/dist/src/cli.js +10 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/connectors/github/backfill.js +272 -0
- package/dist/src/connectors/github/backfill.js.map +1 -0
- package/dist/src/connectors/github/cli-impl.js +192 -0
- package/dist/src/connectors/github/cli-impl.js.map +1 -0
- package/dist/src/connectors/github/deletion.js +83 -0
- package/dist/src/connectors/github/deletion.js.map +1 -0
- package/dist/src/connectors/github/dlq.js +182 -0
- package/dist/src/connectors/github/dlq.js.map +1 -0
- package/dist/src/connectors/github/idempotency.js +25 -0
- package/dist/src/connectors/github/idempotency.js.map +1 -0
- package/dist/src/connectors/github/ingest.js +138 -0
- package/dist/src/connectors/github/ingest.js.map +1 -0
- package/dist/src/connectors/github/octokit-client.js +65 -0
- package/dist/src/connectors/github/octokit-client.js.map +1 -0
- package/dist/src/connectors/github/ratelimit.js +31 -0
- package/dist/src/connectors/github/ratelimit.js.map +1 -0
- package/dist/src/connectors/github/scope.js +13 -0
- package/dist/src/connectors/github/scope.js.map +1 -0
- package/dist/src/connectors/github/signature.js +58 -0
- package/dist/src/connectors/github/signature.js.map +1 -0
- package/dist/src/connectors/github/tenant-routing.js +61 -0
- package/dist/src/connectors/github/tenant-routing.js.map +1 -0
- package/dist/src/connectors/github/transform.js +103 -0
- package/dist/src/connectors/github/transform.js.map +1 -0
- package/dist/src/connectors/github/types.js +94 -0
- package/dist/src/connectors/github/types.js.map +1 -0
- package/dist/src/db.js +94 -1
- package/dist/src/db.js.map +1 -1
- package/dist/src/mcp/server.js +5 -4
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/server.js +313 -2
- package/dist/src/server.js.map +1 -1
- package/dist/src/version.js +35 -0
- package/dist/src/version.js.map +1 -0
- package/dist/version.d.ts +25 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +35 -0
- package/dist/version.js.map +1 -0
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paginated backfill of three GitHub REST streams with per-stream
|
|
3
|
+
* high-water marks (HWMs):
|
|
4
|
+
* - /repos/{repo}/issues -> issues_hwm
|
|
5
|
+
* - /repos/{repo}/issues/comments -> issue_comments_hwm
|
|
6
|
+
* - /repos/{repo}/pulls/comments -> pr_review_comments_hwm
|
|
7
|
+
*
|
|
8
|
+
* Crash safety (codex P1 #3): each stream's HWM is persisted ONLY after
|
|
9
|
+
* the stream fully drains. If stream 2 throws mid-flight, stream 1's HWM
|
|
10
|
+
* is committed and stream 2's stays NULL (or its prior value). Rerun
|
|
11
|
+
* picks up from stream 1's saved HWM and re-fetches stream 2 from its
|
|
12
|
+
* last committed point.
|
|
13
|
+
*
|
|
14
|
+
* Codex P1 #2: the /issues endpoint returns BOTH issues and PRs (a PR is
|
|
15
|
+
* an issue with a `pull_request` field). We skip PRs here so they don't
|
|
16
|
+
* get ingested under the issues schema. PRs are handled via webhook in
|
|
17
|
+
* V1 (no /pulls backfill stream — review comments cover the discussion
|
|
18
|
+
* surface).
|
|
19
|
+
*
|
|
20
|
+
* Privacy (V1 limitation): the REST list endpoints don't reliably set
|
|
21
|
+
* `repository.private`, and resolving it requires an extra API call per
|
|
22
|
+
* repo. Backfill leaves the field undefined so scopeFromRepository falls
|
|
23
|
+
* through to private. Callers who know the repo is public can re-tag
|
|
24
|
+
* downstream; the fail-safe default protects private orgs.
|
|
25
|
+
*/
|
|
26
|
+
import { openHippoDb, closeHippoDb } from '../../db.js';
|
|
27
|
+
import { ingestEvent } from './ingest.js';
|
|
28
|
+
const API = 'https://api.github.com';
|
|
29
|
+
function readCursor(root, tenantId, repo) {
|
|
30
|
+
const db = openHippoDb(root);
|
|
31
|
+
try {
|
|
32
|
+
const row = db
|
|
33
|
+
.prepare(`SELECT issues_hwm, issue_comments_hwm, pr_review_comments_hwm
|
|
34
|
+
FROM github_cursors WHERE tenant_id = ? AND repo_full_name = ?`)
|
|
35
|
+
.get(tenantId, repo);
|
|
36
|
+
return {
|
|
37
|
+
issues: row?.issues_hwm ?? null,
|
|
38
|
+
issueComments: row?.issue_comments_hwm ?? null,
|
|
39
|
+
prReviewComments: row?.pr_review_comments_hwm ?? null,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
closeHippoDb(db);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function writeOneHwm(root, tenantId, repo, column, value) {
|
|
47
|
+
const db = openHippoDb(root);
|
|
48
|
+
try {
|
|
49
|
+
db.prepare(`INSERT INTO github_cursors (tenant_id, repo_full_name, ${column}, updated_at)
|
|
50
|
+
VALUES (?, ?, ?, ?)
|
|
51
|
+
ON CONFLICT(tenant_id, repo_full_name)
|
|
52
|
+
DO UPDATE SET ${column} = excluded.${column}, updated_at = excluded.updated_at`).run(tenantId, repo, value, new Date().toISOString());
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
closeHippoDb(db);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build a synthetic `repository` object from the known repo full name.
|
|
60
|
+
* REST list endpoints often omit the full repository object on each item;
|
|
61
|
+
* we already know the repo since the caller passed it. `private` left
|
|
62
|
+
* undefined so scopeFromRepository falls through to private.
|
|
63
|
+
*/
|
|
64
|
+
function syntheticRepository(repoFullName) {
|
|
65
|
+
const [owner, name] = repoFullName.split('/');
|
|
66
|
+
return {
|
|
67
|
+
full_name: repoFullName,
|
|
68
|
+
name: name ?? repoFullName,
|
|
69
|
+
owner: { login: owner ?? repoFullName },
|
|
70
|
+
// private intentionally omitted — fail-safe to private scope.
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Parse the trailing issue/PR number from a REST API URL.
|
|
75
|
+
* e.g. https://api.github.com/repos/o/r/issues/42 -> 42
|
|
76
|
+
* https://api.github.com/repos/o/r/pulls/7 -> 7
|
|
77
|
+
*/
|
|
78
|
+
function parseTrailingNumber(url) {
|
|
79
|
+
if (!url)
|
|
80
|
+
return null;
|
|
81
|
+
const m = url.match(/\/(\d+)(?:\?.*)?$/);
|
|
82
|
+
if (!m)
|
|
83
|
+
return null;
|
|
84
|
+
const n = Number(m[1]);
|
|
85
|
+
return Number.isFinite(n) ? n : null;
|
|
86
|
+
}
|
|
87
|
+
function isIssuesItem(x) {
|
|
88
|
+
if (!x || typeof x !== 'object')
|
|
89
|
+
return false;
|
|
90
|
+
const o = x;
|
|
91
|
+
if (typeof o.number !== 'number')
|
|
92
|
+
return false;
|
|
93
|
+
if (typeof o.title !== 'string')
|
|
94
|
+
return false;
|
|
95
|
+
const u = o.user;
|
|
96
|
+
if (!u || typeof u.login !== 'string' || typeof u.id !== 'number')
|
|
97
|
+
return false;
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
function isCommentItem(x) {
|
|
101
|
+
if (!x || typeof x !== 'object')
|
|
102
|
+
return false;
|
|
103
|
+
const o = x;
|
|
104
|
+
if (typeof o.id !== 'number')
|
|
105
|
+
return false;
|
|
106
|
+
const u = o.user;
|
|
107
|
+
if (!u || typeof u.login !== 'string' || typeof u.id !== 'number')
|
|
108
|
+
return false;
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Drain one stream end-to-end. Pauses and retries on rate-limit. Throws on
|
|
113
|
+
* any other fetch error so the caller leaves the HWM unchanged (round 1
|
|
114
|
+
* codex P1 #3 crash safety).
|
|
115
|
+
*
|
|
116
|
+
* v1.3.1 (round 2 codex P1s + claude P1):
|
|
117
|
+
* - Tracks max(updated_at) across ALL fetched items, including ones
|
|
118
|
+
* `toIngestEvent` rejects (e.g., PRs returned via `/issues`). Otherwise
|
|
119
|
+
* a page of pure PRs would never advance the HWM and the next run would
|
|
120
|
+
* re-fetch the same window forever.
|
|
121
|
+
* - Returns `drained: boolean` — true only when the stream actually ran
|
|
122
|
+
* to next=null. Callers MUST NOT advance the HWM when drained=false.
|
|
123
|
+
* Was a bug in v1.3.0: hitting maxPerStream cap returned the partial
|
|
124
|
+
* maxUpdatedAt and the caller persisted it, skipping the unfetched tail.
|
|
125
|
+
*/
|
|
126
|
+
async function drainStream(ctx, url0, toIngestEvent, fetcher, token, sleep, maxItems) {
|
|
127
|
+
let url = url0;
|
|
128
|
+
let ingested = 0;
|
|
129
|
+
let pages = 0;
|
|
130
|
+
let maxUpdatedAt = null;
|
|
131
|
+
while (url) {
|
|
132
|
+
// Fetch with rate-limit retry loop.
|
|
133
|
+
let page;
|
|
134
|
+
while (true) {
|
|
135
|
+
page = await fetcher({ url, token });
|
|
136
|
+
if (page.rateLimit.reason !== 'none') {
|
|
137
|
+
await sleep(page.rateLimit.sleepSeconds * 1000);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
pages++;
|
|
143
|
+
for (const item of page.items) {
|
|
144
|
+
// v1.3.1: track updated_at on EVERY item, before the toIngestEvent
|
|
145
|
+
// filter. Skipped PRs from /issues still contribute to the HWM so
|
|
146
|
+
// PR-only pages don't loop forever.
|
|
147
|
+
const updatedAt = item && typeof item === 'object'
|
|
148
|
+
? (item.updated_at ?? null)
|
|
149
|
+
: null;
|
|
150
|
+
if (updatedAt && (!maxUpdatedAt || updatedAt > maxUpdatedAt)) {
|
|
151
|
+
maxUpdatedAt = updatedAt;
|
|
152
|
+
}
|
|
153
|
+
const evt = toIngestEvent(item);
|
|
154
|
+
if (!evt)
|
|
155
|
+
continue;
|
|
156
|
+
const r = ingestEvent(ctx, {
|
|
157
|
+
event: evt,
|
|
158
|
+
rawBody: JSON.stringify(item),
|
|
159
|
+
deliveryId: `backfill:${ctx.tenantId}:${updatedAt ?? ''}`,
|
|
160
|
+
});
|
|
161
|
+
if (r.status === 'ingested' || r.status === 'skipped')
|
|
162
|
+
ingested++;
|
|
163
|
+
if (maxItems && ingested >= maxItems) {
|
|
164
|
+
// Capped mid-stream: caller MUST NOT advance the HWM (drained=false).
|
|
165
|
+
return { ingested, pages, maxUpdatedAt, drained: false };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
url = page.next;
|
|
169
|
+
}
|
|
170
|
+
return { ingested, pages, maxUpdatedAt, drained: true };
|
|
171
|
+
}
|
|
172
|
+
export async function backfillRepo(ctx, opts) {
|
|
173
|
+
const sleep = opts.sleepMs ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
174
|
+
const cursors = readCursor(ctx.hippoRoot, ctx.tenantId, opts.repoFullName);
|
|
175
|
+
const repository = syntheticRepository(opts.repoFullName);
|
|
176
|
+
const result = {
|
|
177
|
+
ingested: { issues: 0, issueComments: 0, prReviewComments: 0 },
|
|
178
|
+
pages: { issues: 0, issueComments: 0, prReviewComments: 0 },
|
|
179
|
+
};
|
|
180
|
+
// ---------- Stream 1: issues (skip PRs) ----------
|
|
181
|
+
const issuesUrl = `${API}/repos/${opts.repoFullName}/issues?state=all&per_page=100` +
|
|
182
|
+
(cursors.issues ? `&since=${encodeURIComponent(cursors.issues)}` : '');
|
|
183
|
+
const issuesRes = await drainStream(ctx, issuesUrl, (item) => {
|
|
184
|
+
if (!isIssuesItem(item))
|
|
185
|
+
return null;
|
|
186
|
+
// Codex P1 #2: /issues returns PRs too — skip them.
|
|
187
|
+
if (item.pull_request)
|
|
188
|
+
return null;
|
|
189
|
+
const payload = {
|
|
190
|
+
action: 'opened',
|
|
191
|
+
repository,
|
|
192
|
+
issue: {
|
|
193
|
+
number: item.number,
|
|
194
|
+
title: item.title,
|
|
195
|
+
body: item.body ?? null,
|
|
196
|
+
user: { login: item.user.login, id: item.user.id },
|
|
197
|
+
updated_at: item.updated_at,
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
return { eventName: 'issues', payload };
|
|
201
|
+
}, opts.fetcher, opts.token, sleep, opts.maxPerStream);
|
|
202
|
+
result.ingested.issues = issuesRes.ingested;
|
|
203
|
+
result.pages.issues = issuesRes.pages;
|
|
204
|
+
// v1.3.1: only advance HWM when the stream actually drained. A capped run
|
|
205
|
+
// (--max) must leave the HWM at its previous value so the next invocation
|
|
206
|
+
// re-fetches the unprocessed tail.
|
|
207
|
+
if (issuesRes.drained && issuesRes.maxUpdatedAt) {
|
|
208
|
+
writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, 'issues_hwm', issuesRes.maxUpdatedAt);
|
|
209
|
+
}
|
|
210
|
+
// ---------- Stream 2: repo-level issue comments ----------
|
|
211
|
+
const commentsUrl = `${API}/repos/${opts.repoFullName}/issues/comments?per_page=100` +
|
|
212
|
+
(cursors.issueComments
|
|
213
|
+
? `&since=${encodeURIComponent(cursors.issueComments)}`
|
|
214
|
+
: '');
|
|
215
|
+
const commentsRes = await drainStream(ctx, commentsUrl, (item) => {
|
|
216
|
+
if (!isCommentItem(item))
|
|
217
|
+
return null;
|
|
218
|
+
const c = item;
|
|
219
|
+
const issueNumber = parseTrailingNumber(c.issue_url);
|
|
220
|
+
if (issueNumber === null)
|
|
221
|
+
return null;
|
|
222
|
+
const payload = {
|
|
223
|
+
action: 'created',
|
|
224
|
+
repository,
|
|
225
|
+
issue: { number: issueNumber },
|
|
226
|
+
comment: {
|
|
227
|
+
id: c.id,
|
|
228
|
+
body: c.body ?? null,
|
|
229
|
+
user: { login: c.user.login, id: c.user.id },
|
|
230
|
+
updated_at: c.updated_at,
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
return { eventName: 'issue_comment', payload };
|
|
234
|
+
}, opts.fetcher, opts.token, sleep, opts.maxPerStream);
|
|
235
|
+
result.ingested.issueComments = commentsRes.ingested;
|
|
236
|
+
result.pages.issueComments = commentsRes.pages;
|
|
237
|
+
if (commentsRes.drained && commentsRes.maxUpdatedAt) {
|
|
238
|
+
writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, 'issue_comments_hwm', commentsRes.maxUpdatedAt);
|
|
239
|
+
}
|
|
240
|
+
// ---------- Stream 3: repo-level PR review comments ----------
|
|
241
|
+
const prCommentsUrl = `${API}/repos/${opts.repoFullName}/pulls/comments?per_page=100` +
|
|
242
|
+
(cursors.prReviewComments
|
|
243
|
+
? `&since=${encodeURIComponent(cursors.prReviewComments)}`
|
|
244
|
+
: '');
|
|
245
|
+
const prCommentsRes = await drainStream(ctx, prCommentsUrl, (item) => {
|
|
246
|
+
if (!isCommentItem(item))
|
|
247
|
+
return null;
|
|
248
|
+
const c = item;
|
|
249
|
+
const prNumber = parseTrailingNumber(c.pull_request_url);
|
|
250
|
+
if (prNumber === null)
|
|
251
|
+
return null;
|
|
252
|
+
const payload = {
|
|
253
|
+
action: 'created',
|
|
254
|
+
repository,
|
|
255
|
+
pull_request: { number: prNumber },
|
|
256
|
+
comment: {
|
|
257
|
+
id: c.id,
|
|
258
|
+
body: c.body ?? null,
|
|
259
|
+
user: { login: c.user.login, id: c.user.id },
|
|
260
|
+
updated_at: c.updated_at,
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
return { eventName: 'pull_request_review_comment', payload };
|
|
264
|
+
}, opts.fetcher, opts.token, sleep, opts.maxPerStream);
|
|
265
|
+
result.ingested.prReviewComments = prCommentsRes.ingested;
|
|
266
|
+
result.pages.prReviewComments = prCommentsRes.pages;
|
|
267
|
+
if (prCommentsRes.drained && prCommentsRes.maxUpdatedAt) {
|
|
268
|
+
writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, 'pr_review_comments_hwm', prCommentsRes.maxUpdatedAt);
|
|
269
|
+
}
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=backfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backfill.js","sourceRoot":"","sources":["../../../../src/connectors/github/backfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,WAAW,EAAoB,MAAM,aAAa,CAAC;AAU5D,MAAM,GAAG,GAAG,wBAAwB,CAAC;AAgCrC,SAAS,UAAU,CAAC,IAAY,EAAE,QAAgB,EAAE,IAAY;IAC9D,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE;aACX,OAAO,CACN;wEACgE,CACjE;aACA,GAAG,CAAC,QAAQ,EAAE,IAAI,CAMR,CAAC;QACd,OAAO;YACL,MAAM,EAAE,GAAG,EAAE,UAAU,IAAI,IAAI;YAC/B,aAAa,EAAE,GAAG,EAAE,kBAAkB,IAAI,IAAI;YAC9C,gBAAgB,EAAE,GAAG,EAAE,sBAAsB,IAAI,IAAI;SACtD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAClB,IAAY,EACZ,QAAgB,EAChB,IAAY,EACZ,MAAiB,EACjB,KAAa;IAEb,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC;QACH,EAAE,CAAC,OAAO,CACR,0DAA0D,MAAM;;;uBAG/C,MAAM,eAAe,MAAM,oCAAoC,CACjF,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACzD,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,YAAoB;IAC/C,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9C,OAAO;QACL,SAAS,EAAE,YAAY;QACvB,IAAI,EAAE,IAAI,IAAI,YAAY;QAC1B,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,IAAI,YAAY,EAAE;QACvC,8DAA8D;KAC/D,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,GAAuB;IAClD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACzC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC;AA2BD,SAAS,YAAY,CAAC,CAAU;IAC9B,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAqD,CAAC;IAClE,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAChF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,CAAU;IAC/B,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAqD,CAAC;IAClE,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAChF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,KAAK,UAAU,WAAW,CACxB,GAAY,EACZ,IAAY,EACZ,aAAoD,EACpD,OAAsB,EACtB,KAAa,EACb,KAAoC,EACpC,QAAiB;IAEjB,IAAI,GAAG,GAAkB,IAAI,CAAC;IAC9B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,YAAY,GAAkB,IAAI,CAAC;IAEvC,OAAO,GAAG,EAAE,CAAC;QACX,oCAAoC;QACpC,IAAI,IAAwB,CAAC;QAC7B,OAAO,IAAI,EAAE,CAAC;YACZ,IAAI,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;YACrC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBACrC,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;gBAChD,SAAS;YACX,CAAC;YACD,MAAM;QACR,CAAC;QACD,KAAK,EAAE,CAAC;QAER,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,mEAAmE;YACnE,kEAAkE;YAClE,oCAAoC;YACpC,MAAM,SAAS,GACb,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAC9B,CAAC,CAAC,CAAE,IAAgC,CAAC,UAAU,IAAI,IAAI,CAAC;gBACxD,CAAC,CAAC,IAAI,CAAC;YACX,IAAI,SAAS,IAAI,CAAC,CAAC,YAAY,IAAI,SAAS,GAAG,YAAY,CAAC,EAAE,CAAC;gBAC7D,YAAY,GAAG,SAAS,CAAC;YAC3B,CAAC;YAED,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE;gBACzB,KAAK,EAAE,GAAG;gBACV,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC7B,UAAU,EAAE,YAAY,GAAG,CAAC,QAAQ,IAAI,SAAS,IAAI,EAAE,EAAE;aAC1D,CAAC,CAAC;YACH,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;gBAAE,QAAQ,EAAE,CAAC;YAElE,IAAI,QAAQ,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;gBACrC,sEAAsE;gBACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC3D,CAAC;QACH,CAAC;QAED,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAY,EACZ,IAAkB;IAElB,MAAM,KAAK,GACT,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAChF,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3E,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAE1D,MAAM,MAAM,GAAmB;QAC7B,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE;QAC9D,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE;KAC5D,CAAC;IAEF,oDAAoD;IACpD,MAAM,SAAS,GACb,GAAG,GAAG,UAAU,IAAI,CAAC,YAAY,gCAAgC;QACjE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,MAAM,WAAW,CACjC,GAAG,EACH,SAAS,EACT,CAAC,IAAI,EAAE,EAAE;QACP,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACrC,oDAAoD;QACpD,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,OAAO,GAAqB;YAChC,MAAM,EAAE,QAAQ;YAChB,UAAU;YACV,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI;gBACvB,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;gBAClD,UAAU,EAAE,IAAI,CAAC,UAAU;aAC5B;SACF,CAAC;QACF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC1C,CAAC,EACD,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,KAAK,EACV,KAAK,EACL,IAAI,CAAC,YAAY,CAClB,CAAC;IACF,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC;IAC5C,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC;IACtC,0EAA0E;IAC1E,0EAA0E;IAC1E,mCAAmC;IACnC,IAAI,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,YAAY,EAAE,CAAC;QAChD,WAAW,CACT,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,QAAQ,EACZ,IAAI,CAAC,YAAY,EACjB,YAAY,EACZ,SAAS,CAAC,YAAY,CACvB,CAAC;IACJ,CAAC;IAED,4DAA4D;IAC5D,MAAM,WAAW,GACf,GAAG,GAAG,UAAU,IAAI,CAAC,YAAY,+BAA+B;QAChE,CAAC,OAAO,CAAC,aAAa;YACpB,CAAC,CAAC,UAAU,kBAAkB,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE;YACvD,CAAC,CAAC,EAAE,CAAC,CAAC;IACV,MAAM,WAAW,GAAG,MAAM,WAAW,CACnC,GAAG,EACH,WAAW,EACX,CAAC,IAAI,EAAE,EAAE;QACP,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,MAAM,CAAC,GAAG,IAAwB,CAAC;QACnC,MAAM,WAAW,GAAG,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACrD,IAAI,WAAW,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACtC,MAAM,OAAO,GAA4B;YACvC,MAAM,EAAE,SAAS;YACjB,UAAU;YACV,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE;YAC9B,OAAO,EAAE;gBACP,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI;gBACpB,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE;gBAC5C,UAAU,EAAE,CAAC,CAAC,UAAU;aACzB;SACF,CAAC;QACF,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC;IACjD,CAAC,EACD,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,KAAK,EACV,KAAK,EACL,IAAI,CAAC,YAAY,CAClB,CAAC;IACF,MAAM,CAAC,QAAQ,CAAC,aAAa,GAAG,WAAW,CAAC,QAAQ,CAAC;IACrD,MAAM,CAAC,KAAK,CAAC,aAAa,GAAG,WAAW,CAAC,KAAK,CAAC;IAC/C,IAAI,WAAW,CAAC,OAAO,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;QACpD,WAAW,CACT,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,QAAQ,EACZ,IAAI,CAAC,YAAY,EACjB,oBAAoB,EACpB,WAAW,CAAC,YAAY,CACzB,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,MAAM,aAAa,GACjB,GAAG,GAAG,UAAU,IAAI,CAAC,YAAY,8BAA8B;QAC/D,CAAC,OAAO,CAAC,gBAAgB;YACvB,CAAC,CAAC,UAAU,kBAAkB,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE;YAC1D,CAAC,CAAC,EAAE,CAAC,CAAC;IACV,MAAM,aAAa,GAAG,MAAM,WAAW,CACrC,GAAG,EACH,aAAa,EACb,CAAC,IAAI,EAAE,EAAE;QACP,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,MAAM,CAAC,GAAG,IAA2B,CAAC;QACtC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;QACzD,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,OAAO,GAAwC;YACnD,MAAM,EAAE,SAAS;YACjB,UAAU;YACV,YAAY,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;YAClC,OAAO,EAAE;gBACP,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI;gBACpB,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE;gBAC5C,UAAU,EAAE,CAAC,CAAC,UAAU;aACzB;SACF,CAAC;QACF,OAAO,EAAE,SAAS,EAAE,6BAA6B,EAAE,OAAO,EAAE,CAAC;IAC/D,CAAC,EACD,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,KAAK,EACV,KAAK,EACL,IAAI,CAAC,YAAY,CAClB,CAAC;IACF,MAAM,CAAC,QAAQ,CAAC,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAC1D,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,aAAa,CAAC,KAAK,CAAC;IACpD,IAAI,aAAa,CAAC,OAAO,IAAI,aAAa,CAAC,YAAY,EAAE,CAAC;QACxD,WAAW,CACT,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,QAAQ,EACZ,IAAI,CAAC,YAAY,EACjB,wBAAwB,EACxB,aAAa,CAAC,YAAY,CAC3B,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Implementation of `hippo github` CLI subcommands. Extracted from the main
|
|
3
|
+
* cli.ts so unit tests can import these functions directly without triggering
|
|
4
|
+
* the cli.ts main() side effects. The cli.ts dispatcher re-exports the
|
|
5
|
+
* top-level cmdGithub.
|
|
6
|
+
*
|
|
7
|
+
* Subcommands mirror the Slack connector shape (cli.ts §Slack subcommands):
|
|
8
|
+
* - hippo github backfill --repo <owner/name> [--since ISO] [--max <N>]
|
|
9
|
+
* - hippo github dlq list
|
|
10
|
+
* - hippo github dlq replay <id> [--force]
|
|
11
|
+
*/
|
|
12
|
+
import { openHippoDb, closeHippoDb } from '../../db.js';
|
|
13
|
+
import { resolveTenantId } from '../../tenant.js';
|
|
14
|
+
import { backfillRepo } from './backfill.js';
|
|
15
|
+
import { realGitHubFetcher } from './octokit-client.js';
|
|
16
|
+
import { listDlq, replayDlqEntry } from './dlq.js';
|
|
17
|
+
import { ingestEvent } from './ingest.js';
|
|
18
|
+
import { isGitHubIssueEvent, isGitHubIssueCommentEvent, isGitHubPullRequestEvent, isGitHubPullRequestReviewCommentEvent, } from './types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Map a parsed envelope + eventName header to an IngestEvent discriminated
|
|
21
|
+
* union. Returns null for unknown event types or shapes that don't pass the
|
|
22
|
+
* type guards.
|
|
23
|
+
*/
|
|
24
|
+
function parsedToIngestEvent(parsed, eventName) {
|
|
25
|
+
if (eventName === 'issues' && isGitHubIssueEvent(parsed, eventName)) {
|
|
26
|
+
return { eventName: 'issues', payload: parsed };
|
|
27
|
+
}
|
|
28
|
+
if (eventName === 'issue_comment' && isGitHubIssueCommentEvent(parsed, eventName)) {
|
|
29
|
+
return { eventName: 'issue_comment', payload: parsed };
|
|
30
|
+
}
|
|
31
|
+
if (eventName === 'pull_request' && isGitHubPullRequestEvent(parsed, eventName)) {
|
|
32
|
+
return { eventName: 'pull_request', payload: parsed };
|
|
33
|
+
}
|
|
34
|
+
if (eventName === 'pull_request_review_comment' &&
|
|
35
|
+
isGitHubPullRequestReviewCommentEvent(parsed, eventName)) {
|
|
36
|
+
return { eventName: 'pull_request_review_comment', payload: parsed };
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
export function printGithubBackfillUsage() {
|
|
41
|
+
console.log('hippo github backfill --repo <owner/name> [--since ISO] [--max <N>]');
|
|
42
|
+
console.log(' --repo GitHub repository in owner/name format (required, e.g. acme/widgets)');
|
|
43
|
+
console.log(' --since Initial high-water-mark for first run (optional, ISO 8601)');
|
|
44
|
+
console.log(' --max Cap items per stream (optional, integer)');
|
|
45
|
+
console.log(' Requires GITHUB_TOKEN env var with repo read scope.');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `hippo github backfill`. The fetcher is injectable so tests can drive the
|
|
49
|
+
* code path without hitting the network. Defaults to `realGitHubFetcher`.
|
|
50
|
+
*/
|
|
51
|
+
export async function cmdGithubBackfill(hippoRoot, flags, fetcher = realGitHubFetcher) {
|
|
52
|
+
if (flags['help']) {
|
|
53
|
+
printGithubBackfillUsage();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const repo = flags['repo'];
|
|
57
|
+
if (typeof repo !== 'string' || !repo.includes('/')) {
|
|
58
|
+
printGithubBackfillUsage();
|
|
59
|
+
process.exit(2);
|
|
60
|
+
}
|
|
61
|
+
const token = process.env.GITHUB_TOKEN;
|
|
62
|
+
if (!token) {
|
|
63
|
+
console.error('GITHUB_TOKEN is not set. Backfill requires a personal access token with repo read scope.');
|
|
64
|
+
process.exit(2);
|
|
65
|
+
}
|
|
66
|
+
const maxRaw = flags['max'];
|
|
67
|
+
let maxPerStream;
|
|
68
|
+
if (typeof maxRaw === 'string' || typeof maxRaw === 'number') {
|
|
69
|
+
const parsed = Number(maxRaw);
|
|
70
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
71
|
+
maxPerStream = Math.floor(parsed);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const sinceIso = typeof flags['since'] === 'string' ? flags['since'] : undefined;
|
|
75
|
+
const tenantId = resolveTenantId({});
|
|
76
|
+
// Seed the github_cursors row so all 3 streams use --since on a fresh run.
|
|
77
|
+
// COALESCE preserves any existing HWM (subsequent runs ignore --since for
|
|
78
|
+
// streams that already drained at least once — same idempotency story as
|
|
79
|
+
// Slack's slack_cursors).
|
|
80
|
+
if (sinceIso) {
|
|
81
|
+
const db = openHippoDb(hippoRoot);
|
|
82
|
+
try {
|
|
83
|
+
db.prepare(`INSERT INTO github_cursors (tenant_id, repo_full_name, issues_hwm, issue_comments_hwm, pr_review_comments_hwm, updated_at)
|
|
84
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
85
|
+
ON CONFLICT(tenant_id, repo_full_name) DO UPDATE SET
|
|
86
|
+
issues_hwm = COALESCE(github_cursors.issues_hwm, excluded.issues_hwm),
|
|
87
|
+
issue_comments_hwm = COALESCE(github_cursors.issue_comments_hwm, excluded.issue_comments_hwm),
|
|
88
|
+
pr_review_comments_hwm = COALESCE(github_cursors.pr_review_comments_hwm, excluded.pr_review_comments_hwm),
|
|
89
|
+
updated_at = excluded.updated_at`).run(tenantId, repo, sinceIso, sinceIso, sinceIso, new Date().toISOString());
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
closeHippoDb(db);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const ctx = {
|
|
96
|
+
hippoRoot,
|
|
97
|
+
tenantId,
|
|
98
|
+
actor: 'cli:github-backfill',
|
|
99
|
+
};
|
|
100
|
+
try {
|
|
101
|
+
const result = await backfillRepo(ctx, {
|
|
102
|
+
repoFullName: repo,
|
|
103
|
+
fetcher,
|
|
104
|
+
token: token,
|
|
105
|
+
maxPerStream,
|
|
106
|
+
});
|
|
107
|
+
console.log(JSON.stringify(result, null, 2));
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
console.error('backfill failed:', e.message);
|
|
111
|
+
process.exit(3);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export function cmdGithubDlqList(hippoRoot, _flags) {
|
|
115
|
+
const db = openHippoDb(hippoRoot);
|
|
116
|
+
try {
|
|
117
|
+
const tenantId = resolveTenantId({});
|
|
118
|
+
const items = listDlq(db, { tenantId });
|
|
119
|
+
if (items.length === 0) {
|
|
120
|
+
console.log('no entries');
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
for (const it of items) {
|
|
124
|
+
console.log(`${it.id}\t${it.bucket}\t${it.tenantId}\t${it.eventName ?? '-'}\t${it.receivedAt}\t${it.error}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
closeHippoDb(db);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export async function cmdGithubDlqReplay(hippoRoot, args, flags) {
|
|
132
|
+
const idArg = args[0];
|
|
133
|
+
if (!idArg) {
|
|
134
|
+
console.error('Usage: hippo github dlq replay <id> [--force]');
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
const id = Number(idArg);
|
|
138
|
+
if (!Number.isFinite(id) || !Number.isInteger(id) || id < 1) {
|
|
139
|
+
console.error(`replay: invalid id ${idArg}`);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
const force = flags['force'] === true;
|
|
143
|
+
const ctx = {
|
|
144
|
+
hippoRoot,
|
|
145
|
+
tenantId: resolveTenantId({}),
|
|
146
|
+
actor: 'cli:github-dlq-replay',
|
|
147
|
+
};
|
|
148
|
+
// v1.3.1 hotfix (codex P1): without an ingestHook the v1.3.0 CLI was a
|
|
149
|
+
// dry-run that printed "replay ok" while only bumping retry_count. Wire the
|
|
150
|
+
// real hook so `replay` actually re-runs the ingest path.
|
|
151
|
+
const result = await replayDlqEntry(ctx, id, {
|
|
152
|
+
force,
|
|
153
|
+
webhookSecret: process.env.GITHUB_WEBHOOK_SECRET,
|
|
154
|
+
previousSecret: process.env.GITHUB_WEBHOOK_SECRET_PREVIOUS,
|
|
155
|
+
ingestHook: async (innerCtx, args) => {
|
|
156
|
+
const parsed = JSON.parse(args.rawPayload);
|
|
157
|
+
const event = parsedToIngestEvent(parsed, args.eventName);
|
|
158
|
+
if (!event) {
|
|
159
|
+
return { memoryId: null };
|
|
160
|
+
}
|
|
161
|
+
const r = ingestEvent(innerCtx, {
|
|
162
|
+
event,
|
|
163
|
+
rawBody: args.rawPayload,
|
|
164
|
+
deliveryId: args.deliveryId,
|
|
165
|
+
});
|
|
166
|
+
return { memoryId: r.memoryId };
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
if (!result.ok) {
|
|
170
|
+
console.error(`replay failed: status=${result.status} retry_count=${result.retryCount}${result.reason ? ` reason=${result.reason}` : ''}`);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
console.log(`replay ok: status=${result.status} memory_id=${result.memoryId ?? '(none)'} retry_count=${result.retryCount}`);
|
|
174
|
+
}
|
|
175
|
+
export async function cmdGithub(hippoRoot, args, flags) {
|
|
176
|
+
const sub = args[0];
|
|
177
|
+
if (sub === 'backfill') {
|
|
178
|
+
await cmdGithubBackfill(hippoRoot, flags);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (sub === 'dlq' && args[1] === 'list') {
|
|
182
|
+
cmdGithubDlqList(hippoRoot, flags);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (sub === 'dlq' && args[1] === 'replay') {
|
|
186
|
+
await cmdGithubDlqReplay(hippoRoot, args.slice(2), flags);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
console.error('Usage: hippo github <backfill|dlq list|dlq replay <id> [--force]> [...]');
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=cli-impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-impl.js","sourceRoot":"","sources":["../../../../src/connectors/github/cli-impl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { openHippoDb, closeHippoDb } from '../../db.js';
|
|
2
|
+
import { archiveRawMemory } from '../../raw-archive.js';
|
|
3
|
+
import { hasSeenKey, markKeySeen } from './idempotency.js';
|
|
4
|
+
/**
|
|
5
|
+
* Handle GitHub `issue_comment.deleted` and `pull_request_review_comment.deleted`.
|
|
6
|
+
*
|
|
7
|
+
* Codex round 1 P0 #5: filter by tenant_id + kind='raw'. Multi-row archive:
|
|
8
|
+
* GitHub edits keep the same artifact_ref, so multiple active raw rows can
|
|
9
|
+
* match a single deletion event. Archive ALL of them.
|
|
10
|
+
*
|
|
11
|
+
* Claude round 2 P0 #2 (v1.3.1 hotfix): the v1.3.0 implementation called
|
|
12
|
+
* archiveRaw N times in a loop, each opening its own DB handle and SAVEPOINT.
|
|
13
|
+
* The first archive's afterArchive committed the idempotency mark. If archive
|
|
14
|
+
* 2..N threw, idempotency was already committed and retry returned 'duplicate'
|
|
15
|
+
* with archivedCount=0 — survivors stayed searchable, leaking private bodies.
|
|
16
|
+
*
|
|
17
|
+
* v1.3.1 fix: ONE shared DB handle wrapping ALL archives + the idempotency
|
|
18
|
+
* mark in a single outer SAVEPOINT. Any per-row failure rolls back the entire
|
|
19
|
+
* batch (including idempotency), so retry re-attempts cleanly. archiveRawMemory
|
|
20
|
+
* (the lower-level function from raw-archive.js) runs its own inner SAVEPOINT
|
|
21
|
+
* which nests safely inside the outer one.
|
|
22
|
+
*
|
|
23
|
+
* Tenant scope and kind='raw' filtering are load-bearing: without them a
|
|
24
|
+
* deletion event from tenant A could archive tenant B's row sharing the same
|
|
25
|
+
* artifact_ref, or accidentally target a distilled row.
|
|
26
|
+
*/
|
|
27
|
+
export function handleCommentDeleted(ctx, input) {
|
|
28
|
+
const db = openHippoDb(ctx.hippoRoot);
|
|
29
|
+
try {
|
|
30
|
+
if (hasSeenKey(db, input.idempotencyKey)) {
|
|
31
|
+
return { status: 'duplicate', archivedCount: 0 };
|
|
32
|
+
}
|
|
33
|
+
const rows = db
|
|
34
|
+
.prepare(`SELECT id FROM memories WHERE artifact_ref = ? AND tenant_id = ? AND kind = 'raw'`)
|
|
35
|
+
.all(input.artifactRef, ctx.tenantId);
|
|
36
|
+
const memoryIds = rows.map((r) => r.id);
|
|
37
|
+
if (memoryIds.length === 0) {
|
|
38
|
+
// Nothing to archive — still mark idempotency so a retry returns 'duplicate'.
|
|
39
|
+
// Independent INSERT, no rollback needed.
|
|
40
|
+
markKeySeen(db, {
|
|
41
|
+
idempotencyKey: input.idempotencyKey,
|
|
42
|
+
deliveryId: input.deliveryId,
|
|
43
|
+
eventName: input.eventName,
|
|
44
|
+
memoryId: null,
|
|
45
|
+
});
|
|
46
|
+
return { status: 'archive_skipped_not_found', archivedCount: 0 };
|
|
47
|
+
}
|
|
48
|
+
// Outer SAVEPOINT wrapping all archives + the idempotency mark. Any throw
|
|
49
|
+
// rolls back the whole batch so retry sees neither archive nor mark — and
|
|
50
|
+
// re-attempts the full set.
|
|
51
|
+
db.exec('SAVEPOINT github_delete_all');
|
|
52
|
+
try {
|
|
53
|
+
for (const id of memoryIds) {
|
|
54
|
+
archiveRawMemory(db, id, {
|
|
55
|
+
reason: `source_deleted:github:${input.eventName}:${input.deliveryId}`,
|
|
56
|
+
who: ctx.actor || 'connector:github',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
markKeySeen(db, {
|
|
60
|
+
idempotencyKey: input.idempotencyKey,
|
|
61
|
+
deliveryId: input.deliveryId,
|
|
62
|
+
eventName: input.eventName,
|
|
63
|
+
memoryId: memoryIds[0],
|
|
64
|
+
});
|
|
65
|
+
db.exec('RELEASE SAVEPOINT github_delete_all');
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
try {
|
|
69
|
+
db.exec('ROLLBACK TO SAVEPOINT github_delete_all');
|
|
70
|
+
db.exec('RELEASE SAVEPOINT github_delete_all');
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Best effort. Surface the original error.
|
|
74
|
+
}
|
|
75
|
+
throw e;
|
|
76
|
+
}
|
|
77
|
+
return { status: 'archived', archivedCount: memoryIds.length };
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
closeHippoDb(db);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=deletion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deletion.js","sourceRoot":"","sources":["../../../../src/connectors/github/deletion.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAsB3D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY,EAAE,KAAoB;IACrE,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;YACzC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;QACnD,CAAC;QAED,MAAM,IAAI,GAAG,EAAE;aACZ,OAAO,CACN,mFAAmF,CACpF;aACA,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,QAAQ,CAA0B,CAAC;QACjE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAExC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,8EAA8E;YAC9E,0CAA0C;YAC1C,WAAW,CAAC,EAAE,EAAE;gBACd,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,2BAA2B,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;QACnE,CAAC;QAED,0EAA0E;QAC1E,0EAA0E;QAC1E,4BAA4B;QAC5B,EAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QACvC,IAAI,CAAC;YACH,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,gBAAgB,CAAC,EAAE,EAAE,EAAE,EAAE;oBACvB,MAAM,EAAE,yBAAyB,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,UAAU,EAAE;oBACtE,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,kBAAkB;iBACrC,CAAC,CAAC;YACL,CAAC;YACD,WAAW,CAAC,EAAE,EAAE;gBACd,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAE;aACxB,CAAC,CAAC;YACH,EAAE,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,EAAE,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;gBACnD,EAAE,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,2CAA2C;YAC7C,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;IACjE,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;AACH,CAAC"}
|