@polishd/next 0.2.3-dev.0 → 0.2.3-dev.2
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/AGENTS.md +1 -0
- package/CHANGELOG.md +144 -0
- package/README.md +34 -3
- package/dist/ai/digest.d.ts.map +1 -1
- package/dist/ai/digest.js +3 -2
- package/dist/ai/digest.js.map +1 -1
- package/dist/ai/github.d.ts +22 -1
- package/dist/ai/github.d.ts.map +1 -1
- package/dist/ai/github.js +99 -3
- package/dist/ai/github.js.map +1 -1
- package/dist/ai/issue-pages.d.ts +52 -0
- package/dist/ai/issue-pages.d.ts.map +1 -0
- package/dist/ai/issue-pages.js +50 -0
- package/dist/ai/issue-pages.js.map +1 -0
- package/dist/ai/issues.d.ts +13 -1
- package/dist/ai/issues.d.ts.map +1 -1
- package/dist/ai/issues.js +60 -4
- package/dist/ai/issues.js.map +1 -1
- package/dist/ai/summary.d.ts.map +1 -1
- package/dist/ai/summary.js +7 -0
- package/dist/ai/summary.js.map +1 -1
- package/dist/ai/types.d.ts +43 -0
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/client/dom.d.ts +23 -0
- package/dist/client/dom.d.ts.map +1 -1
- package/dist/client/dom.js +45 -2
- package/dist/client/dom.js.map +1 -1
- package/dist/client/init.d.ts.map +1 -1
- package/dist/client/init.js +15 -6
- package/dist/client/init.js.map +1 -1
- package/dist/client/monitor.d.ts.map +1 -1
- package/dist/client/monitor.js +5 -1
- package/dist/client/monitor.js.map +1 -1
- package/dist/dashboard/chrome.d.ts +4 -2
- package/dist/dashboard/chrome.d.ts.map +1 -1
- package/dist/dashboard/chrome.js +15 -5
- package/dist/dashboard/chrome.js.map +1 -1
- package/dist/dashboard/design.d.ts +3 -1
- package/dist/dashboard/design.d.ts.map +1 -1
- package/dist/dashboard/design.js +2 -2
- package/dist/dashboard/design.js.map +1 -1
- package/dist/dashboard/drawer.d.ts +34 -0
- package/dist/dashboard/drawer.d.ts.map +1 -0
- package/dist/dashboard/drawer.js +44 -0
- package/dist/dashboard/drawer.js.map +1 -0
- package/dist/dashboard/index.d.ts +3 -1
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +29 -23
- package/dist/dashboard/index.js.map +1 -1
- package/dist/dashboard/issues.d.ts +9 -0
- package/dist/dashboard/issues.d.ts.map +1 -0
- package/dist/dashboard/issues.js +81 -0
- package/dist/dashboard/issues.js.map +1 -0
- package/dist/dashboard/journeys.d.ts.map +1 -1
- package/dist/dashboard/journeys.js +1 -0
- package/dist/dashboard/journeys.js.map +1 -1
- package/dist/dashboard/metric-trends.d.ts +6 -0
- package/dist/dashboard/metric-trends.d.ts.map +1 -0
- package/dist/dashboard/metric-trends.js +236 -0
- package/dist/dashboard/metric-trends.js.map +1 -0
- package/dist/dashboard/pages.d.ts.map +1 -1
- package/dist/dashboard/pages.js +7 -45
- package/dist/dashboard/pages.js.map +1 -1
- package/dist/dashboard/snapshots.d.ts +8 -1
- package/dist/dashboard/snapshots.d.ts.map +1 -1
- package/dist/dashboard/snapshots.js +6 -4
- package/dist/dashboard/snapshots.js.map +1 -1
- package/dist/dashboard/telemetry.d.ts.map +1 -1
- package/dist/dashboard/telemetry.js +5 -4
- package/dist/dashboard/telemetry.js.map +1 -1
- package/dist/dashboard/ui.d.ts +33 -6
- package/dist/dashboard/ui.d.ts.map +1 -1
- package/dist/dashboard/ui.js +44 -6
- package/dist/dashboard/ui.js.map +1 -1
- package/dist/dashboard.css +114 -0
- package/dist/server/ingest.d.ts.map +1 -1
- package/dist/server/ingest.js +7 -0
- package/dist/server/ingest.js.map +1 -1
- package/dist/server/queries.d.ts +41 -0
- package/dist/server/queries.d.ts.map +1 -1
- package/dist/server/queries.js +109 -3
- package/dist/server/queries.js.map +1 -1
- package/dist/server/reclassify.d.ts +3 -0
- package/dist/server/reclassify.d.ts.map +1 -0
- package/dist/server/reclassify.js +65 -0
- package/dist/server/reclassify.js.map +1 -0
- package/dist/server/snapshots.d.ts +20 -2
- package/dist/server/snapshots.d.ts.map +1 -1
- package/dist/server/snapshots.js +216 -20
- package/dist/server/snapshots.js.map +1 -1
- package/dist/server/store.d.ts +5 -0
- package/dist/server/store.d.ts.map +1 -1
- package/dist/server/store.js +17 -0
- package/dist/server/store.js.map +1 -1
- package/dist/shared/metric-buckets.d.ts +31 -0
- package/dist/shared/metric-buckets.d.ts.map +1 -0
- package/dist/shared/metric-buckets.js +49 -0
- package/dist/shared/metric-buckets.js.map +1 -0
- package/dist/shared/text-signals.d.ts +56 -0
- package/dist/shared/text-signals.d.ts.map +1 -0
- package/dist/shared/text-signals.js +80 -0
- package/dist/shared/text-signals.js.map +1 -0
- package/dist/shared/types.d.ts +1 -1
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js.map +1 -1
- package/package.json +4 -2
package/AGENTS.md
CHANGED
|
@@ -325,6 +325,7 @@ survive there.
|
|
|
325
325
|
| Variable | Required | Purpose |
|
|
326
326
|
|---|---|---|
|
|
327
327
|
| `POLISHD_DATABASE_URL` | for production capture | Pooled Postgres connection string |
|
|
328
|
+
| `BLOB_READ_WRITE_TOKEN` | for production site snapshots | Injected automatically when a Vercel Blob store is connected; snapshot images upload there instead of the (read-only) filesystem |
|
|
328
329
|
| `POLISHD_DASHBOARD_TOKEN` | for production, unless auth is wired | Protects `/polishd`. `openssl rand -hex 32` |
|
|
329
330
|
| `POLISHD_DASHBOARD_PUBLIC` | no | `true` to serve the dashboard unguarded on purpose |
|
|
330
331
|
| `POLISHD_SESSION_COOKIE` | no | Rename the session cookie; read by both proxy and ingest |
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,150 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
### Every Overview tile opens its own graph
|
|
6
|
+
|
|
7
|
+
The six numbers at the top of the Analytics tab were all-time totals, which
|
|
8
|
+
answer "how much" and never "when" — 37 rage clicks is a different problem if
|
|
9
|
+
they all landed on Tuesday. Each tile is now a button: clicking one opens a
|
|
10
|
+
bottom drawer with that metric bucketed over time.
|
|
11
|
+
|
|
12
|
+
- **Hourly or daily**, switchable in the drawer. Both series are computed on
|
|
13
|
+
the server and travel together, so flipping granularity — or switching
|
|
14
|
+
metric from inside the drawer — costs no round trip. Daily is the default
|
|
15
|
+
once there's more than a day of history; before that a daily chart is one
|
|
16
|
+
bar, and hourly is the only shape worth drawing.
|
|
17
|
+
- Every tile grows a **sparkline**, which is both the hint that there's a
|
|
18
|
+
chart behind the number and the shape of it at a glance.
|
|
19
|
+
- The window ends at the **newest bucket that has data**, not at now, so an
|
|
20
|
+
install last browsed three days ago still gets a chart instead of an empty
|
|
21
|
+
one. It covers the last 48 hours or 30 days of activity; where that differs
|
|
22
|
+
from the tile's all-time total, the drawer says so rather than leaving the
|
|
23
|
+
reader to notice.
|
|
24
|
+
- Quiet buckets are drawn as **measured zeros**, not skipped — an empty night
|
|
25
|
+
is a fact about the site, and dropping those points would silently compress
|
|
26
|
+
the axis.
|
|
27
|
+
- **Sessions are never summed.** A visitor active across three hours is
|
|
28
|
+
counted in all three buckets, so the drawer shows peak/average/latest for
|
|
29
|
+
that metric and explains why there's no total.
|
|
30
|
+
- Reading a bucket works by pointer, by tap, and by keyboard (←/→, Home/End
|
|
31
|
+
on the focused chart); the readout sits above the plot so it never covers
|
|
32
|
+
the tallest bar, which is the one you were reaching for.
|
|
33
|
+
- Buckets start at the UTC hour or day, matching the existing per-page chart.
|
|
34
|
+
A visitor whose clock is set to next year can't anchor the window there and
|
|
35
|
+
blank the chart — the windowing rule lives in
|
|
36
|
+
`src/shared/metric-buckets.ts`, pure and tested (`npm test`).
|
|
37
|
+
|
|
38
|
+
The bottom drawer itself, the info tooltip and the axis-tick maths are now
|
|
39
|
+
shared (`src/dashboard/drawer.tsx`, `src/dashboard/ui.tsx`) instead of copied
|
|
40
|
+
between the Top-pages table and this, which is what stopped the two charts
|
|
41
|
+
drifting apart.
|
|
42
|
+
### An Issues tab: every bug polishd filed, in one list
|
|
43
|
+
|
|
44
|
+
Filed issues used to exist only inside the loss that produced them — one
|
|
45
|
+
summary, one card, gone at the next regenerate. The dashboard grows an
|
|
46
|
+
**Issues** tab that lists them all, newest first, and appears only once a
|
|
47
|
+
GitHub repository is connected (nothing to list, and no way to list it,
|
|
48
|
+
otherwise).
|
|
49
|
+
|
|
50
|
+
- Each row joins two sources. The analytics **evidence**, the claim as the
|
|
51
|
+
summary stated it, and the verdict the source verification reached are
|
|
52
|
+
polishd's own record; the title, state, labels, assignees, comment count and
|
|
53
|
+
body are read live from GitHub on every render, so a bug closed an hour ago
|
|
54
|
+
reads as closed here.
|
|
55
|
+
- The issue log the dedupe already kept is what makes the list *ours* rather
|
|
56
|
+
than the repo's — a repo full of other people's issues stays that way. New
|
|
57
|
+
filings additionally record the claim, the verdict and the filing time;
|
|
58
|
+
entries written by earlier versions have only a number and a URL and still
|
|
59
|
+
render, dated from GitHub's own `created_at`.
|
|
60
|
+
- An issue that can no longer be read — deleted, transferred, token access
|
|
61
|
+
revoked — keeps its row and says so, rather than quietly disappearing from
|
|
62
|
+
a count you were trusting.
|
|
63
|
+
- Loading the tab is **one GitHub API call**, not one per issue. The repo's
|
|
64
|
+
issue list returns whole issues, body and all, a hundred at a time, so a
|
|
65
|
+
single page answers for every issue polishd has ever filed. Issue numbers
|
|
66
|
+
only climb and the list comes back newest-first, so a page that has dropped
|
|
67
|
+
below the oldest number we want proves no later page can hold it, and paging
|
|
68
|
+
stops; anything buried past a three-page budget is read individually. The
|
|
69
|
+
rule lives in `src/ai/issue-pages.ts` — pure, no network — with tests
|
|
70
|
+
(`npm test`).
|
|
71
|
+
|
|
72
|
+
### Site snapshots now work in production
|
|
73
|
+
|
|
74
|
+
Capturing a snapshot on a serverless host used to fail on two fronts at once:
|
|
75
|
+
no browser to launch and no writable filesystem to keep the images on. Both
|
|
76
|
+
are now handled, and neither needs configuration beyond connecting a Vercel
|
|
77
|
+
Blob store to the project:
|
|
78
|
+
|
|
79
|
+
- When `BLOB_READ_WRITE_TOKEN` is present (Vercel injects it once a Blob store
|
|
80
|
+
is connected), shots are staged in the system temp directory and uploaded to
|
|
81
|
+
Vercel Blob instead of `.polishd/snapshots/`. Pruning deletes the blobs;
|
|
82
|
+
a failed upload cleans up after itself so a half-stored snapshot never
|
|
83
|
+
survives. Blob pathnames get a random suffix and the dashboard still serves
|
|
84
|
+
every image through the auth-gated server action.
|
|
85
|
+
- When no local Chrome, Edge, or Playwright Chromium can launch on Linux,
|
|
86
|
+
capture falls back to `@sparticuz/chromium` — a Chromium built to run inside
|
|
87
|
+
Lambda-shaped sandboxes. It and `@vercel/blob` ship as optional
|
|
88
|
+
dependencies, so a standard `npm install` brings them along and
|
|
89
|
+
`--omit=optional` keeps them out.
|
|
90
|
+
- An install run with `--omit=optional` loses the feature but not the plot:
|
|
91
|
+
when the environment shows a missing optional dependency will be needed
|
|
92
|
+
(a Blob token with no `@vercel/blob`, a Vercel host with no
|
|
93
|
+
`@sparticuz/chromium`), the gallery says so up front and disables the
|
|
94
|
+
capture button, instead of failing a minute into a doomed run. Failures
|
|
95
|
+
that can only surface at capture time name the missing piece precisely.
|
|
96
|
+
- A deployment with **no Blob store connected at all** gets the same
|
|
97
|
+
treatment. Without the token, storage falls back to disk — which on a
|
|
98
|
+
serverless host is read-only and gone by the next invocation, so every
|
|
99
|
+
capture was doomed before it started and said only "is the filesystem
|
|
100
|
+
writable?" a minute later. The gallery now names the actual gap and the
|
|
101
|
+
one-time fix (connect a Blob store, redeploy) before the button is pressed,
|
|
102
|
+
and the capture action refuses the same way for callers that never rendered
|
|
103
|
+
the dashboard.
|
|
104
|
+
- Local development is unchanged: your own Chrome first, images on disk,
|
|
105
|
+
same index, same gallery.
|
|
106
|
+
|
|
107
|
+
### Reading is not friction: text clicks and trivial scrolls stop counting
|
|
108
|
+
|
|
109
|
+
Three signals could report engagement or frustration where there was only
|
|
110
|
+
reading, inflating exactly the numbers the AI summary leans on hardest.
|
|
111
|
+
|
|
112
|
+
- **Dead clicks skip text.** A click inside a paragraph, heading, list item,
|
|
113
|
+
or other prose block — or on standalone text long enough to read as content
|
|
114
|
+
(40+ chars) — is cursor placement or the start of a selection, not a user
|
|
115
|
+
expecting something to happen. It no longer records a `dead_click`. Clicks
|
|
116
|
+
on non-interactive *layout* elements still do, and so do short standalone
|
|
117
|
+
labels (`<div>Submit</div>`, `<span>Click here</span>`) — that shape is
|
|
118
|
+
exactly what a mis-wired fake control looks like.
|
|
119
|
+
- **Rage clicks skip select-a-word/paragraph.** Double- and triple-clicking
|
|
120
|
+
prose selects text; a rapid burst on a non-interactive text target no
|
|
121
|
+
longer records a `rage_click`. Hammering a real button — or a fake one with
|
|
122
|
+
a short label — still does.
|
|
123
|
+
- **History gets the same fix.** A one-time sweep (versioned via
|
|
124
|
+
`polishd_meta`, run on the first dashboard load after upgrading) re-runs
|
|
125
|
+
the new classification over already-stored `dead_click`/`rage_click` rows,
|
|
126
|
+
using the stored selector path and label. Matching rows are retyped to
|
|
127
|
+
`text_click` — kept in the table, counted by no aggregate — never deleted.
|
|
128
|
+
Rage rows whose selector path contains an interactive element are left
|
|
129
|
+
untouched. Ingest applies the same retype to arriving events, so a cached
|
|
130
|
+
client bundle — or a telemetry emitter still on an older package — can't
|
|
131
|
+
keep refilling the table with the old semantics after the sweep has run. Old `component_view` rows always carried a scroll depth, so at
|
|
132
|
+
read time depth from components short enough to fit a typical viewport
|
|
133
|
+
(≤700px) is ignored; page-level `scroll_depth` history is unaffected (a
|
|
134
|
+
recorded depth needed a real scroll event, and genuine deep scrolls can't
|
|
135
|
+
be told apart after the fact).
|
|
136
|
+
- **100% scroll requires somewhere to scroll.** A page (or dashboard region)
|
|
137
|
+
whose scrollable distance is under 10% of the viewport reaches "100%" by
|
|
138
|
+
existing, so it now records no `scroll_depth` at all; likewise
|
|
139
|
+
`<PolishdMonitor content>` only reports scroll-through for components
|
|
140
|
+
taller than one screen. Aggregates already treat absent as "no data" (shown
|
|
141
|
+
as —), never 0.
|
|
142
|
+
- Both capture layers (host site and the dashboard's own telemetry) share the
|
|
143
|
+
new classification via `src/client/dom.ts`, so they can't drift.
|
|
144
|
+
- The AI digest now omits scroll % where it wasn't measurable and the system
|
|
145
|
+
prompt tells the model these semantics — no more "users read to the bottom!"
|
|
146
|
+
wins on pages that fit in one viewport, and reported dead/rage counts can be
|
|
147
|
+
taken as genuine friction.
|
|
148
|
+
|
|
5
149
|
### The "your proxy isn't running" banner stops crying wolf
|
|
6
150
|
|
|
7
151
|
A correctly installed, verifiably healthy site could show the red banner
|
package/README.md
CHANGED
|
@@ -390,6 +390,27 @@ again.
|
|
|
390
390
|
Ignoring a loss marks the summary stale, exactly like new analytics does, so
|
|
391
391
|
the next refresh actually re-asks the model with the dismissal in hand.
|
|
392
392
|
|
|
393
|
+
### The Issues tab
|
|
394
|
+
|
|
395
|
+
Filing a bug is easy to lose track of — it happens inside one loss, on one
|
|
396
|
+
summary, and then the summary regenerates. The **Issues** tab is the standing
|
|
397
|
+
list: every issue polishd has filed in the connected repo, newest first,
|
|
398
|
+
whether you clicked **File bug** yourself or auto-filing did it for you. The
|
|
399
|
+
tab only appears once a GitHub repository is connected.
|
|
400
|
+
|
|
401
|
+
Each row joins what polishd knows to what GitHub knows. The **evidence** — the
|
|
402
|
+
selector, component or path the analytics cited — and whether the source
|
|
403
|
+
verification confirmed the report are polishd's own record, kept at filing
|
|
404
|
+
time. The title, state, labels, assignees and comment count are read live from
|
|
405
|
+
GitHub on every render, so a bug someone closed an hour ago reads as closed
|
|
406
|
+
here, and the issue body is one click away without leaving the dashboard. An
|
|
407
|
+
issue that can no longer be read — deleted, transferred, or beyond what the
|
|
408
|
+
token now covers — keeps its row and says exactly that.
|
|
409
|
+
|
|
410
|
+
Opening the tab costs a single GitHub API call in the ordinary case, not one
|
|
411
|
+
per issue: the repo's issue list hands back a hundred whole issues at a time,
|
|
412
|
+
which is more than polishd is ever likely to have filed.
|
|
413
|
+
|
|
393
414
|
## Design review
|
|
394
415
|
|
|
395
416
|
The dashboard's **Design** tab (in the sidebar) is your site's brand guideline
|
|
@@ -437,9 +458,19 @@ shoot is taken from the request that rendered the dashboard, or set
|
|
|
437
458
|
`.polishd/snapshots/` (override with `POLISHD_SNAPSHOT_DIR`; the last 6
|
|
438
459
|
snapshots are kept), and each snapshot is stamped with the design-metrics
|
|
439
460
|
fingerprint at capture time — so a snapshot taken before a round of design
|
|
440
|
-
fixes can be held against one taken after.
|
|
441
|
-
|
|
442
|
-
|
|
461
|
+
fixes can be held against one taken after.
|
|
462
|
+
|
|
463
|
+
**In production on Vercel**, capture works too — connect a
|
|
464
|
+
[Blob store](https://vercel.com/docs/vercel-blob) to the project and that's
|
|
465
|
+
the whole setup: the `BLOB_READ_WRITE_TOKEN` it injects switches image storage
|
|
466
|
+
from disk to Blob, and the browser comes from `@sparticuz/chromium` (a
|
|
467
|
+
Chromium built for serverless sandboxes, installed automatically as an
|
|
468
|
+
optional dependency). The snapshot index rides in the same database the rest
|
|
469
|
+
of Polishd already requires in production, so no other wiring changes. If a
|
|
470
|
+
capture of many routes brushes against your function's time limit, raise it
|
|
471
|
+
with `export const maxDuration = 300` in the dashboard's `page.tsx`. On hosts
|
|
472
|
+
with neither a writable filesystem nor a Blob token, the button explains what's
|
|
473
|
+
missing rather than failing silently.
|
|
443
474
|
|
|
444
475
|
## Component-level tracking
|
|
445
476
|
|
package/dist/ai/digest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../../src/ai/digest.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAS9D;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../../src/ai/digest.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAS9D;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CA+FhF;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD"}
|
package/dist/ai/digest.js
CHANGED
|
@@ -55,10 +55,11 @@ export function buildDigest(data, context) {
|
|
|
55
55
|
.sort((a, b) => b.score - a.score)
|
|
56
56
|
.slice(0, 6);
|
|
57
57
|
if (worst.length) {
|
|
58
|
-
lines.push("PAGES WITH FRICTION (worst first):");
|
|
58
|
+
lines.push("PAGES WITH FRICTION (worst first; scroll depth is only measured on pages tall enough to scroll — absent means no signal, not disengagement):");
|
|
59
59
|
for (const p of worst) {
|
|
60
|
+
const scroll = p.avgScrollDepth === null ? "" : `, scroll ${r(p.avgScrollDepth)}%`;
|
|
60
61
|
lines.push(` - ${p.path}: ${p.sessions} sessions, ${p.rageClicks} rage, ` +
|
|
61
|
-
`${p.deadClicks} dead, ${p.jsErrors} err
|
|
62
|
+
`${p.deadClicks} dead, ${p.jsErrors} err${scroll}`);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
const brokenEls = elements.filter((e) => e.rageClicks > 0 || e.deadClicks > 0).slice(0, 8);
|
package/dist/ai/digest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"digest.js","sourceRoot":"","sources":["../../src/ai/digest.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"digest.js","sourceRoot":"","sources":["../../src/ai/digest.ts"],"names":[],"mappings":"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"}
|
package/dist/ai/github.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PolishdGithubStatus, VerifyGithubResult } from "./types";
|
|
1
|
+
import type { PolishdGithubIssue, PolishdGithubStatus, VerifyGithubResult } from "./types";
|
|
2
2
|
/** True when both a repo and a token are configured. */
|
|
3
3
|
export declare function isGithubConnected(): Promise<boolean>;
|
|
4
4
|
/**
|
|
@@ -39,6 +39,27 @@ export declare function createGithubPullRequest(input: {
|
|
|
39
39
|
url: string;
|
|
40
40
|
number: number;
|
|
41
41
|
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Read one issue by number. Returns null when it can't be read — deleted,
|
|
44
|
+
* transferred, or the token lost access — so a single missing issue never
|
|
45
|
+
* takes down the list that contains it.
|
|
46
|
+
*/
|
|
47
|
+
export declare function readGithubIssue(number: number): Promise<PolishdGithubIssue | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Read a known set of issues by number, in as few API calls as possible.
|
|
50
|
+
*
|
|
51
|
+
* The naive way — one call per number — is what the repo's own issue list
|
|
52
|
+
* saves us from: it returns whole issue objects, body and all, a hundred at a
|
|
53
|
+
* time, so a single call usually answers for every issue polishd has ever
|
|
54
|
+
* filed. When to stop asking for pages is its own rule, in issue-pages.ts.
|
|
55
|
+
*
|
|
56
|
+
* Anything the pages didn't reach is read individually afterwards, which is
|
|
57
|
+
* also the whole strategy when there's only one number to find.
|
|
58
|
+
*
|
|
59
|
+
* Numbers that can't be read at all (deleted, transferred, token access
|
|
60
|
+
* narrowed) are simply absent from the returned map.
|
|
61
|
+
*/
|
|
62
|
+
export declare function readGithubIssues(numbers: number[]): Promise<Map<number, PolishdGithubIssue>>;
|
|
42
63
|
/** File an issue in the connected repo. Throws on failure. */
|
|
43
64
|
export declare function createGithubIssue(input: {
|
|
44
65
|
title: string;
|
package/dist/ai/github.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/ai/github.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/ai/github.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAajB,wDAAwD;AACxD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE1D;AA0CD;;;;GAIG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CA2B1E;AAED,gFAAgF;AAChF,wBAAsB,eAAe,IAAI,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAG3E;AAID;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,SAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAclF;AAID;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAa3C;AA2CD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAUxF;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CA4C1C;AAED,8DAA8D;AAC9D,wBAAsB,iBAAiB,CAAC,KAAK,EAAE;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAU3C"}
|
package/dist/ai/github.js
CHANGED
|
@@ -5,14 +5,16 @@
|
|
|
5
5
|
* onboarding. Capabilities, all scoped to that one repo: read and search source
|
|
6
6
|
* (Contents + code-search APIs — lets the AI layer ground its findings in real
|
|
7
7
|
* code even where the source tree isn't on disk, e.g. Vercel), create branches,
|
|
8
|
-
* open pull requests, and file issues
|
|
9
|
-
*
|
|
8
|
+
* open pull requests, and file issues — then read those issues back, which is
|
|
9
|
+
* what the dashboard's Issues tab lists. The "loss → verified bug"
|
|
10
|
+
* orchestration that uses this client lives in issues.ts.
|
|
10
11
|
*
|
|
11
12
|
* The token lives in the same server-side settings blob as the model API key
|
|
12
13
|
* and never reaches the browser; the client only sees a "connected" flag. A
|
|
13
14
|
* fine-grained PAT with Contents (read), Issues (write), and Pull requests
|
|
14
15
|
* (write) on the one repo is all it needs.
|
|
15
16
|
*/
|
|
17
|
+
import { ISSUE_PAGE_SIZE, keepPaging, worthListing, } from "./issue-pages";
|
|
16
18
|
import { resolveSettings } from "./settings";
|
|
17
19
|
const API = "https://api.github.com";
|
|
18
20
|
/** The connected repo + token, or null when either half is missing. */
|
|
@@ -163,7 +165,101 @@ export async function createGithubPullRequest(input) {
|
|
|
163
165
|
const pr = await gh(conn.token, "POST", `/repos/${conn.repo}/pulls`, { title: input.title, body: input.body ?? "", head: input.head, base });
|
|
164
166
|
return { url: pr.html_url, number: pr.number };
|
|
165
167
|
}
|
|
166
|
-
|
|
168
|
+
function toIssue(raw) {
|
|
169
|
+
return {
|
|
170
|
+
number: raw.number,
|
|
171
|
+
title: raw.title,
|
|
172
|
+
body: raw.body ?? "",
|
|
173
|
+
url: raw.html_url,
|
|
174
|
+
state: raw.state === "closed" ? "closed" : "open",
|
|
175
|
+
stateReason: raw.state_reason ?? undefined,
|
|
176
|
+
labels: (raw.labels ?? [])
|
|
177
|
+
.map((l) => (typeof l === "string" ? l : l.name))
|
|
178
|
+
.filter((n) => typeof n === "string" && n.length > 0),
|
|
179
|
+
author: raw.user?.login ?? undefined,
|
|
180
|
+
assignees: (raw.assignees ?? [])
|
|
181
|
+
.map((a) => a.login)
|
|
182
|
+
.filter((n) => typeof n === "string" && n.length > 0),
|
|
183
|
+
comments: raw.comments ?? 0,
|
|
184
|
+
createdAt: Date.parse(raw.created_at),
|
|
185
|
+
updatedAt: Date.parse(raw.updated_at),
|
|
186
|
+
closedAt: raw.closed_at ? Date.parse(raw.closed_at) : undefined,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Read one issue by number. Returns null when it can't be read — deleted,
|
|
191
|
+
* transferred, or the token lost access — so a single missing issue never
|
|
192
|
+
* takes down the list that contains it.
|
|
193
|
+
*/
|
|
194
|
+
export async function readGithubIssue(number) {
|
|
195
|
+
const conn = await connection();
|
|
196
|
+
if (!conn)
|
|
197
|
+
return null;
|
|
198
|
+
try {
|
|
199
|
+
return toIssue(await gh(conn.token, "GET", `/repos/${conn.repo}/issues/${number}`));
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/** How many individual issue reads run at once, when it comes to that. */
|
|
206
|
+
const ISSUE_FETCH_CONCURRENCY = 6;
|
|
207
|
+
/**
|
|
208
|
+
* Read a known set of issues by number, in as few API calls as possible.
|
|
209
|
+
*
|
|
210
|
+
* The naive way — one call per number — is what the repo's own issue list
|
|
211
|
+
* saves us from: it returns whole issue objects, body and all, a hundred at a
|
|
212
|
+
* time, so a single call usually answers for every issue polishd has ever
|
|
213
|
+
* filed. When to stop asking for pages is its own rule, in issue-pages.ts.
|
|
214
|
+
*
|
|
215
|
+
* Anything the pages didn't reach is read individually afterwards, which is
|
|
216
|
+
* also the whole strategy when there's only one number to find.
|
|
217
|
+
*
|
|
218
|
+
* Numbers that can't be read at all (deleted, transferred, token access
|
|
219
|
+
* narrowed) are simply absent from the returned map.
|
|
220
|
+
*/
|
|
221
|
+
export async function readGithubIssues(numbers) {
|
|
222
|
+
const found = new Map();
|
|
223
|
+
const conn = await connection();
|
|
224
|
+
if (!conn || numbers.length === 0)
|
|
225
|
+
return found;
|
|
226
|
+
const wanted = new Set(numbers);
|
|
227
|
+
const oldestWanted = Math.min(...numbers);
|
|
228
|
+
let pagesRead = 0;
|
|
229
|
+
let morePages = worthListing(wanted.size);
|
|
230
|
+
while (morePages) {
|
|
231
|
+
let batch;
|
|
232
|
+
try {
|
|
233
|
+
batch = await gh(conn.token, "GET", `/repos/${conn.repo}/issues?state=all&per_page=${ISSUE_PAGE_SIZE}&page=${pagesRead + 1}`);
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
break; // fall through to the per-issue reads
|
|
237
|
+
}
|
|
238
|
+
pagesRead++;
|
|
239
|
+
let lowestSeen = Infinity;
|
|
240
|
+
for (const raw of batch) {
|
|
241
|
+
if (wanted.has(raw.number))
|
|
242
|
+
found.set(raw.number, toIssue(raw));
|
|
243
|
+
lowestSeen = Math.min(lowestSeen, raw.number);
|
|
244
|
+
}
|
|
245
|
+
morePages = keepPaging({
|
|
246
|
+
pagesRead,
|
|
247
|
+
batchSize: batch.length,
|
|
248
|
+
lowestSeen,
|
|
249
|
+
oldestWanted,
|
|
250
|
+
outstanding: wanted.size - found.size,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const missing = numbers.filter((n) => !found.has(n));
|
|
254
|
+
for (let i = 0; i < missing.length; i += ISSUE_FETCH_CONCURRENCY) {
|
|
255
|
+
const slice = missing.slice(i, i + ISSUE_FETCH_CONCURRENCY);
|
|
256
|
+
for (const issue of await Promise.all(slice.map((n) => readGithubIssue(n)))) {
|
|
257
|
+
if (issue)
|
|
258
|
+
found.set(issue.number, issue);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return found;
|
|
262
|
+
}
|
|
167
263
|
/** File an issue in the connected repo. Throws on failure. */
|
|
168
264
|
export async function createGithubIssue(input) {
|
|
169
265
|
const conn = await connection();
|
package/dist/ai/github.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/ai/github.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/ai/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polishd — when to stop paging the repo's issue list.
|
|
3
|
+
*
|
|
4
|
+
* Looking up a known set of issue numbers has two ways to spend API calls: one
|
|
5
|
+
* request per number, or requests for pages of the repo's issue list — a
|
|
6
|
+
* hundred whole issues each — until the numbers turn up. The second is far
|
|
7
|
+
* cheaper right up until it isn't, which is what this rule decides.
|
|
8
|
+
*
|
|
9
|
+
* It leans on one fact about GitHub: issue numbers only ever climb, and the
|
|
10
|
+
* list comes back newest-first. So a page whose lowest number has already
|
|
11
|
+
* dropped below the oldest number we're looking for is proof that no later
|
|
12
|
+
* page can hold anything we want — every one of them is older still.
|
|
13
|
+
*
|
|
14
|
+
* Pure, no network, no settings — the caller in github.ts does the fetching.
|
|
15
|
+
* Kept separate so the arithmetic can be tested, because both ways of getting
|
|
16
|
+
* it wrong are quiet: stop one page early and issues silently vanish from the
|
|
17
|
+
* tab, never stop and a dashboard render walks the whole repo.
|
|
18
|
+
*/
|
|
19
|
+
/** GitHub's maximum page size for the repo issue list. */
|
|
20
|
+
export declare const ISSUE_PAGE_SIZE = 100;
|
|
21
|
+
/**
|
|
22
|
+
* How many pages one lookup will scan before it gives up and reads whatever
|
|
23
|
+
* is still missing one issue at a time. Three covers the 300 most recent
|
|
24
|
+
* issues, which is well past where paging stops being the cheaper way to find
|
|
25
|
+
* a handful of old ones.
|
|
26
|
+
*/
|
|
27
|
+
export declare const MAX_ISSUE_PAGES = 3;
|
|
28
|
+
export interface PagingState {
|
|
29
|
+
/** How many pages have been read so far, this one included. */
|
|
30
|
+
pagesRead: number;
|
|
31
|
+
/** How many issues the page just read came back with. */
|
|
32
|
+
batchSize: number;
|
|
33
|
+
/** The lowest issue number on that page; Infinity when it was empty. */
|
|
34
|
+
lowestSeen: number;
|
|
35
|
+
/** The oldest (lowest) number still being looked for. */
|
|
36
|
+
oldestWanted: number;
|
|
37
|
+
/** How many wanted numbers are still unaccounted for. */
|
|
38
|
+
outstanding: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Whether another page of the issue list is worth requesting.
|
|
42
|
+
*
|
|
43
|
+
* Stops on any of: everything found, a short page (there is no next page),
|
|
44
|
+
* having paged past the oldest number wanted, or the page budget.
|
|
45
|
+
*/
|
|
46
|
+
export declare function keepPaging(state: PagingState): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Whether to list at all. One number is never worth a hundred-issue page —
|
|
49
|
+
* fetching it directly is a single call either way, and a smaller one.
|
|
50
|
+
*/
|
|
51
|
+
export declare function worthListing(wanted: number): boolean;
|
|
52
|
+
//# sourceMappingURL=issue-pages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-pages.d.ts","sourceRoot":"","sources":["../../src/ai/issue-pages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,0DAA0D;AAC1D,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAKtD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpD"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polishd — when to stop paging the repo's issue list.
|
|
3
|
+
*
|
|
4
|
+
* Looking up a known set of issue numbers has two ways to spend API calls: one
|
|
5
|
+
* request per number, or requests for pages of the repo's issue list — a
|
|
6
|
+
* hundred whole issues each — until the numbers turn up. The second is far
|
|
7
|
+
* cheaper right up until it isn't, which is what this rule decides.
|
|
8
|
+
*
|
|
9
|
+
* It leans on one fact about GitHub: issue numbers only ever climb, and the
|
|
10
|
+
* list comes back newest-first. So a page whose lowest number has already
|
|
11
|
+
* dropped below the oldest number we're looking for is proof that no later
|
|
12
|
+
* page can hold anything we want — every one of them is older still.
|
|
13
|
+
*
|
|
14
|
+
* Pure, no network, no settings — the caller in github.ts does the fetching.
|
|
15
|
+
* Kept separate so the arithmetic can be tested, because both ways of getting
|
|
16
|
+
* it wrong are quiet: stop one page early and issues silently vanish from the
|
|
17
|
+
* tab, never stop and a dashboard render walks the whole repo.
|
|
18
|
+
*/
|
|
19
|
+
/** GitHub's maximum page size for the repo issue list. */
|
|
20
|
+
export const ISSUE_PAGE_SIZE = 100;
|
|
21
|
+
/**
|
|
22
|
+
* How many pages one lookup will scan before it gives up and reads whatever
|
|
23
|
+
* is still missing one issue at a time. Three covers the 300 most recent
|
|
24
|
+
* issues, which is well past where paging stops being the cheaper way to find
|
|
25
|
+
* a handful of old ones.
|
|
26
|
+
*/
|
|
27
|
+
export const MAX_ISSUE_PAGES = 3;
|
|
28
|
+
/**
|
|
29
|
+
* Whether another page of the issue list is worth requesting.
|
|
30
|
+
*
|
|
31
|
+
* Stops on any of: everything found, a short page (there is no next page),
|
|
32
|
+
* having paged past the oldest number wanted, or the page budget.
|
|
33
|
+
*/
|
|
34
|
+
export function keepPaging(state) {
|
|
35
|
+
if (state.outstanding === 0)
|
|
36
|
+
return false;
|
|
37
|
+
if (state.batchSize < ISSUE_PAGE_SIZE)
|
|
38
|
+
return false;
|
|
39
|
+
if (state.lowestSeen <= state.oldestWanted)
|
|
40
|
+
return false;
|
|
41
|
+
return state.pagesRead < MAX_ISSUE_PAGES;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether to list at all. One number is never worth a hundred-issue page —
|
|
45
|
+
* fetching it directly is a single call either way, and a smaller one.
|
|
46
|
+
*/
|
|
47
|
+
export function worthListing(wanted) {
|
|
48
|
+
return wanted > 1;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=issue-pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-pages.js","sourceRoot":"","sources":["../../src/ai/issue-pages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,0DAA0D;AAC1D,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAejC;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,IAAI,KAAK,CAAC,WAAW,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,IAAI,KAAK,CAAC,SAAS,GAAG,eAAe;QAAE,OAAO,KAAK,CAAC;IACpD,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,YAAY;QAAE,OAAO,KAAK,CAAC;IACzD,OAAO,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,OAAO,MAAM,GAAG,CAAC,CAAC;AACpB,CAAC"}
|
package/dist/ai/issues.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PolishdLossItem, CreateIssueResult } from "./types";
|
|
1
|
+
import type { PolishdFiledIssue, PolishdLossItem, CreateIssueResult } from "./types";
|
|
2
2
|
/** The slice of a loss the pipeline needs. */
|
|
3
3
|
type Loss = Pick<PolishdLossItem, "issue" | "evidence" | "location">;
|
|
4
4
|
/**
|
|
@@ -17,5 +17,17 @@ export declare function createIssueFromLoss(loss: Loss): Promise<CreateIssueResu
|
|
|
17
17
|
* "file bug" button as the fallback.
|
|
18
18
|
*/
|
|
19
19
|
export declare function attachGithubIssues(losses: PolishdLossItem[]): Promise<PolishdLossItem[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Every issue polishd has filed in the connected repo, newest first, each one
|
|
22
|
+
* joined to its live state on GitHub.
|
|
23
|
+
*
|
|
24
|
+
* The log is the source of truth for *which* issues are ours — the repo's own
|
|
25
|
+
* issue list is full of everyone else's — and GitHub is the source of truth
|
|
26
|
+
* for everything about them since: title edits, labels, comments, whether
|
|
27
|
+
* someone closed it. An issue that can't be read comes back with a null
|
|
28
|
+
* `detail` rather than disappearing, so a deleted or transferred issue is
|
|
29
|
+
* visible as exactly that. Returns [] when nothing is connected.
|
|
30
|
+
*/
|
|
31
|
+
export declare function listFiledIssues(): Promise<PolishdFiledIssue[]>;
|
|
20
32
|
export {};
|
|
21
33
|
//# sourceMappingURL=issues.d.ts.map
|
package/dist/ai/issues.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../../src/ai/issues.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../../src/ai/issues.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB,8CAA8C;AAC9C,KAAK,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC,CAAC;AA0QrE;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAiDhF;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAoB9F;AAoBD;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA8BpE"}
|