@onepointfour-packs/flaredeck-agent 0.2.38 → 0.2.39

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.
Files changed (84) hide show
  1. package/dist/agent.d.ts +42 -3
  2. package/dist/agent.js +84 -6
  3. package/dist/agent.js.map +1 -1
  4. package/dist/automode.js +43 -3
  5. package/dist/automode.js.map +1 -1
  6. package/dist/branches.d.ts +12 -1
  7. package/dist/branches.js +13 -3
  8. package/dist/branches.js.map +1 -1
  9. package/dist/browser.d.ts +52 -0
  10. package/dist/browser.js +185 -17
  11. package/dist/browser.js.map +1 -1
  12. package/dist/config.d.ts +6 -0
  13. package/dist/config.js +36 -2
  14. package/dist/config.js.map +1 -1
  15. package/dist/credentials.d.ts +217 -0
  16. package/dist/credentials.js +332 -0
  17. package/dist/credentials.js.map +1 -0
  18. package/dist/engine-antigravity.js +2 -0
  19. package/dist/engine-antigravity.js.map +1 -1
  20. package/dist/engine-claude.js +14 -2
  21. package/dist/engine-claude.js.map +1 -1
  22. package/dist/engine.d.ts +19 -0
  23. package/dist/engine.js.map +1 -1
  24. package/dist/environment.d.ts +13 -1
  25. package/dist/environment.js +35 -2
  26. package/dist/environment.js.map +1 -1
  27. package/dist/envtools.d.ts +58 -0
  28. package/dist/envtools.js +151 -0
  29. package/dist/envtools.js.map +1 -0
  30. package/dist/flaredeck.d.ts +24 -0
  31. package/dist/flaredeck.js +20 -0
  32. package/dist/flaredeck.js.map +1 -1
  33. package/dist/github.d.ts +2 -0
  34. package/dist/github.js +4 -0
  35. package/dist/github.js.map +1 -1
  36. package/dist/githubauth.d.ts +11 -1
  37. package/dist/githubauth.js +82 -16
  38. package/dist/githubauth.js.map +1 -1
  39. package/dist/hydrate.d.ts +76 -0
  40. package/dist/hydrate.js +77 -0
  41. package/dist/hydrate.js.map +1 -0
  42. package/dist/limits.d.ts +184 -0
  43. package/dist/limits.js +251 -0
  44. package/dist/limits.js.map +1 -0
  45. package/dist/main.js +121 -18
  46. package/dist/main.js.map +1 -1
  47. package/dist/picker.js +50 -4
  48. package/dist/picker.js.map +1 -1
  49. package/dist/preflight.d.ts +43 -0
  50. package/dist/preflight.js +133 -19
  51. package/dist/preflight.js.map +1 -1
  52. package/dist/runs.d.ts +11 -3
  53. package/dist/runs.js +41 -4
  54. package/dist/runs.js.map +1 -1
  55. package/dist/serve.js +956 -113
  56. package/dist/serve.js.map +1 -1
  57. package/dist/session.d.ts +51 -0
  58. package/dist/session.js +145 -0
  59. package/dist/session.js.map +1 -0
  60. package/dist/settle.d.ts +18 -0
  61. package/dist/settle.js +39 -0
  62. package/dist/settle.js.map +1 -0
  63. package/dist/signin.d.ts +47 -0
  64. package/dist/signin.js +331 -0
  65. package/dist/signin.js.map +1 -0
  66. package/dist/stream.d.ts +6 -0
  67. package/dist/stream.js +44 -3
  68. package/dist/stream.js.map +1 -1
  69. package/dist/subscriptions.d.ts +115 -0
  70. package/dist/subscriptions.js +140 -0
  71. package/dist/subscriptions.js.map +1 -0
  72. package/dist/ui.d.ts +11 -0
  73. package/dist/ui.js +6 -1
  74. package/dist/ui.js.map +1 -1
  75. package/dist/usage.d.ts +105 -0
  76. package/dist/usage.js +348 -0
  77. package/dist/usage.js.map +1 -0
  78. package/dist/wall.d.ts +35 -0
  79. package/dist/wall.js +94 -0
  80. package/dist/wall.js.map +1 -0
  81. package/dist/worktree.d.ts +19 -0
  82. package/dist/worktree.js +179 -4
  83. package/dist/worktree.js.map +1 -1
  84. package/package.json +1 -1
