agentfootprint-lens 0.31.1 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -0
- package/dist/{chunk-CJCPL73F.js → chunk-QBSH233H.js} +189 -2
- package/dist/chunk-QBSH233H.js.map +1 -0
- package/dist/core.cjs +202 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +29 -3
- package/dist/{index-626OVHSK.d.cts → index-CPndFgKv.d.cts} +398 -1
- package/dist/{index-626OVHSK.d.ts → index-CPndFgKv.d.ts} +398 -1
- package/dist/index.cjs +932 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -4
- package/dist/index.d.ts +97 -4
- package/dist/index.js +759 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-CJCPL73F.js.map +0 -1
package/README.md
CHANGED
|
@@ -222,6 +222,142 @@ use `observeRecording`.
|
|
|
222
222
|
|
|
223
223
|
---
|
|
224
224
|
|
|
225
|
+
## Report a bug with this run
|
|
226
|
+
|
|
227
|
+
A bug report about an agent is only worth reading with the run attached. A run
|
|
228
|
+
carries prompts, tool arguments and retrieved documents — which is exactly why
|
|
229
|
+
nobody should send one without seeing it first.
|
|
230
|
+
|
|
231
|
+
`<BugReportButton>` puts the consent step in the way. Clicking it opens a dialog
|
|
232
|
+
that shows every selectable unit of evidence — one row per conversation, one per
|
|
233
|
+
derived file — with its size, its event and turn counts, and the names of every
|
|
234
|
+
state key that was already scrubbed. The reporter's own account (title, steps,
|
|
235
|
+
expected, actual) is in the same dialog, because a report missing either half is
|
|
236
|
+
not one. Nothing leaves until a person ticks it.
|
|
237
|
+
|
|
238
|
+
The evidence itself is agentfootprint's (9.9.0 or newer): `describeBugReport`
|
|
239
|
+
measures the run, `exportBugReport` bundles the units that were kept. Lens
|
|
240
|
+
renders the offer and hands the ids back — it never assembles a bundle and never
|
|
241
|
+
decides what a unit is.
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
import { BugReportButton } from 'agentfootprint-lens';
|
|
245
|
+
|
|
246
|
+
// The whole integration. `source` is whatever this Lens is already showing.
|
|
247
|
+
<BugReportButton
|
|
248
|
+
source={recording} // or a recordRun() handle, a Runner, or an array
|
|
249
|
+
issuesUrl="https://github.com/acme/agent/issues" // owner + repo are read from this
|
|
250
|
+
labels={['bug', 'from-lens']}
|
|
251
|
+
/>;
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### What the reporter sees
|
|
255
|
+
|
|
256
|
+
- **The consent manifest** — one checkbox per unit. The **3 most recent
|
|
257
|
+
conversations** start ticked, older ones do not (`defaultRecentConversations`
|
|
258
|
+
changes the number). Derived files — the readable transcript, the narrative,
|
|
259
|
+
the environment block — are rebuilt over the conversations that survive, so
|
|
260
|
+
unticking a conversation takes it out of those too.
|
|
261
|
+
- **A live size meter** — `12.4 MB of 24.0 MB`, recomputed on every toggle. Over
|
|
262
|
+
the ceiling it turns red, submit is refused, and it names what to do about it:
|
|
263
|
+
*"Untick conv-3 (20.0 MB) to fit."* The number is an estimate and says so — the
|
|
264
|
+
derived files shrink as conversations come out, so the real zip is that size or
|
|
265
|
+
smaller.
|
|
266
|
+
- **The redacted keys, by name.** footprintjs scrubbed the values upstream at
|
|
267
|
+
commit time; the manifest can therefore say *which* secrets were protected
|
|
268
|
+
without ever carrying one.
|
|
269
|
+
|
|
270
|
+
### The three submit modes
|
|
271
|
+
|
|
272
|
+
They stack by what you configured. The first is always there, so the button is
|
|
273
|
+
never a dead end, and a mode you did not configure is simply not offered —
|
|
274
|
+
nothing fails at click time.
|
|
275
|
+
|
|
276
|
+
| mode | needs | who the issue is from | where the zip goes |
|
|
277
|
+
|---|---|---|---|
|
|
278
|
+
| **Copy report + download zip** | nothing | the reporter, by hand | their machine |
|
|
279
|
+
| **Sign in with GitHub** | `deviceClientId` | the reporter, as themselves | their machine, attached by hand |
|
|
280
|
+
| **File automatically** | `endpoint` | your application | wherever your relay puts it |
|
|
281
|
+
|
|
282
|
+
**(a) Copy + download** copies the composed issue body to the clipboard, saves
|
|
283
|
+
the evidence zip, and opens the repo's new-issue form prefilled. A body too long
|
|
284
|
+
for a URL is cut at a line break with a sentence pointing at the clipboard,
|
|
285
|
+
never silently shortened.
|
|
286
|
+
|
|
287
|
+
**(b) Sign in with GitHub** runs the OAuth **device flow** inside the dialog:
|
|
288
|
+
Lens shows the user code and the verification link, GitHub polls in the
|
|
289
|
+
background, and on approval the issue is filed from the browser as *that person*
|
|
290
|
+
— so a maintainer can ask them a follow-up.
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
<BugReportButton
|
|
294
|
+
source={recording}
|
|
295
|
+
issuesUrl="https://github.com/acme/agent/issues"
|
|
296
|
+
deviceClientId="Iv1.0123456789abcdef" // an OAuth App with Device Flow enabled
|
|
297
|
+
/>;
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
The client id is public by design (the device flow has no client secret). The
|
|
301
|
+
token it yields is not: Lens holds it in memory for the life of the modal and
|
|
302
|
+
drops it — never `localStorage`, never a cookie, never a log line, never the
|
|
303
|
+
issue body. Signing in does not give Lens anywhere to push the zip, so the zip
|
|
304
|
+
downloads to the reporter's machine and the issue says plainly that it must be
|
|
305
|
+
attached by hand.
|
|
306
|
+
|
|
307
|
+
**(c) File automatically** POSTs the finished bundle to your own endpoint, which
|
|
308
|
+
holds the token and files the report with `githubBugReporter`. One click for the
|
|
309
|
+
reporter; nothing about your repository lives in the browser.
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
<BugReportButton source={recording} issuesUrl={ISSUES} endpoint="/api/bug-report" />;
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
// The server side, in full. The browser already built the bundle — the relay
|
|
317
|
+
// only holds the credential.
|
|
318
|
+
import { githubBugReporter } from 'agentfootprint/observe';
|
|
319
|
+
|
|
320
|
+
const reporter = githubBugReporter({ issueRepo: 'acme/agent' }); // token: GITHUB_TOKEN
|
|
321
|
+
|
|
322
|
+
app.post('/api/bug-report', async (req, res) => {
|
|
323
|
+
const { manifest, filename, zipBase64 } = req.body; // kind: 'agentfootprint-lens.bug-report'
|
|
324
|
+
const zip = Buffer.from(zipBase64, 'base64');
|
|
325
|
+
res.json(await reporter.file({ manifest, files: [], zip, filename }));
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
The response Lens renders is `{ issueUrl, zipUrl }`; anything else — a non-2xx,
|
|
330
|
+
an `error` string — is shown to the reporter exactly as the server wrote it.
|
|
331
|
+
That is the rule for every failure in this flow: agentfootprint's refusals teach
|
|
332
|
+
what to do next, so they are rendered verbatim rather than paraphrased.
|
|
333
|
+
|
|
334
|
+
### On an older agentfootprint
|
|
335
|
+
|
|
336
|
+
The substrate shipped in agentfootprint 9.9.0. On 7.x or 8.x the button does not
|
|
337
|
+
render at all — a one-line hint says which version it needs. Lens will not send
|
|
338
|
+
a run it cannot measure first.
|
|
339
|
+
|
|
340
|
+
### Props
|
|
341
|
+
|
|
342
|
+
| prop | | |
|
|
343
|
+
|---|---|---|
|
|
344
|
+
| `source` | required | a `Recording`, a `recordRun()` handle, a `Runner`, or an array of them |
|
|
345
|
+
| `issuesUrl` | required | `https://github.com/OWNER/REPO/issues` — owner, repo and API root are read from it (GitHub Enterprise Server works unchanged) |
|
|
346
|
+
| `endpoint` | | your relay URL — offers "File automatically" |
|
|
347
|
+
| `deviceClientId` | | OAuth App client id — offers "Sign in with GitHub" |
|
|
348
|
+
| `labels` | | labels applied to the issue |
|
|
349
|
+
| `defaultRecentConversations` | `3` | how many of the most recent conversations start ticked |
|
|
350
|
+
| `maxBytes` | 24 MB | the ceiling the meter measures against |
|
|
351
|
+
| `appVersion` | | your app's version, for the environment block |
|
|
352
|
+
| `label` | | the button's own text |
|
|
353
|
+
| `api` | | the agentfootprint functions to call — defaults to the installed ones |
|
|
354
|
+
|
|
355
|
+
The headless half is on `agentfootprint-lens/core` — `defaultSelection`,
|
|
356
|
+
`measureSelection`, `trimHintFor`, `buildIssueBody`, `buildNewIssueUrl`,
|
|
357
|
+
`parseGithubRepo` — so a CLI or a Vue shell can build the same dialog.
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
225
361
|
## Theming
|
|
226
362
|
|
|
227
363
|
**Lens inherits theme tokens from your app via CSS variables.** Set `--fp-*`
|
|
@@ -376,6 +512,16 @@ exact `formatSlice` text the LLM tool returns. Honest absence stays honest:
|
|
|
376
512
|
"never written — initial state / args / a closure", and reads-off runs say
|
|
377
513
|
"unknowable, not absent".
|
|
378
514
|
|
|
515
|
+
### `<BugReportButton>` — report a bug with the run attached, consent first
|
|
516
|
+
|
|
517
|
+
A small button for a debug UI. The dialog it opens shows every selectable unit
|
|
518
|
+
of evidence with its size and counts, meters the selection live against a 24 MB
|
|
519
|
+
ceiling (naming the unit to untick when it is over), and offers whichever of the
|
|
520
|
+
three submit modes you configured — copy + download, sign in with GitHub, or
|
|
521
|
+
file through your own endpoint. Needs agentfootprint 9.9+; on anything older it
|
|
522
|
+
renders a version hint instead of itself. See
|
|
523
|
+
[Report a bug with this run](#report-a-bug-with-this-run).
|
|
524
|
+
|
|
379
525
|
### Headless core
|
|
380
526
|
|
|
381
527
|
`agentfootprint-lens/core` is React-free: `LensRecorder`, `ChangeNotifier`,
|
|
@@ -2821,6 +2821,180 @@ function layoutLensGraph(output, options = {}) {
|
|
|
2821
2821
|
};
|
|
2822
2822
|
}
|
|
2823
2823
|
|
|
2824
|
+
// src/core/bugReport/selection.ts
|
|
2825
|
+
var DEFAULT_MAX_BYTES = 24 * 1024 * 1024;
|
|
2826
|
+
function formatBytes(bytes) {
|
|
2827
|
+
if (!Number.isFinite(bytes) || bytes < 0) return "0 bytes";
|
|
2828
|
+
if (bytes < 1024) return `${Math.round(bytes)} bytes`;
|
|
2829
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
2830
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
2831
|
+
}
|
|
2832
|
+
function conversationUnits(manifest) {
|
|
2833
|
+
return manifest.units.filter((unit) => unit.kind === "conversation");
|
|
2834
|
+
}
|
|
2835
|
+
function fileUnits(manifest) {
|
|
2836
|
+
return manifest.units.filter((unit) => unit.kind !== "conversation");
|
|
2837
|
+
}
|
|
2838
|
+
function defaultSelection(manifest, recent = 3) {
|
|
2839
|
+
const conversations = conversationUnits(manifest);
|
|
2840
|
+
const keep = recent <= 0 ? [] : conversations.slice(Math.max(0, conversations.length - recent));
|
|
2841
|
+
return [...keep.map((unit) => unit.id), ...fileUnits(manifest).map((unit) => unit.id)];
|
|
2842
|
+
}
|
|
2843
|
+
function measureSelection(manifest, selected, limitBytes = DEFAULT_MAX_BYTES) {
|
|
2844
|
+
const ticked = new Set(selected);
|
|
2845
|
+
const units = manifest.units.filter((unit) => ticked.has(unit.id));
|
|
2846
|
+
const bytes = units.reduce((sum, unit) => sum + (unit.bytes || 0), 0);
|
|
2847
|
+
const over = bytes > limitBytes;
|
|
2848
|
+
const hint = over ? trimHintFor(manifest, ticked, limitBytes) : void 0;
|
|
2849
|
+
return {
|
|
2850
|
+
bytes,
|
|
2851
|
+
limitBytes,
|
|
2852
|
+
over,
|
|
2853
|
+
label: `${formatBytes(bytes)} of ${formatBytes(limitBytes)}`,
|
|
2854
|
+
conversations: units.filter((unit) => unit.kind === "conversation").length,
|
|
2855
|
+
...hint !== void 0 && { hint }
|
|
2856
|
+
};
|
|
2857
|
+
}
|
|
2858
|
+
function trimHintFor(manifest, selected, limitBytes = DEFAULT_MAX_BYTES) {
|
|
2859
|
+
const ticked = new Set(selected);
|
|
2860
|
+
const droppable = manifest.units.filter((unit) => ticked.has(unit.id) && unit.kind === "conversation").sort((left, right) => right.bytes - left.bytes);
|
|
2861
|
+
let remaining = manifest.units.filter((unit) => ticked.has(unit.id)).reduce((sum, unit) => sum + (unit.bytes || 0), 0);
|
|
2862
|
+
if (remaining <= limitBytes) return void 0;
|
|
2863
|
+
const named = [];
|
|
2864
|
+
for (const unit of droppable) {
|
|
2865
|
+
if (named.length >= droppable.length - 1) break;
|
|
2866
|
+
remaining -= unit.bytes || 0;
|
|
2867
|
+
named.push(`${unit.id} (${formatBytes(unit.bytes || 0)})`);
|
|
2868
|
+
if (remaining <= limitBytes) break;
|
|
2869
|
+
}
|
|
2870
|
+
if (remaining > limitBytes) {
|
|
2871
|
+
return `Even with one conversation left this is over ${formatBytes(limitBytes)}. Untick a derived file, record a shorter reproduction, or file the issue and attach the zip by hand.`;
|
|
2872
|
+
}
|
|
2873
|
+
return `Untick ${joinWithAnd(named)} to fit.`;
|
|
2874
|
+
}
|
|
2875
|
+
function joinWithAnd(parts) {
|
|
2876
|
+
if (parts.length <= 1) return parts[0] ?? "";
|
|
2877
|
+
return `${parts.slice(0, -1).join(", ")} and ${parts[parts.length - 1]}`;
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
// src/core/bugReport/issueBody.ts
|
|
2881
|
+
function buildIssueBody(args) {
|
|
2882
|
+
const { fields, manifest, evidence } = args;
|
|
2883
|
+
const selected = new Set(args.selected ?? manifest.selected ?? manifest.units.map((u) => u.id));
|
|
2884
|
+
const lines = [];
|
|
2885
|
+
lines.push("### Steps to reproduce", "", textOr(fields.stepsToReproduce), "");
|
|
2886
|
+
lines.push("### Expected", "", textOr(fields.expected), "");
|
|
2887
|
+
lines.push("### Actual", "", textOr(fields.actual), "");
|
|
2888
|
+
lines.push("### Evidence in this report", "");
|
|
2889
|
+
lines.push("| unit | kind | size | events | turns |");
|
|
2890
|
+
lines.push("| --- | --- | --- | --- | --- |");
|
|
2891
|
+
for (const unit of manifest.units) {
|
|
2892
|
+
if (!selected.has(unit.id)) continue;
|
|
2893
|
+
lines.push(
|
|
2894
|
+
`| \`${unit.id}\` | ${unit.kind} | ${formatBytes(unit.bytes || 0)} | ${unit.eventCount ?? "\u2014"} | ${unit.turnCount ?? "\u2014"} |`
|
|
2895
|
+
);
|
|
2896
|
+
}
|
|
2897
|
+
lines.push("");
|
|
2898
|
+
const left = manifest.units.filter((unit) => !selected.has(unit.id));
|
|
2899
|
+
if (left.length > 0) {
|
|
2900
|
+
lines.push(
|
|
2901
|
+
`The reporter left out ${left.length} unit${left.length === 1 ? "" : "s"}: ${left.map((unit) => `\`${unit.id}\``).join(", ")}. A turn that refers to something not here is referring to one of those.`,
|
|
2902
|
+
""
|
|
2903
|
+
);
|
|
2904
|
+
}
|
|
2905
|
+
const redacted = manifest.redactedKeys ?? [];
|
|
2906
|
+
if (redacted.length > 0) {
|
|
2907
|
+
lines.push(
|
|
2908
|
+
`**Redacted before recording** (names only \u2014 the values never left the reporter's machine): ${redacted.map((key) => `\`${key}\``).join(", ")}`,
|
|
2909
|
+
""
|
|
2910
|
+
);
|
|
2911
|
+
}
|
|
2912
|
+
for (const warning of manifest.warnings ?? []) lines.push(`> \u26A0 ${warning}`, "");
|
|
2913
|
+
for (const note of manifest.notes ?? []) lines.push(`> ${note}`, "");
|
|
2914
|
+
if (evidence) {
|
|
2915
|
+
lines.push(
|
|
2916
|
+
evidence.delivery === "by-hand" ? `**Evidence bundle:** \`${evidence.filename}\` (${formatBytes(evidence.bytes)}) \u2014 downloaded to the reporter's machine and attached to this issue by hand. If it is not attached above, ask them for it: nothing was uploaded automatically.` : `**Evidence bundle:** \`${evidence.filename}\` (${formatBytes(evidence.bytes)}) \u2014 sent to the application's bug-report endpoint, which files it with this issue.`,
|
|
2917
|
+
""
|
|
2918
|
+
);
|
|
2919
|
+
}
|
|
2920
|
+
lines.push("### Environment", "");
|
|
2921
|
+
const env = manifest.environment ?? {};
|
|
2922
|
+
for (const [label, value] of [
|
|
2923
|
+
["agentfootprint", env.agentfootprint],
|
|
2924
|
+
["footprintjs", env.footprintjs],
|
|
2925
|
+
["node", env.node],
|
|
2926
|
+
["platform", joinPlatform(env.platform, env.arch)],
|
|
2927
|
+
["app", env.appVersion ?? fields.appVersion]
|
|
2928
|
+
]) {
|
|
2929
|
+
if (value) lines.push(`- ${label}: \`${value}\``);
|
|
2930
|
+
}
|
|
2931
|
+
lines.push("");
|
|
2932
|
+
lines.push("<sub>Filed from Why Lens \u2014 the manifest above is the library's own.</sub>");
|
|
2933
|
+
return `${lines.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd()}
|
|
2934
|
+
`;
|
|
2935
|
+
}
|
|
2936
|
+
var textOr = (value) => value && value.trim() !== "" ? value.trim() : "_(not given)_";
|
|
2937
|
+
function joinPlatform(platform, arch) {
|
|
2938
|
+
if (!platform && !arch) return void 0;
|
|
2939
|
+
return [platform, arch].filter(Boolean).join("/");
|
|
2940
|
+
}
|
|
2941
|
+
|
|
2942
|
+
// src/core/bugReport/github.ts
|
|
2943
|
+
function parseGithubRepo(issuesUrl) {
|
|
2944
|
+
let url;
|
|
2945
|
+
try {
|
|
2946
|
+
url = new URL(issuesUrl);
|
|
2947
|
+
} catch {
|
|
2948
|
+
return void 0;
|
|
2949
|
+
}
|
|
2950
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") return void 0;
|
|
2951
|
+
const [owner, repo] = url.pathname.split("/").filter(Boolean);
|
|
2952
|
+
if (!owner || !repo) return void 0;
|
|
2953
|
+
const isDotCom = url.hostname === "github.com" || url.hostname === "www.github.com";
|
|
2954
|
+
return {
|
|
2955
|
+
owner,
|
|
2956
|
+
repo: repo.replace(/\.git$/, ""),
|
|
2957
|
+
apiBase: isDotCom ? "https://api.github.com" : `${url.origin}/api/v3`,
|
|
2958
|
+
newIssueUrl: `${url.origin}/${owner}/${repo}/issues/new`
|
|
2959
|
+
};
|
|
2960
|
+
}
|
|
2961
|
+
var MAX_ISSUE_URL_BYTES = 8e3;
|
|
2962
|
+
var TRUNCATION_NOTICE = "\n\n\u2026truncated to fit a URL \u2014 the full report is on the clipboard, paste it over this.\n";
|
|
2963
|
+
function buildNewIssueUrl(args) {
|
|
2964
|
+
const limit = args.maxBytes ?? MAX_ISSUE_URL_BYTES;
|
|
2965
|
+
const compose = (body) => {
|
|
2966
|
+
const params = new URLSearchParams();
|
|
2967
|
+
params.set("title", args.title);
|
|
2968
|
+
params.set("body", body);
|
|
2969
|
+
if (args.labels && args.labels.length > 0) params.set("labels", args.labels.join(","));
|
|
2970
|
+
return `${args.target.newIssueUrl}?${params.toString()}`;
|
|
2971
|
+
};
|
|
2972
|
+
const full = compose(args.body);
|
|
2973
|
+
if (full.length <= limit) return { url: full, truncated: false };
|
|
2974
|
+
let keep = args.body.length;
|
|
2975
|
+
let url = full;
|
|
2976
|
+
while (keep > 0 && url.length > limit) {
|
|
2977
|
+
keep = Math.floor(keep * (limit / url.length) * 0.95);
|
|
2978
|
+
url = compose(cutAtLine(args.body, keep) + TRUNCATION_NOTICE);
|
|
2979
|
+
}
|
|
2980
|
+
return { url, truncated: true };
|
|
2981
|
+
}
|
|
2982
|
+
function cutAtLine(body, keep) {
|
|
2983
|
+
const head = body.slice(0, Math.max(0, keep));
|
|
2984
|
+
const lastBreak = head.lastIndexOf("\n");
|
|
2985
|
+
return lastBreak > keep * 0.5 ? head.slice(0, lastBreak) : head;
|
|
2986
|
+
}
|
|
2987
|
+
function encodeBase64(bytes) {
|
|
2988
|
+
const maybeBuffer = globalThis.Buffer;
|
|
2989
|
+
if (typeof maybeBuffer?.from === "function") return maybeBuffer.from(bytes).toString("base64");
|
|
2990
|
+
let binary = "";
|
|
2991
|
+
const chunk = 32768;
|
|
2992
|
+
for (let i = 0; i < bytes.length; i += chunk) {
|
|
2993
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunk));
|
|
2994
|
+
}
|
|
2995
|
+
return btoa(binary);
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2824
2998
|
export {
|
|
2825
2999
|
ChangeNotifier,
|
|
2826
3000
|
lensSnapshotRecorder,
|
|
@@ -2866,6 +3040,19 @@ export {
|
|
|
2866
3040
|
explainableShellPropsFromRunner,
|
|
2867
3041
|
toReactFlow,
|
|
2868
3042
|
defaultSize,
|
|
2869
|
-
layoutLensGraph
|
|
3043
|
+
layoutLensGraph,
|
|
3044
|
+
DEFAULT_MAX_BYTES,
|
|
3045
|
+
formatBytes,
|
|
3046
|
+
conversationUnits,
|
|
3047
|
+
fileUnits,
|
|
3048
|
+
defaultSelection,
|
|
3049
|
+
measureSelection,
|
|
3050
|
+
trimHintFor,
|
|
3051
|
+
buildIssueBody,
|
|
3052
|
+
parseGithubRepo,
|
|
3053
|
+
MAX_ISSUE_URL_BYTES,
|
|
3054
|
+
TRUNCATION_NOTICE,
|
|
3055
|
+
buildNewIssueUrl,
|
|
3056
|
+
encodeBase64
|
|
2870
3057
|
};
|
|
2871
|
-
//# sourceMappingURL=chunk-
|
|
3058
|
+
//# sourceMappingURL=chunk-QBSH233H.js.map
|