@nanonets/graft 0.19.0 → 0.21.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 +9 -4
- package/dist/app/history.d.ts +36 -1
- package/dist/app/history.d.ts.map +1 -1
- package/dist/app/history.js +75 -22
- package/dist/app/history.js.map +1 -1
- package/dist/app/sources.d.ts +13 -0
- package/dist/app/sources.d.ts.map +1 -1
- package/dist/app/sources.js +129 -1
- package/dist/app/sources.js.map +1 -1
- package/dist/ask/ask.js +1 -1
- package/dist/brain/claude-md.d.ts +61 -0
- package/dist/brain/claude-md.d.ts.map +1 -0
- package/dist/brain/claude-md.js +171 -0
- package/dist/brain/claude-md.js.map +1 -0
- package/dist/brain/connect.d.ts +3 -3
- package/dist/brain/connect.js +7 -7
- package/dist/brain/context-files.d.ts +79 -0
- package/dist/brain/context-files.d.ts.map +1 -0
- package/dist/brain/context-files.js +245 -0
- package/dist/brain/context-files.js.map +1 -0
- package/dist/brain/link.d.ts +18 -1
- package/dist/brain/link.d.ts.map +1 -1
- package/dist/brain/link.js +22 -1
- package/dist/brain/link.js.map +1 -1
- package/dist/brain/pull.d.ts +17 -0
- package/dist/brain/pull.d.ts.map +1 -0
- package/dist/brain/pull.js +172 -0
- package/dist/brain/pull.js.map +1 -0
- package/dist/brain/push.d.ts +86 -3
- package/dist/brain/push.d.ts.map +1 -1
- package/dist/brain/push.js +149 -36
- package/dist/brain/push.js.map +1 -1
- package/dist/brain/signup.d.ts +46 -2
- package/dist/brain/signup.d.ts.map +1 -1
- package/dist/brain/signup.js +103 -13
- package/dist/brain/signup.js.map +1 -1
- package/dist/brain/upload.d.ts +61 -0
- package/dist/brain/upload.d.ts.map +1 -0
- package/dist/brain/upload.js +210 -0
- package/dist/brain/upload.js.map +1 -0
- package/dist/brain/watch.d.ts +77 -4
- package/dist/brain/watch.d.ts.map +1 -1
- package/dist/brain/watch.js +263 -39
- package/dist/brain/watch.js.map +1 -1
- package/dist/claude/build-progress.d.ts +29 -0
- package/dist/claude/build-progress.d.ts.map +1 -0
- package/dist/claude/build-progress.js +76 -0
- package/dist/claude/build-progress.js.map +1 -0
- package/dist/claude/init.d.ts.map +1 -1
- package/dist/claude/init.js +3 -1
- package/dist/claude/init.js.map +1 -1
- package/dist/cli-picker.d.ts +17 -2
- package/dist/cli-picker.d.ts.map +1 -1
- package/dist/cli-picker.js +103 -22
- package/dist/cli-picker.js.map +1 -1
- package/dist/cli.js +462 -123
- package/dist/cli.js.map +1 -1
- package/dist/legacy-args.d.ts +12 -0
- package/dist/legacy-args.d.ts.map +1 -0
- package/dist/legacy-args.js +31 -0
- package/dist/legacy-args.js.map +1 -0
- package/dist/telemetry/contract.d.ts +17 -4
- package/dist/telemetry/contract.d.ts.map +1 -1
- package/dist/telemetry/contract.js +25 -7
- package/dist/telemetry/contract.js.map +1 -1
- package/dist/upkeep.d.ts +1 -1
- package/dist/upkeep.js +1 -1
- package/dist/util/spinner.d.ts +15 -0
- package/dist/util/spinner.d.ts.map +1 -0
- package/dist/util/spinner.js +52 -0
- package/dist/util/spinner.js.map +1 -0
- package/dist/util/state.d.ts +8 -0
- package/dist/util/state.d.ts.map +1 -1
- package/dist/util/state.js.map +1 -1
- package/package.json +1 -1
package/dist/brain/push.js
CHANGED
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
* hashes. No file contents, no diffs, no source.
|
|
16
16
|
*/
|
|
17
17
|
import { spawnSync } from "node:child_process";
|
|
18
|
-
import { buildDigest, readCommits, readSymbols, readThreads, } from "../app/history.js";
|
|
18
|
+
import { buildDigest, newThreadReadCache, readCommits, readSymbols, readThreads, } from "../app/history.js";
|
|
19
19
|
import { budgetSources, readAgentInstructions, readBranchProtection, readCodeowners, readCodifiedRules, readDecisionDocs, readDeclinedIssues, readReverts, readTestNames, } from "../app/sources.js";
|
|
20
|
+
import { readStamp, wiredHostIds } from "../upkeep.js";
|
|
20
21
|
import { baseUrlFor } from "./link.js";
|
|
22
|
+
import { postDigestOnce, uploadDigest } from "./upload.js";
|
|
21
23
|
function git(root, args) {
|
|
22
24
|
const res = spawnSync("git", ["-c", "core.quotePath=false", ...args], {
|
|
23
25
|
cwd: root,
|
|
@@ -90,6 +92,10 @@ async function isPrivate(owner, name, token, fetchImpl) {
|
|
|
90
92
|
* afterwards — the rules simply describe someone else's codebase — so the round
|
|
91
93
|
* trip is worth it.
|
|
92
94
|
*
|
|
95
|
+
* The same read says what the server can take: gzip, chunks, a live event
|
|
96
|
+
* stream. Every flag defaults to off, so an older Trail gets exactly the
|
|
97
|
+
* requests it always did.
|
|
98
|
+
*
|
|
93
99
|
* Null on any failure, which keeps an older brain (or an unreachable one)
|
|
94
100
|
* working exactly as it did before this check existed.
|
|
95
101
|
*/
|
|
@@ -104,24 +110,134 @@ export async function fetchExpectedRepo(link, fetchImpl = fetch) {
|
|
|
104
110
|
const body = (await res.json());
|
|
105
111
|
if (!body.repo?.slug)
|
|
106
112
|
return null;
|
|
107
|
-
return {
|
|
113
|
+
return {
|
|
114
|
+
slug: body.repo.slug,
|
|
115
|
+
status: String(body.repo.status ?? ""),
|
|
116
|
+
brainName: String(body.brain_name ?? ""),
|
|
117
|
+
ruleCount: typeof body.repo.rule_count === "number" && body.repo.rule_count > 0 ? body.repo.rule_count : 0,
|
|
118
|
+
earlyUpload: body.early_upload === true,
|
|
119
|
+
gzipUpload: body.gzip_upload === true,
|
|
120
|
+
chunkedUpload: body.chunked_upload === true,
|
|
121
|
+
events: body.events === true,
|
|
122
|
+
};
|
|
108
123
|
}
|
|
109
124
|
catch {
|
|
110
125
|
return null;
|
|
111
126
|
}
|
|
112
127
|
}
|
|
128
|
+
/** The upload capabilities an expected-repo read advertised. */
|
|
129
|
+
export function uploadCaps(expected) {
|
|
130
|
+
return { gzip: expected?.gzipUpload === true, chunked: expected?.chunkedUpload === true };
|
|
131
|
+
}
|
|
113
132
|
/** Whether two repo slugs name the same repository. GitHub is case-insensitive. */
|
|
114
133
|
export function sameRepo(a, b) {
|
|
115
134
|
return a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
116
135
|
}
|
|
136
|
+
/** How many of the newest pull requests and commits the early upload carries —
|
|
137
|
+
* what Trail's quick CLAUDE.md pass reads, and no more. */
|
|
138
|
+
export const EARLY_THREADS = 30;
|
|
139
|
+
export const EARLY_COMMITS = 80;
|
|
140
|
+
/** The shared context for a push from `root`, or null without a GitHub origin. */
|
|
141
|
+
export function pushContext(root, opts = {}) {
|
|
142
|
+
const slug = repoSlugFromGit(root);
|
|
143
|
+
if (!slug)
|
|
144
|
+
return null;
|
|
145
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
146
|
+
const token = githubToken();
|
|
147
|
+
let privacy = null;
|
|
148
|
+
return {
|
|
149
|
+
owner: slug.owner,
|
|
150
|
+
name: slug.name,
|
|
151
|
+
token,
|
|
152
|
+
fetchImpl,
|
|
153
|
+
headSha: git(root, ["rev-parse", "HEAD"]) ?? "",
|
|
154
|
+
branch: currentBranch(root),
|
|
155
|
+
isPrivate: () => (privacy ??= isPrivate(slug.owner, slug.name, token, fetchImpl)),
|
|
156
|
+
threads: newThreadReadCache(),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The early upload: the instruction files, the newest pull requests and the
|
|
161
|
+
* newest commits, read before the rest of the history.
|
|
162
|
+
*
|
|
163
|
+
* Reading the history is most of a push's wait — up to 200 pull requests at two
|
|
164
|
+
* GitHub calls each — and Trail's first CLAUDE.md suggestions need none of it
|
|
165
|
+
* beyond the newest few. Sent first, they start while the full read is still
|
|
166
|
+
* going here, and the full upload that follows mines as before.
|
|
167
|
+
*
|
|
168
|
+
* Only the newest commits are read here, not the thousand the full read takes,
|
|
169
|
+
* so nothing but these few requests stands between the push starting and Trail
|
|
170
|
+
* starting. The pull requests go through the shared cache, so the full read
|
|
171
|
+
* asks GitHub for none of them again — not even one still in flight.
|
|
172
|
+
*
|
|
173
|
+
* Null when there is nothing worth sending early.
|
|
174
|
+
*/
|
|
175
|
+
export async function buildEarlyDigest(root, opts = {}) {
|
|
176
|
+
const ctx = opts.context ?? pushContext(root, opts);
|
|
177
|
+
if (!ctx)
|
|
178
|
+
return null;
|
|
179
|
+
// Oldest first, like the full read, so the newest are the tail.
|
|
180
|
+
const commits = readCommits(root, EARLY_COMMITS);
|
|
181
|
+
if (commits.length === 0)
|
|
182
|
+
return null;
|
|
183
|
+
let threads = [];
|
|
184
|
+
if (ctx.token) {
|
|
185
|
+
try {
|
|
186
|
+
threads = await readThreads(ctx.owner, ctx.name, ctx.token, ctx.fetchImpl, undefined, EARLY_THREADS, undefined, ctx.threads);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
threads = [];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const digest = buildDigest({
|
|
193
|
+
owner: ctx.owner,
|
|
194
|
+
name: ctx.name,
|
|
195
|
+
headSha: ctx.headSha,
|
|
196
|
+
defaultBranch: ctx.branch,
|
|
197
|
+
isPrivate: await ctx.isPrivate(),
|
|
198
|
+
commits,
|
|
199
|
+
threads,
|
|
200
|
+
symbols: [],
|
|
201
|
+
sources: budgetSources(readAgentInstructions(root)),
|
|
202
|
+
autoApprove: true,
|
|
203
|
+
agents: pickedAgents(root),
|
|
204
|
+
});
|
|
205
|
+
return { digest, threads };
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* The agents this repo is wired for — what `graft init` recorded plus what is on
|
|
209
|
+
* disk, the same set `graft trail pull` filters by — so Trail can show only the
|
|
210
|
+
* context files those agents read. Empty before the first init; Trail then
|
|
211
|
+
* shows every kind.
|
|
212
|
+
*/
|
|
213
|
+
export function pickedAgents(root) {
|
|
214
|
+
try {
|
|
215
|
+
return [...new Set([...(readStamp(root)?.hosts ?? []), ...wiredHostIds(root)])];
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/** Send the early upload. Best-effort: false on any failure, and the full
|
|
222
|
+
* upload still does everything. Gzipped when the server takes it. */
|
|
223
|
+
export async function pushEarlyDigest(link, digest, fetchImpl = fetch, opts = {}) {
|
|
224
|
+
try {
|
|
225
|
+
const res = await postDigestOnce(link, digest, { gzip: opts.gzip, fetchImpl, query: "?stage=early", timeoutMs: 15_000 });
|
|
226
|
+
if (!res.ok)
|
|
227
|
+
return false;
|
|
228
|
+
return (await res.json()).early === true;
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
117
234
|
/** Build the digest for the checkout at `root`. Reads nothing but text. */
|
|
118
235
|
export async function buildLocalDigest(root, graph, opts = {}) {
|
|
119
|
-
const
|
|
120
|
-
if (!
|
|
236
|
+
const ctx = opts.context ?? pushContext(root, opts);
|
|
237
|
+
if (!ctx) {
|
|
121
238
|
return { error: "this directory has no GitHub `origin` remote — graft can only push a GitHub repository today" };
|
|
122
239
|
}
|
|
123
|
-
const
|
|
124
|
-
const token = githubToken();
|
|
240
|
+
const { token, fetchImpl } = ctx;
|
|
125
241
|
const commits = readCommits(root);
|
|
126
242
|
if (commits.length === 0) {
|
|
127
243
|
return { error: "no commits found here — is this a shallow clone with no history?" };
|
|
@@ -129,9 +245,18 @@ export async function buildLocalDigest(root, graph, opts = {}) {
|
|
|
129
245
|
const symbols = readSymbols(graph);
|
|
130
246
|
let threads = [];
|
|
131
247
|
let warning;
|
|
248
|
+
// The GitHub-side sources start with the threads rather than after them:
|
|
249
|
+
// they are a request or two each, and waiting behind 400 is waiting for no reason.
|
|
250
|
+
const remote = token
|
|
251
|
+
? Promise.all([
|
|
252
|
+
readBranchProtection(ctx.owner, ctx.name, ctx.branch, token, fetchImpl),
|
|
253
|
+
readDeclinedIssues(ctx.owner, ctx.name, token, fetchImpl),
|
|
254
|
+
])
|
|
255
|
+
: Promise.resolve([[], []]);
|
|
132
256
|
if (token) {
|
|
133
257
|
try {
|
|
134
|
-
|
|
258
|
+
const known = new Map((opts.knownThreads ?? []).map((t) => [t.number, t]));
|
|
259
|
+
threads = await readThreads(ctx.owner, ctx.name, token, fetchImpl, undefined, undefined, known, ctx.threads);
|
|
135
260
|
}
|
|
136
261
|
catch {
|
|
137
262
|
warning = "could not read pull-request discussion; mining commits and repo files only";
|
|
@@ -141,7 +266,7 @@ export async function buildLocalDigest(root, graph, opts = {}) {
|
|
|
141
266
|
warning =
|
|
142
267
|
"no GitHub token found (`gh auth login`, or GH_TOKEN) — mining commits and repo files only, without pull-request discussion";
|
|
143
268
|
}
|
|
144
|
-
const
|
|
269
|
+
const [protection, declined] = await remote;
|
|
145
270
|
const sources = budgetSources([
|
|
146
271
|
...readAgentInstructions(root),
|
|
147
272
|
...readDecisionDocs(root),
|
|
@@ -149,43 +274,31 @@ export async function buildLocalDigest(root, graph, opts = {}) {
|
|
|
149
274
|
...readCodifiedRules(root),
|
|
150
275
|
...readReverts(root),
|
|
151
276
|
...readTestNames(symbols.map((s) => ({ name: s.name, path: s.path }))),
|
|
152
|
-
...
|
|
153
|
-
...
|
|
277
|
+
...protection,
|
|
278
|
+
...declined,
|
|
154
279
|
]);
|
|
155
280
|
const digest = buildDigest({
|
|
156
|
-
owner:
|
|
157
|
-
name:
|
|
158
|
-
headSha:
|
|
159
|
-
defaultBranch: branch,
|
|
160
|
-
isPrivate: await isPrivate(
|
|
281
|
+
owner: ctx.owner,
|
|
282
|
+
name: ctx.name,
|
|
283
|
+
headSha: ctx.headSha,
|
|
284
|
+
defaultBranch: ctx.branch,
|
|
285
|
+
isPrivate: await ctx.isPrivate(),
|
|
161
286
|
commits,
|
|
162
287
|
threads,
|
|
163
288
|
symbols,
|
|
164
289
|
sources,
|
|
165
290
|
autoApprove: opts.autoApprove ?? true,
|
|
291
|
+
agents: pickedAgents(root),
|
|
166
292
|
});
|
|
167
293
|
return { digest, warning };
|
|
168
294
|
}
|
|
169
|
-
/**
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
"content-type": "application/json",
|
|
178
|
-
accept: "application/json",
|
|
179
|
-
},
|
|
180
|
-
body: JSON.stringify(digest),
|
|
181
|
-
});
|
|
182
|
-
const text = await res.text();
|
|
183
|
-
if (!res.ok)
|
|
184
|
-
return { error: `the brain refused the ingest: ${res.status} ${text.slice(0, 200)}` };
|
|
185
|
-
return { jobId: String(JSON.parse(text).job_id ?? "") };
|
|
186
|
-
}
|
|
187
|
-
catch (e) {
|
|
188
|
-
return { error: `could not reach the brain: ${e instanceof Error ? e.message : e}` };
|
|
189
|
-
}
|
|
295
|
+
/**
|
|
296
|
+
* Send a digest to the brain and return the job to poll.
|
|
297
|
+
*
|
|
298
|
+
* Chunked and gzipped when the server advertises both, gzipped in one POST when
|
|
299
|
+
* it advertises only gzip, and today's plain POST otherwise.
|
|
300
|
+
*/
|
|
301
|
+
export async function pushDigest(link, digest, fetchImpl = fetch, caps = {}, opts = {}) {
|
|
302
|
+
return uploadDigest(link, digest, caps, { ...opts, fetchImpl });
|
|
190
303
|
}
|
|
191
304
|
//# sourceMappingURL=push.js.map
|
package/dist/brain/push.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/brain/push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/brain/push.ts"],"names":[],"mappings":"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"}
|
package/dist/brain/signup.d.ts
CHANGED
|
@@ -56,13 +56,57 @@ export declare function webBaseUrl(baseUrl?: string): string;
|
|
|
56
56
|
* built perfectly well. The build screen is the same wait the browser-first
|
|
57
57
|
* flow shows, and it leads to the graph once there is a graph. */
|
|
58
58
|
export declare function brainUrl(brainId: string, baseUrl?: string): string;
|
|
59
|
-
/** Where
|
|
59
|
+
/** Where a trail's suggested context-file changes are reviewed and accepted:
|
|
60
|
+
* the Context files overview, which lists every file the repo's agents read
|
|
61
|
+
* (CLAUDE.md, AGENTS.md, Cursor rules, folder files, skills) with what waits
|
|
62
|
+
* on each. Needs a Trail that has the page (NanoNets/assign#2957). */
|
|
63
|
+
export declare function reviewUrl(brainId: string, baseUrl?: string): string;
|
|
64
|
+
/** Where to send the browser for a repo's brain.
|
|
65
|
+
*
|
|
66
|
+
* No port when an agent runs the push: nothing stays listening on loopback, so
|
|
67
|
+
* Trail keeps the trail it made under `state` and graft asks for it by that. */
|
|
60
68
|
export declare function signupUrl(opts: {
|
|
61
69
|
repo: string;
|
|
62
|
-
port
|
|
70
|
+
port?: number;
|
|
63
71
|
state: string;
|
|
64
72
|
baseUrl?: string;
|
|
65
73
|
}): string;
|
|
74
|
+
/** A fresh state for a sign-up link: 24 random bytes, which is what Trail
|
|
75
|
+
* accepts and what makes the link impossible to guess. */
|
|
76
|
+
export declare function newSignupState(): string;
|
|
77
|
+
/** How long one agent-run push waits for the sign-up. Under the two minutes an
|
|
78
|
+
* agent gives a command by default, so the wait ends with a message it can read
|
|
79
|
+
* rather than a killed process. */
|
|
80
|
+
export declare const AGENT_WAIT_MS: number;
|
|
81
|
+
/** How often it asks. */
|
|
82
|
+
export declare const AGENT_POLL_MS = 2000;
|
|
83
|
+
/** How long a saved state is worth asking about: a minute under the fifteen
|
|
84
|
+
* Trail keeps an unclaimed sign-up, so graft never waits on one Trail dropped. */
|
|
85
|
+
export declare const PENDING_SIGNUP_TTL_MS: number;
|
|
86
|
+
/** Why asking stopped short of a link. */
|
|
87
|
+
export type ClaimFailure = "expired" | "unsupported";
|
|
88
|
+
export type ClaimResult = {
|
|
89
|
+
link: BrainLink;
|
|
90
|
+
} | {
|
|
91
|
+
pending: true;
|
|
92
|
+
} | {
|
|
93
|
+
error: string;
|
|
94
|
+
reason: ClaimFailure;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Ask Trail once whether the sign-up for `state` has finished.
|
|
98
|
+
*
|
|
99
|
+
* A network error or a server error counts as "not yet": one bad request in a
|
|
100
|
+
* ninety-second wait is not a reason to give up on it.
|
|
101
|
+
*/
|
|
102
|
+
export declare function claimSignup(state: string, apiBase: string, fetchImpl?: typeof fetch): Promise<ClaimResult>;
|
|
103
|
+
/** Ask until the sign-up finishes, Trail says it never will, or `timeoutMs`
|
|
104
|
+
* passes — which comes back as `{ pending: true }`. */
|
|
105
|
+
export declare function waitForSignup(state: string, apiBase: string, opts?: {
|
|
106
|
+
timeoutMs?: number;
|
|
107
|
+
intervalMs?: number;
|
|
108
|
+
fetchImpl?: typeof fetch;
|
|
109
|
+
}): Promise<ClaimResult>;
|
|
66
110
|
/** Open the user's browser, best effort. A machine with no opener is not an
|
|
67
111
|
* error: the URL is printed too, and that is the fallback everywhere.
|
|
68
112
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signup.d.ts","sourceRoot":"","sources":["../../src/brain/signup.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAU3C;uEACuE;AACvE,eAAO,MAAM,kBAAkB,QAAgB,CAAC;AAEhD,4CAA4C;AAC5C,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,cAAc,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAAC;AAE5F,MAAM,WAAW,OAAO;IACtB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACjD,mDAAmD;IACnD,KAAK,IAAI,IAAI,CAAC;CACf;AAoBD;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"signup.d.ts","sourceRoot":"","sources":["../../src/brain/signup.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAU3C;uEACuE;AACvE,eAAO,MAAM,kBAAkB,QAAgB,CAAC;AAEhD,4CAA4C;AAC5C,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,cAAc,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAAC;AAE5F,MAAM,WAAW,OAAO;IACtB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACjD,mDAAmD;IACnD,KAAK,IAAI,IAAI,CAAC;CACf;AAoBD;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAwFrD;AAED;;;uEAGuE;AACvE,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;;;;;kEAYkE;AAClE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;;sEAGsE;AACtE,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED;;;gFAGgF;AAChF,wBAAgB,SAAS,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAMxG;AAgBD;0DAC0D;AAC1D,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;mCAEmC;AACnC,eAAO,MAAM,aAAa,QAAY,CAAC;AAEvC,yBAAyB;AACzB,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC;kFACkF;AAClF,eAAO,MAAM,qBAAqB,QAAiB,CAAC;AAEpD,0CAA0C;AAC1C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,aAAa,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC;AAE5G;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA6BvH;AAED;uDACuD;AACvD,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAAO,GAC/E,OAAO,CAAC,WAAW,CAAC,CAStB;AAED;;;;;2BAK2B;AAC3B,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAQ7C"}
|
package/dist/brain/signup.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Getting a brain without leaving the terminal.
|
|
3
3
|
*
|
|
4
4
|
* Until now a brain could only begin in the browser. You signed up on Trail, it
|
|
5
|
-
* created the brain, and handed you a `graft init --
|
|
5
|
+
* created the brain, and handed you a `graft init --trail <id>:<token>` line to
|
|
6
6
|
* paste. That is the right way round when the website is where you already are,
|
|
7
7
|
* and the wrong way round when you are standing in a repository with graft
|
|
8
8
|
* already installed — which is where most people meet graft first.
|
|
9
9
|
*
|
|
10
|
-
* So `graft
|
|
10
|
+
* So `graft trail push` on an unlinked repo starts here instead of stopping.
|
|
11
11
|
* Graft opens a listener on loopback, sends the browser to Trail carrying the
|
|
12
12
|
* repository it is standing in and the port to answer on, and waits. Trail does
|
|
13
13
|
* the signing up, makes a brain for that repository, and redirects back to the
|
|
@@ -47,8 +47,8 @@ function sameState(got, want) {
|
|
|
47
47
|
* about to close, so there is nothing to style around. */
|
|
48
48
|
function donePage(ok) {
|
|
49
49
|
const msg = ok
|
|
50
|
-
? "Your
|
|
51
|
-
: "That
|
|
50
|
+
? "Your trail is connected. Return to your terminal — the push is already running."
|
|
51
|
+
: "That sign-up doesn't match this terminal. Run graft trail push again.";
|
|
52
52
|
return `<!doctype html><meta charset="utf-8"><title>graft</title><body style="font:15px/1.5 system-ui,sans-serif;margin:3rem auto;max-width:32rem;color:#1F2129"><p>${msg}</p><p style="color:#676767">You can close this tab.</p>`;
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
@@ -82,7 +82,7 @@ export async function startHandoff() {
|
|
|
82
82
|
if (!brainId || !token) {
|
|
83
83
|
res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
|
|
84
84
|
res.end(donePage(false));
|
|
85
|
-
settle({ error: "
|
|
85
|
+
settle({ error: "sign-up came back incomplete · nothing was sent — run graft trail push again", reason: "bad_callback" });
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
88
88
|
// 303 so the browser issues a plain GET, and Location built from
|
|
@@ -117,7 +117,10 @@ export async function startHandoff() {
|
|
|
117
117
|
async wait(timeoutMs = HANDOFF_TIMEOUT_MS) {
|
|
118
118
|
let timer;
|
|
119
119
|
const timeout = new Promise((resolve) => {
|
|
120
|
-
timer = setTimeout(() => resolve({
|
|
120
|
+
timer = setTimeout(() => resolve({
|
|
121
|
+
error: `no sign-up after ${timeoutMs >= 60_000 ? `${Math.round(timeoutMs / 60_000)} minutes` : `${Math.max(1, Math.round(timeoutMs / 1000))} seconds`} · nothing was sent — run graft trail push again`,
|
|
122
|
+
reason: "timed_out",
|
|
123
|
+
}), timeoutMs);
|
|
121
124
|
// The timer must not hold the process open once the browser has answered.
|
|
122
125
|
timer.unref?.();
|
|
123
126
|
});
|
|
@@ -155,17 +158,104 @@ export function webBaseUrl(baseUrl) {
|
|
|
155
158
|
export function brainUrl(brainId, baseUrl) {
|
|
156
159
|
return `${webBaseUrl(baseUrl)}/get-started?step=build&brain=${encodeURIComponent(brainId)}`;
|
|
157
160
|
}
|
|
158
|
-
/** Where
|
|
161
|
+
/** Where a trail's suggested context-file changes are reviewed and accepted:
|
|
162
|
+
* the Context files overview, which lists every file the repo's agents read
|
|
163
|
+
* (CLAUDE.md, AGENTS.md, Cursor rules, folder files, skills) with what waits
|
|
164
|
+
* on each. Needs a Trail that has the page (NanoNets/assign#2957). */
|
|
165
|
+
export function reviewUrl(brainId, baseUrl) {
|
|
166
|
+
return `${webBaseUrl(baseUrl)}/brain/${encodeURIComponent(brainId)}/context-files`;
|
|
167
|
+
}
|
|
168
|
+
/** Where to send the browser for a repo's brain.
|
|
169
|
+
*
|
|
170
|
+
* No port when an agent runs the push: nothing stays listening on loopback, so
|
|
171
|
+
* Trail keeps the trail it made under `state` and graft asks for it by that. */
|
|
159
172
|
export function signupUrl(opts) {
|
|
160
173
|
const base = webBaseUrl(opts.baseUrl);
|
|
161
|
-
const q = new URLSearchParams({
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
graft_state: opts.state,
|
|
166
|
-
});
|
|
174
|
+
const q = new URLSearchParams({ step: "repo", graft_repo: opts.repo });
|
|
175
|
+
if (opts.port !== undefined)
|
|
176
|
+
q.set("graft_port", String(opts.port));
|
|
177
|
+
q.set("graft_state", opts.state);
|
|
167
178
|
return `${base}/get-started?${q.toString()}`;
|
|
168
179
|
}
|
|
180
|
+
/*
|
|
181
|
+
* Signing up when an agent runs the push.
|
|
182
|
+
*
|
|
183
|
+
* Claude Code, Cursor and the rest run `graft trail push` with no terminal, and
|
|
184
|
+
* show the person nothing until the command exits. A loopback listener cannot
|
|
185
|
+
* work there: the link would sit unseen inside a running command, and anything
|
|
186
|
+
* the browser is sent back to is gone by the time the person finishes signing
|
|
187
|
+
* up. So the push runs in two short steps instead. The first opens the sign-up
|
|
188
|
+
* page, saves the state it put in the link, and exits at once so the agent can
|
|
189
|
+
* tell the person what to do. The next asks Trail every couple of seconds,
|
|
190
|
+
* by that state, whether the sign-up has finished, and carries on with the push
|
|
191
|
+
* when it has.
|
|
192
|
+
*/
|
|
193
|
+
/** A fresh state for a sign-up link: 24 random bytes, which is what Trail
|
|
194
|
+
* accepts and what makes the link impossible to guess. */
|
|
195
|
+
export function newSignupState() {
|
|
196
|
+
return randomBytes(24).toString("base64url");
|
|
197
|
+
}
|
|
198
|
+
/** How long one agent-run push waits for the sign-up. Under the two minutes an
|
|
199
|
+
* agent gives a command by default, so the wait ends with a message it can read
|
|
200
|
+
* rather than a killed process. */
|
|
201
|
+
export const AGENT_WAIT_MS = 90 * 1000;
|
|
202
|
+
/** How often it asks. */
|
|
203
|
+
export const AGENT_POLL_MS = 2000;
|
|
204
|
+
/** How long a saved state is worth asking about: a minute under the fifteen
|
|
205
|
+
* Trail keeps an unclaimed sign-up, so graft never waits on one Trail dropped. */
|
|
206
|
+
export const PENDING_SIGNUP_TTL_MS = 14 * 60 * 1000;
|
|
207
|
+
/**
|
|
208
|
+
* Ask Trail once whether the sign-up for `state` has finished.
|
|
209
|
+
*
|
|
210
|
+
* A network error or a server error counts as "not yet": one bad request in a
|
|
211
|
+
* ninety-second wait is not a reason to give up on it.
|
|
212
|
+
*/
|
|
213
|
+
export async function claimSignup(state, apiBase, fetchImpl = fetch) {
|
|
214
|
+
let res;
|
|
215
|
+
try {
|
|
216
|
+
res = await fetchImpl(`${apiBase}/api/public/graft-handoffs/claim`, {
|
|
217
|
+
method: "POST",
|
|
218
|
+
headers: { "content-type": "application/json" },
|
|
219
|
+
body: JSON.stringify({ state }),
|
|
220
|
+
signal: AbortSignal.timeout(10_000),
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
return { pending: true };
|
|
225
|
+
}
|
|
226
|
+
if (res.status === 200) {
|
|
227
|
+
const body = (await res.json().catch(() => ({})));
|
|
228
|
+
if (body.brain_id && body.token)
|
|
229
|
+
return { link: { brainId: body.brain_id, token: body.token } };
|
|
230
|
+
return { pending: true };
|
|
231
|
+
}
|
|
232
|
+
await res.body?.cancel().catch(() => undefined);
|
|
233
|
+
if (res.status === 410) {
|
|
234
|
+
return { error: "that sign-up link was already used or has expired · run graft trail push again for a new one", reason: "expired" };
|
|
235
|
+
}
|
|
236
|
+
// An older Trail, without the route. Waiting on it would never end.
|
|
237
|
+
if (res.status === 404 || res.status === 405) {
|
|
238
|
+
return {
|
|
239
|
+
error: "this Trail can't hand a sign-up to an agent yet · run graft trail push in a terminal, or graft trail connect <trailId>:<token>",
|
|
240
|
+
reason: "unsupported",
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
return { pending: true };
|
|
244
|
+
}
|
|
245
|
+
/** Ask until the sign-up finishes, Trail says it never will, or `timeoutMs`
|
|
246
|
+
* passes — which comes back as `{ pending: true }`. */
|
|
247
|
+
export async function waitForSignup(state, apiBase, opts = {}) {
|
|
248
|
+
const deadline = Date.now() + (opts.timeoutMs ?? AGENT_WAIT_MS);
|
|
249
|
+
const interval = opts.intervalMs ?? AGENT_POLL_MS;
|
|
250
|
+
for (;;) {
|
|
251
|
+
const got = await claimSignup(state, apiBase, opts.fetchImpl);
|
|
252
|
+
if (!("pending" in got))
|
|
253
|
+
return got;
|
|
254
|
+
if (Date.now() + interval > deadline)
|
|
255
|
+
return got;
|
|
256
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
169
259
|
/** Open the user's browser, best effort. A machine with no opener is not an
|
|
170
260
|
* error: the URL is printed too, and that is the fallback everywhere.
|
|
171
261
|
*
|
package/dist/brain/signup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signup.js","sourceRoot":"","sources":["../../src/brain/signup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAe,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAI3D;;;;;6EAK6E;AAC7E,MAAM,oBAAoB,GAAG,yBAAyB,CAAC;AAEvD;uEACuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhD,4CAA4C;AAC5C,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAyB/C,4DAA4D;AAC5D,SAAS,SAAS,CAAC,GAAW,EAAE,IAAY;IAC1C,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED;;0DAE0D;AAC1D,SAAS,QAAQ,CAAC,EAAW;IAC3B,MAAM,GAAG,GAAG,EAAE;QACZ,CAAC,CAAC,iFAAiF;QACnF,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"signup.js","sourceRoot":"","sources":["../../src/brain/signup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { RepoDigest } from "../app/history.js";
|
|
2
|
+
import { type BrainLink } from "./link.js";
|
|
3
|
+
/** The size of one chunk: the index-th slice of the gzip is bytes [i*CHUNK, (i+1)*CHUNK). */
|
|
4
|
+
export declare const CHUNK_BYTES: number;
|
|
5
|
+
/** Chunks in flight at once. */
|
|
6
|
+
export declare const CHUNK_CONCURRENCY = 4;
|
|
7
|
+
/** Waits before each retry. Four retries, so five attempts in all. */
|
|
8
|
+
export declare const RETRY_DELAYS_MS: readonly [500, 1000, 2000, 4000];
|
|
9
|
+
/** What the server said it accepts, from GET /repo. */
|
|
10
|
+
export interface UploadCaps {
|
|
11
|
+
/** `gzip_upload: true` — POST /repo takes `Content-Encoding: gzip`. */
|
|
12
|
+
gzip?: boolean;
|
|
13
|
+
/** `chunked_upload: true` — the /repo/uploads routes exist. */
|
|
14
|
+
chunked?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface UploadOptions {
|
|
17
|
+
fetchImpl?: typeof fetch;
|
|
18
|
+
sleep?: (ms: number) => Promise<void>;
|
|
19
|
+
chunkBytes?: number;
|
|
20
|
+
concurrency?: number;
|
|
21
|
+
}
|
|
22
|
+
export type UploadResult = {
|
|
23
|
+
jobId: string;
|
|
24
|
+
} | {
|
|
25
|
+
error: string;
|
|
26
|
+
};
|
|
27
|
+
/** The digest as the exact bytes a single POST would carry, gzipped. */
|
|
28
|
+
export declare function gzipDigest(digest: RepoDigest): Promise<Buffer>;
|
|
29
|
+
/**
|
|
30
|
+
* The single POST to /repo — gzipped when the server takes it, plain otherwise.
|
|
31
|
+
* Not retried: a repeated POST of a whole ingest is not idempotent, and a 409
|
|
32
|
+
* for "already running" on the retry would read as a refusal.
|
|
33
|
+
*/
|
|
34
|
+
export declare function postDigestOnce(link: BrainLink, digest: RepoDigest, opts?: {
|
|
35
|
+
gzip?: boolean;
|
|
36
|
+
fetchImpl?: typeof fetch;
|
|
37
|
+
query?: string;
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
}): Promise<Response>;
|
|
40
|
+
/**
|
|
41
|
+
* Upload the full digest by whichever route the server advertises.
|
|
42
|
+
*
|
|
43
|
+
* Chunked when `caps.chunked`; if the upload session cannot even be opened
|
|
44
|
+
* (a 404 from a server that advertised the flag but not the route), it falls
|
|
45
|
+
* back to the single POST rather than failing a push that would otherwise work.
|
|
46
|
+
*/
|
|
47
|
+
export declare function uploadDigest(link: BrainLink, digest: RepoDigest, caps: UploadCaps, opts?: UploadOptions): Promise<UploadResult>;
|
|
48
|
+
/**
|
|
49
|
+
* The chunked route:
|
|
50
|
+
*
|
|
51
|
+
* POST /repo/uploads {stage, auto_approve, chunks, bytes} → {upload_id}
|
|
52
|
+
* PUT /repo/uploads/:id/chunks/:index raw gzip slice, idempotent → 204
|
|
53
|
+
* POST /repo/uploads/:id/complete → today's /repo response
|
|
54
|
+
*
|
|
55
|
+
* `{fallback: true}` means the session could not be opened and nothing was
|
|
56
|
+
* sent, so the caller may use the single POST instead.
|
|
57
|
+
*/
|
|
58
|
+
export declare function uploadChunked(link: BrainLink, digest: RepoDigest, opts?: UploadOptions): Promise<UploadResult | {
|
|
59
|
+
fallback: true;
|
|
60
|
+
}>;
|
|
61
|
+
//# sourceMappingURL=upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/brain/upload.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAIvD,6FAA6F;AAC7F,eAAO,MAAM,WAAW,QAAc,CAAC;AACvC,gCAAgC;AAChC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,sEAAsE;AACtE,eAAO,MAAM,eAAe,kCAAmC,CAAC;AAEhE,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,uEAAuE;IACvE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAIjE,wEAAwE;AACxE,wBAAsB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpE;AAmDD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1F,OAAO,CAAC,QAAQ,CAAC,CAanB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAChB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,YAAY,CAAC,CAUvB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,YAAY,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC,CA0F5C"}
|