package/dist/usage.js ADDED
@@ -0,0 +1,348 @@
1
+ /**
2
+ * Asking a Claude subscription how much of itself is left.
3
+ *
4
+ * Everything else here learns about limits by being told: `rate_limit_event` arrives mid-run,
5
+ * and the text paths only appear once a cap has already been hit. That is enough to ROTATE off
6
+ * a dead subscription, which is what the user did by hand — but not enough to route by headroom,
7
+ * because by the time you know, the run has already failed.
8
+ *
9
+ * `/usage` is the missing half. It is a real slash command in the CLI, it runs through the SDK
10
+ * the same way `/goal` already does in engine-claude.ts, and it answers on demand. So FlareDeck
11
+ * can ask each subscription where it stands before choosing one, instead of discovering it
12
+ * afterwards.
13
+ *
14
+ * WHAT IT COSTS: a turn, with no model work beyond rendering a local command — but not nothing.
15
+ * It is for a scheduled refresh, not for every run.
16
+ *
17
+ * STRUCTURED FIRST, PROSE ONLY AS A FALLBACK. `/usage` attaches a `usage_report` to the
18
+ * synthetic assistant message that carries its text, and that is what is read: server-sent rows
19
+ * with a `kind` ('session', 'weekly_all', 'weekly_scoped'), a percent, and an ISO `resets_at`
20
+ * complete with offset. The SDK's own instruction is to "classify a row on this, never on a
21
+ * label" — which is exactly what an earlier version of this file did, matching "Current
22
+ * session" and "Current week" and inferring local time and a year the text never stated.
23
+ *
24
+ * The prose parser is kept because the SDK documents the text as the canonical fallback for
25
+ * CLIs too old to attach the report. It is written to fail SILENTLY AND COMPLETELY rather than
26
+ * partially: a line it does not recognise yields nothing for that window, and nothing means
27
+ * "unknown", never 0. A wrong number here would route every run at the plan it misread.
28
+ *
29
+ * Not on the init message, whatever the declarations imply: measured on this CLI, init carries
30
+ * no rate_limits, no subscription_type and no account id. Identity comes from `accountInfo()`,
31
+ * which answers without spending a turn at all.
32
+ */
33
+ /**
34
+ * Pull the windows out of what `/usage` printed.
35
+ *
36
+ * The shape it answers with, as measured:
37
+ *
38
+ * Current session: 15% used · resets Oct 10 at 12:10pm (Africa/Johannesburg)
39
+ * Current week (all models): 30% used · resets Oct 16 at 4pm (Africa/Johannesburg)
40
+ * Current week (Fable): 7% used · resets Oct 16 at 4pm (Africa/Johannesburg)
41
+ *
42
+ * "Current session" is the five-hour window and "Current week" the seven-day one — the labels
43
+ * are the product's words for them, not new concepts. A per-model week ("Fable") is kept
44
+ * separately rather than folded in, because it can be the one that blocks while the overall
45
+ * week still has room, which is precisely the case worth routing around.
46
+ */
47
+ export function parseUsage(text, now = Date.now()) {
48
+ const out = [];
49
+ for (const raw of String(text ?? '').split('\n')) {
50
+ const line = raw.trim();
51
+ const m = /^Current (session|week)(?:\s*\(([^)]+)\))?:\s*(\d{1,3})%\s*used(?:\s*[·•-]\s*resets\s+(.+?))?$/i.exec(line);
52
+ if (!m)
53
+ continue;
54
+ const [, period = '', scope, pct, when] = m;
55
+ const utilization = Number(pct);
56
+ // A percentage outside 0-100 is a line we have misread, not a reading. Drop it rather than
57
+ // store something that would be acted on.
58
+ if (!Number.isFinite(utilization) || utilization < 0 || utilization > 100)
59
+ continue;
60
+ const model = scope && !/^all models$/i.test(scope) ? scope.trim() : undefined;
61
+ const resetsAt = when ? resetTime(when, now) : undefined;
62
+ out.push({
63
+ window: period.toLowerCase() === 'session' ? 'five_hour' : 'seven_day',
64
+ utilization,
65
+ ...(typeof resetsAt === 'number' ? { resetsAt } : {}),
66
+ ...(model ? { model } : {}),
67
+ });
68
+ }
69
+ return out;
70
+ }
71
+ /**
72
+ * "Oct 10 at 12:10pm (Africa/Johannesburg)" → epoch ms, or undefined.
73
+ *
74
+ * Deliberately undefined rather than a guess when it cannot be read with confidence. A derived
75
+ * reset is worse than none: twenty agents each contributing their own idea of when a window
76
+ * closes pushes it out for most of a day, which is the bug that already bit this ledger once.
77
+ * The YEAR is absent from the text, so it is inferred as the nearest future date — a reset is
78
+ * always ahead, and in late December that is next year.
79
+ */
80
+ function resetTime(text, now) {
81
+ const m = /^([A-Z][a-z]{2})\s+(\d{1,2})\s+at\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)/i.exec(text.trim());
82
+ if (!m)
83
+ return undefined;
84
+ const [, mon, day, hour12, min, ampm] = m;
85
+ const month = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
86
+ .indexOf(String(mon).toLowerCase());
87
+ if (month < 0)
88
+ return undefined;
89
+ let hour = Number(hour12) % 12;
90
+ if (/pm/i.test(String(ampm)))
91
+ hour += 12;
92
+ /* Local time, because the string is in the machine's own zone — `/usage` prints the zone it
93
+ used and it is this machine's. Reading it as UTC would shift every reset by the offset,
94
+ which in Johannesburg is two hours of a five-hour window. */
95
+ const here = new Date(now);
96
+ for (const year of [here.getFullYear(), here.getFullYear() + 1]) {
97
+ const t = new Date(year, month, Number(day), hour, Number(min ?? 0), 0, 0).getTime();
98
+ if (t > now)
99
+ return t;
100
+ }
101
+ return undefined;
102
+ }
103
+ /**
104
+ * Run `/usage` against a subscription and read what it says.
105
+ *
106
+ * `token` picks which subscription answers — the same CLAUDE_CODE_OAUTH_TOKEN the run itself
107
+ * would use, so the reading is about the plan that would actually have paid. Without one it
108
+ * reports on whatever this machine is logged in as.
109
+ */
110
+ export async function readUsage(opts) {
111
+ const ask = opts.ask ?? defaultAsk;
112
+ const started = Date.now();
113
+ try {
114
+ const { report, text, seen, getter } = await withTimeout(ask(opts.token), opts.timeoutMs ?? 90_000);
115
+ // The SDK's usage call is the real source — the plan's own percentages and reset times.
116
+ if (getter?.length)
117
+ return getter;
118
+ /* Structured when the CLI attached it, prose only when it did not. Never merged: two
119
+ readings of the same window from two sources would disagree on rounding and on which is
120
+ newer, and the wrong one winning is invisible. */
121
+ const structured = windowsFromReport(report);
122
+ if (structured.length)
123
+ return structured;
124
+ const parsed = parseUsage(text ?? '');
125
+ /* Empty with no error was a black box: "could not read it" and nothing else, so a changed
126
+ SDK response, a timing problem and a refused token all looked the same. Say what came. */
127
+ if (!parsed.length) {
128
+ opts.onEmpty?.(`${Date.now() - started}ms · messages: ${(seen ?? []).join(' ') || 'none'} · ` +
129
+ `usage_report: ${report === undefined ? 'absent' : JSON.stringify(report).slice(0, 200)} · ` +
130
+ `text: ${JSON.stringify((text ?? '').slice(0, 300))}`);
131
+ }
132
+ return parsed;
133
+ }
134
+ catch (e) {
135
+ // Never throws: a failed reading costs a little routing accuracy and the next one tries
136
+ // again. It must not be able to stop a run, which is the whole point of asking early.
137
+ opts.onEmpty?.(`${Date.now() - started}ms · ${e instanceof Error ? e.message : String(e)}`);
138
+ return [];
139
+ }
140
+ }
141
+ /**
142
+ * Ask the SDK's usage call for this plan's windows, on a session that sends no prompt at all.
143
+ *
144
+ * `/usage` sent as a prompt, headless, answers with THIS SESSION's cost ("Total cost: $0.0000 …
145
+ * Usage: 0 input, 0 output") — never the plan's limits. Every read came back empty for that
146
+ * reason, which looked like a timing or token problem. The query handle has a dedicated call that
147
+ * returns the plan's 5-hour and weekly utilisation (0-100) with ISO reset times; it is marked
148
+ * experimental, so a missing or changed method falls back to `/usage` rather than failing.
149
+ *
150
+ * Only the two governing windows are taken. Model-scoped weeks (opus, sonnet) would be ranked as
151
+ * if they stopped the whole plan, which they do not.
152
+ */
153
+ /** What the usage call last answered when it gave no windows — for the log, not for routing. */
154
+ let lastGetterNote = '';
155
+ async function askGetter(token) {
156
+ lastGetterNote = '';
157
+ const { query } = await import('@anthropic-ai/claude-agent-sdk');
158
+ const { readUsage: readHandle } = await import('./limits.js');
159
+ const { ANTHROPIC_API_KEY: _k, ANTHROPIC_AUTH_TOKEN: _t, ...rest } = process.env;
160
+ let release = () => { };
161
+ const held = new Promise((r) => { release = r; });
162
+ // A prompt stream that sends nothing and ends when we are done, so the CLI starts and waits.
163
+ const q = query({
164
+ prompt: (async function* () { await held; })(),
165
+ options: {
166
+ maxTurns: 1,
167
+ // No user settings: the read must not run this machine's hooks or load its MCP servers.
168
+ settingSources: [],
169
+ env: { ...rest, ...(token ? { CLAUDE_CODE_OAUTH_TOKEN: token } : {}) },
170
+ },
171
+ });
172
+ try {
173
+ const reading = await readHandle(q);
174
+ if (!reading) {
175
+ lastGetterNote = 'usage call: no answer (method missing, threw, or unrecognised)';
176
+ return [];
177
+ }
178
+ // False when the token cannot see plan limits — an API key, or an OAuth token without the
179
+ // profile scope, which is what `claude setup-token` mints.
180
+ if (!reading.rateLimitsAvailable) {
181
+ lastGetterNote = `usage call: rate_limits_available=false (subscription ${reading.subscriptionType ?? 'unknown'})`;
182
+ return [];
183
+ }
184
+ const out = [];
185
+ for (const name of ['five_hour', 'seven_day']) {
186
+ const w = reading.windows[name];
187
+ if (!w || typeof w.utilization !== 'number')
188
+ continue;
189
+ out.push({ window: name, utilization: w.utilization, ...(w.resetsAt ? { resetsAt: w.resetsAt } : {}) });
190
+ }
191
+ if (!out.length)
192
+ lastGetterNote = `usage call: available but no 5h/weekly figures (${JSON.stringify(reading.windows).slice(0, 200)})`;
193
+ return out;
194
+ }
195
+ finally {
196
+ release();
197
+ // Drain so the CLI exits rather than lingering; anything it says now is irrelevant.
198
+ void (async () => { try {
199
+ for await (const _ of q) { /* drain */ }
200
+ }
201
+ catch { /* closed */ } })();
202
+ }
203
+ }
204
+ /**
205
+ * The setup-token route: one tiny Haiku reply, read for the rate-limit state it carries.
206
+ *
207
+ * Costs a few hundred tokens of the plan's own quota (~$0.004 equivalent on a real account) — a
208
+ * real request is the only thing that returns the headers. No tools, no settings, one turn.
209
+ */
210
+ async function askProbe(token) {
211
+ const { query } = await import('@anthropic-ai/claude-agent-sdk');
212
+ const { windowsFromRateLimit } = await import('./limits.js');
213
+ const { ANTHROPIC_API_KEY: _k, ANTHROPIC_AUTH_TOKEN: _t, ...rest } = process.env;
214
+ const q = query({
215
+ prompt: 'Reply with the single word OK.',
216
+ options: {
217
+ maxTurns: 1, model: 'haiku', settingSources: [], allowedTools: [],
218
+ env: { ...rest, ...(token ? { CLAUDE_CODE_OAUTH_TOKEN: token } : {}) },
219
+ },
220
+ });
221
+ const found = new Map();
222
+ for await (const m of q) {
223
+ for (const w of windowsFromRateLimit(m))
224
+ found.set(w.window, w);
225
+ if (m['type'] === 'result')
226
+ break;
227
+ }
228
+ return [...found.values()];
229
+ }
230
+ async function defaultAsk(token) {
231
+ const getter = await askGetter(token).catch((e) => { lastGetterNote = `usage call threw: ${e instanceof Error ? e.message : String(e)}`; return []; });
232
+ if (getter.length)
233
+ return { getter };
234
+ // No usage scope (a setup-token): ask the plan itself, through one tiny request.
235
+ const probed = await askProbe(token).catch((e) => { lastGetterNote += ` · probe threw: ${e instanceof Error ? e.message : String(e)}`; return []; });
236
+ if (probed.length)
237
+ return { getter: probed };
238
+ const { query } = await import('@anthropic-ai/claude-agent-sdk');
239
+ const { ANTHROPIC_API_KEY: _drop, ...rest } = process.env;
240
+ const say = (text) => ({ type: 'user', message: { role: 'user', content: text }, parent_tool_use_id: null });
241
+ const q = query({
242
+ prompt: (async function* () { yield say('/usage'); })(),
243
+ options: {
244
+ maxTurns: 1,
245
+ env: { ...rest, ...(token ? { CLAUDE_CODE_OAUTH_TOKEN: token } : {}) },
246
+ },
247
+ });
248
+ /* The report rides the synthetic ASSISTANT message that carries the text, not the result —
249
+ a wrapper-level sibling, deliberately outside message.content so it is never replayed to
250
+ the model. Reading the result alone finds nothing, which is how this was wrong once. */
251
+ let report;
252
+ let text = '';
253
+ // Every message type that came back, for the log when nothing usable did.
254
+ const seen = [];
255
+ for await (const m of q) {
256
+ seen.push(`${m['type']}${m['subtype'] ? `/${m['subtype']}` : ''}${m['usage_report'] ? '+report' : ''}`);
257
+ if (m['usage_report'])
258
+ report = m['usage_report'];
259
+ if (m['type'] === 'assistant' && !text) {
260
+ const c = m['message']?.content;
261
+ const t = Array.isArray(c) ? c.map((b) => b?.text ?? '').join('') : String(c ?? '');
262
+ if (t)
263
+ text = t;
264
+ }
265
+ if (m['type'] === 'result') {
266
+ text = String(m['result'] ?? '') || text;
267
+ break;
268
+ }
269
+ }
270
+ return { ...(report ? { report } : {}), text, seen: [lastGetterNote || 'usage call: nothing', ...seen] };
271
+ }
272
+ function withTimeout(p, ms) {
273
+ return Promise.race([p, new Promise((_r, reject) => setTimeout(() => reject(new Error('timed out')), ms))]);
274
+ }
275
+ /**
276
+ * The rows `/usage` attaches, mapped onto the ledger's window names.
277
+ *
278
+ * Classified on `kind`, never on a label — the SDK says so outright, and a label is a display
279
+ * string that can be reworded without warning. A `weekly_scoped` row is kept separate rather
280
+ * than folded into the weekly total: it can block while the overall week still has room, which
281
+ * is the case worth routing around.
282
+ */
283
+ export function windowsFromReport(report) {
284
+ const rows = report?.rate_limits?.limits;
285
+ if (!Array.isArray(rows))
286
+ return [];
287
+ const out = [];
288
+ for (const row of rows) {
289
+ const percent = row?.percent;
290
+ if (typeof percent !== 'number' || !Number.isFinite(percent) || percent < 0 || percent > 100)
291
+ continue;
292
+ const kind = String(row?.kind ?? '');
293
+ const model = row?.scope?.model?.display_name;
294
+ /**
295
+ * A scoped week gets its OWN window name, not `seven_day` with a model beside it.
296
+ *
297
+ * The first version mapped every `weekly*` kind to `seven_day` and relied on the `model`
298
+ * field to tell them apart. Anything keying by window name then collided: in a real
299
+ * reading that is `weekly_all` at 31% and `weekly_scoped` at 7%, and the second overwrote
300
+ * the first — so the ledger believed the week was 7% used when the binding constraint was
301
+ * 31%, and would have routed work to a plan nearly three times fuller than it looked.
302
+ * Distinctness must not depend on a consumer remembering to check a second field.
303
+ */
304
+ const window = kind === 'session' ? 'five_hour'
305
+ : kind === 'weekly_all' ? 'seven_day'
306
+ : kind === 'weekly_scoped' ? `seven_day_scoped:${String(model ?? 'unknown')}`
307
+ : kind;
308
+ if (!window)
309
+ continue;
310
+ // ISO with an offset, so no local-time guessing and no year to infer — the two things the
311
+ // prose path has to do and can get wrong.
312
+ const t = typeof row?.resets_at === 'string' ? Date.parse(row.resets_at) : NaN;
313
+ out.push({
314
+ window,
315
+ utilization: percent,
316
+ ...(Number.isFinite(t) ? { resetsAt: t } : {}),
317
+ ...(typeof model === 'string' && model ? { model } : {}),
318
+ // The server's own word for the row, sent so the ledger never has to infer what this is
319
+ // from a name this file chose. It owns window identity; this just reports.
320
+ ...(kind ? { kind } : {}),
321
+ });
322
+ }
323
+ return out;
324
+ }
325
+ /**
326
+ * Ask which account a token belongs to.
327
+ *
328
+ * Costs no turn — it is answered from the session handshake — so it is cheap enough to call
329
+ * whenever a subscription is added, and it is the only way to tell that two entries in the
330
+ * vault are secretly the same account. It is also what makes a run on this machine's own login
331
+ * attributable, which it otherwise is not.
332
+ */
333
+ export async function readAccount(token) {
334
+ try {
335
+ const { query } = await import('@anthropic-ai/claude-agent-sdk');
336
+ const { ANTHROPIC_API_KEY: _drop, ...rest } = process.env;
337
+ const q = query({
338
+ prompt: (async function* () { })(),
339
+ options: { maxTurns: 1, env: { ...rest, ...(token ? { CLAUDE_CODE_OAUTH_TOKEN: token } : {}) } },
340
+ });
341
+ const info = await q.accountInfo();
342
+ return info ?? null;
343
+ }
344
+ catch {
345
+ return null;
346
+ }
347
+ }
348
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"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"}
package/dist/wall.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Is this page a sign-in wall?
3
+ *
4
+ * Without this, an agent that opens a page it has no session for gets a snapshot of a login form
5
+ * and no idea that is what it is. It then does the worst available thing: reasons about the login
6
+ * page, tries to fill it, invents credentials, or reports the card's feature as missing — because
7
+ * from inside the snapshot, "the screen does not have the thing I was sent to look at" is exactly
8
+ * what a login page looks like.
9
+ *
10
+ * Knowing is what makes the simple flow possible: open the browser, and if it is a wall, ask a
11
+ * person to sign in once. No token parsing, no expiry arithmetic, no guessing from cookies —
12
+ * none of which can tell you whether a server still honours a session anyway. The only reliable
13
+ * check is to use it and look.
14
+ *
15
+ * Ported from Sceneflo (BrowserAgent src/wall.ts), where the signals were learned the hard way:
16
+ * "is there a password box" is wrong on any site built in the last few years, and a visible
17
+ * Logout is the counter-signal that stops an app's own dashboard reading as a wall.
18
+ */
19
+ import type { Page } from 'playwright-core';
20
+ export type Wall = {
21
+ wall: boolean;
22
+ why: string;
23
+ how: 'password' | 'sso' | 'link' | 'confirm' | 'none';
24
+ };
25
+ export declare function signInWall(page: Page): Promise<Wall>;
26
+ /**
27
+ * What to tell the AGENT when it lands on one.
28
+ *
29
+ * Deliberately not Sceneflo's wording. There, a wall it cannot drive is the end of the road. Here
30
+ * it is an ordinary thing with an ordinary remedy — a person signs in once, the session is kept,
31
+ * and every card after this one opens straight into the app. So this says what to do, not what
32
+ * cannot be done, and it is explicit about the two ways to get it wrong: inventing credentials,
33
+ * and reporting the card's own feature as missing because a login page does not have it.
34
+ */
35
+ export declare function wallBrief(w: Wall, url: string, published?: string): string;
package/dist/wall.js ADDED
@@ -0,0 +1,94 @@
1
+ const SCRIPT = `(() => {
2
+ const seen = (el) => {
3
+ if (!el) return false;
4
+ const r = el.getBoundingClientRect();
5
+ if (r.width < 1 || r.height < 1) return false;
6
+ const cs = getComputedStyle(el);
7
+ return cs.visibility !== 'hidden' && cs.display !== 'none' && Number(cs.opacity) > 0.05;
8
+ };
9
+ const words = (el) => (el.getAttribute('aria-label') || el.textContent || '').replace(/\\s+/g, ' ').trim();
10
+
11
+ const controls = Array.from(document.querySelectorAll('a, button, input, select, textarea, [role=button], [role=link]'))
12
+ .filter(seen);
13
+ const pressable = controls.filter((e) => e.matches('button, [role=button], a, input[type=submit], input[type=button]'));
14
+ const labels = pressable.map(words).filter(Boolean);
15
+
16
+ const password = controls.some((e) => e.matches('input[type=password]'));
17
+ const sso = labels.find((t) => /(continue|sign ?in|log ?in|connect)\\s+with\\s+(google|microsoft|apple|github|gitlab|okta|azure|facebook|saml|sso)|single sign|use sso/i.test(t));
18
+ const emailField = controls.some((e) =>
19
+ e.matches('input[type=email]') ||
20
+ (e.matches('input[type=text], input:not([type])') && /e-?mail|username|user name/i.test(
21
+ (e.getAttribute('name') || '') + ' ' + (e.getAttribute('id') || '') + ' ' + (e.getAttribute('placeholder') || '') + ' ' + (e.getAttribute('aria-label') || ''))));
22
+ const magic = labels.find((t) => /magic link|sign-?in link|email me a link|send (me )?(a )?link|one-?time (code|link)|passwordless/i.test(t));
23
+ const finish = labels.find((t) => /finish signing|finish sign|complete (your )?sign|confirm (your )?(e-?mail|address|identity)|verify (your )?(e-?mail|address)|continue signing/i.test(t));
24
+ const logout = labels.find((t) => /^(log ?out|sign ?out)$|\\b(log ?out|sign ?out)\\b/i.test(t) && t.length < 30);
25
+
26
+ return {
27
+ password, sso: sso || '', magic: magic || '', finish: finish || '', emailField, logout: logout || '',
28
+ controls: controls.length,
29
+ };
30
+ })()`;
31
+ /** How much else can be on the page before it stops looking like a wall and starts looking like an app. */
32
+ const QUIET = 25;
33
+ export async function signInWall(page) {
34
+ const r = (await page.evaluate(SCRIPT).catch(() => null));
35
+ if (!r)
36
+ return { wall: false, why: '', how: 'none' };
37
+ /* A password box settles it on its own — nothing but a sign-in has one, however busy the page. */
38
+ if (r.password)
39
+ return { wall: true, how: 'password', why: 'it is asking for a password' };
40
+ /* A visible Logout settles it the other way: a page offering to sign you OUT is signed in. An
41
+ app whose tiles are bare divs can distil to very few formal controls, and a login component
42
+ left in the DOM after sign-in then reads as a wall over a screen showing Logout twice. */
43
+ if (r.logout)
44
+ return { wall: false, why: '', how: 'none' };
45
+ /* A signed-in app often has an SSO button somewhere and dozens of other controls; a wall is a
46
+ page with almost nothing else on it, because there is nothing else you are allowed to do. */
47
+ if (r.controls > QUIET)
48
+ return { wall: false, why: '', how: 'none' };
49
+ if (r.sso)
50
+ return { wall: true, how: 'sso', why: `the way in is “${r.sso}”` };
51
+ if (r.magic && r.emailField)
52
+ return { wall: true, how: 'link', why: `it signs you in by emailing a link (“${r.magic}”)` };
53
+ if (r.finish && r.emailField)
54
+ return { wall: true, how: 'confirm', why: `it wants the address confirming first (“${r.finish}”)` };
55
+ return { wall: false, why: '', how: 'none' };
56
+ }
57
+ /**
58
+ * What to tell the AGENT when it lands on one.
59
+ *
60
+ * Deliberately not Sceneflo's wording. There, a wall it cannot drive is the end of the road. Here
61
+ * it is an ordinary thing with an ordinary remedy — a person signs in once, the session is kept,
62
+ * and every card after this one opens straight into the app. So this says what to do, not what
63
+ * cannot be done, and it is explicit about the two ways to get it wrong: inventing credentials,
64
+ * and reporting the card's own feature as missing because a login page does not have it.
65
+ */
66
+ export function wallBrief(w, url, published = '') {
67
+ const how = w.how === 'sso' ? 'It signs in through another company — Google, Microsoft or similar — which nothing here can drive.'
68
+ : w.how === 'link' ? 'It signs in by emailing a link, which nothing here can read.'
69
+ : w.how === 'confirm' ? 'It is part-way through a sign-in and wants the address confirmed.'
70
+ : 'It wants a username and password.';
71
+ const common = `This is a SIGN-IN WALL, not the page you were looking for: ${w.why}. ${how}\n\n` +
72
+ `Nothing on this screen tells you anything about the card — in particular, the thing you ` +
73
+ `came to look at being absent here means nothing at all.\n\n`;
74
+ /* A project that publishes a way in HAS already answered this, and asking a person for what
75
+ the environment handed you is an interruption for nothing. HR Goat prints dev sign-in URLs
76
+ in its own start script for exactly this moment. */
77
+ if (published) {
78
+ return common +
79
+ `This project published a way in, so use it rather than asking anyone:\n\n${published}\n\n` +
80
+ `Those are test identities for this environment, published by the project itself. If none ` +
81
+ `of them works, say so and ask — but try first.`;
82
+ }
83
+ /* Name the tool. This used to say "ask for a sign-in" and nothing more, which is advice, not a
84
+ door: the agent dutifully wrote a comment, flagged the card and stopped, because asking was
85
+ not something it could DO. A brief that describes an action without naming the call is how a
86
+ capability that exists goes unused. */
87
+ return common +
88
+ `Do not try to sign in, and do not invent credentials.\n\n` +
89
+ `Call request_sign_in instead, with what you were going to check. A person signs in once, ` +
90
+ `the session is kept against the project, and every card after this one opens straight into ` +
91
+ `the app. You do not wait for it: say on the card that it is waiting on a sign-in, and you ` +
92
+ `are brought back automatically once the session lands.`;
93
+ }
94
+ //# sourceMappingURL=wall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wall.js","sourceRoot":"","sources":["../src/wall.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6BV,CAAC;AAEN,2GAA2G;AAC3G,MAAM,KAAK,GAAG,EAAE,CAAC;AAEjB,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAU;IACzC,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAQ,CAAC;IACjE,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAErD,kGAAkG;IAClG,IAAI,CAAC,CAAC,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,6BAA6B,EAAE,CAAC;IAE3F;;gGAE4F;IAC5F,IAAI,CAAC,CAAC,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAE3D;mGAC+F;IAC/F,IAAI,CAAC,CAAC,QAAQ,GAAG,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAErE,IAAI,CAAC,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC;IAC9E,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,wCAAwC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;IAC1H,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,UAAU;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,2CAA2C,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;IAClI,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AAC/C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,CAAO,EAAE,GAAW,EAAE,SAAS,GAAG,EAAE;IAC5D,MAAM,GAAG,GACP,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,oGAAoG;QACtH,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,8DAA8D;YACnF,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,mEAAmE;gBAC3F,CAAC,CAAC,mCAAmC,CAAC;IACxC,MAAM,MAAM,GACV,8DAA8D,CAAC,CAAC,GAAG,KAAK,GAAG,MAAM;QACjF,0FAA0F;QAC1F,6DAA6D,CAAC;IAEhE;;0DAEsD;IACtD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,MAAM;YACX,4EAA4E,SAAS,MAAM;YAC3F,2FAA2F;YAC3F,gDAAgD,CAAC;IACrD,CAAC;IAED;;;6CAGyC;IACzC,OAAO,MAAM;QACX,2DAA2D;QAC3D,2FAA2F;QAC3F,6FAA6F;QAC7F,4FAA4F;QAC5F,wDAAwD,CAAC;AAC7D,CAAC"}
@@ -86,3 +86,22 @@ export declare function uncommittedCount(path: string): Promise<number>;
86
86
  * it left anything behind — a question that must never itself cut a checkout.
87
87
  */
88
88
  export declare function existingWorktree(repo: string, card: string): Promise<Worktree | null>;
89
+ /** Bytes free on the disk holding `path`, or null when the platform cannot say. */
90
+ export declare function freeDiskBytes(path: string): number | null;
91
+ /**
92
+ * Release every card worktree of this repository that has sat unused for `idleMs` and holds
93
+ * nothing that is not already on the remote.
94
+ *
95
+ * releaseWorktree used to run only when an agent finished a turn on a card whose lane was Done,
96
+ * and agents never move a card to Done — a person does, later, when no agent is looking at it. So
97
+ * it almost never ran, and 78 worktrees and 45 GB built up on one machine. This sweeps instead,
98
+ * with the same refusals: uncommitted changes, untracked files or unpublished commits keep a
99
+ * worktree, and so does recent use, because several agents can share one repository's worktrees
100
+ * and the one another agent is in the middle of is not this agent's to take.
101
+ *
102
+ * Releasing loses nothing: a card that comes back is checked out again from what it pushed.
103
+ */
104
+ export declare function sweepWorktrees(repo: string, idleMs: number, onStep: (text: string) => void, keep?: ReadonlySet<string>): Promise<{
105
+ removed: number;
106
+ kept: string[];
107
+ }>;