ai-spend-agent 0.9.0 → 0.9.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/dist/guidedPrompt.d.ts +2 -27
- package/dist/guidedPrompt.js +5 -282
- package/dist/improveFlow.d.ts +34 -4
- package/dist/improveFlow.js +44 -16
- package/dist/index.d.ts +11 -0
- package/dist/index.js +972 -83
- package/dist/projectAccountabilityState.d.ts +6 -7
- package/dist/projectAccountabilityState.js +6 -15
- package/dist/signup.d.ts +272 -0
- package/dist/signup.js +681 -0
- package/dist/statuslineRuntime.js +3 -1
- package/dist/telemetry.d.ts +149 -0
- package/dist/telemetry.js +390 -0
- package/package.json +4 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AcceptedOutcomeV0, type AcceptedOutcomeV0DraftInput, type ApprovalEventV0, type ApprovalEventV0DraftInput, type ConfirmedOwnershipV0 } from "@agent-finops/core";
|
|
1
|
+
import { isCredentialLike, isPathLike, type AcceptedOutcomeV0, type AcceptedOutcomeV0DraftInput, type ApprovalEventV0, type ApprovalEventV0DraftInput, type ConfirmedOwnershipV0 } from "@agent-finops/core";
|
|
2
2
|
export declare const PROJECT_ACCOUNTABILITY_STATE_FILE = "project-accountability.json";
|
|
3
3
|
export declare const PROJECT_ACCOUNTABILITY_STATE_KIND: "aibill.project_accountability_store";
|
|
4
4
|
export declare const PROJECT_ACCOUNTABILITY_STATE_VERSION: 1;
|
|
@@ -85,11 +85,10 @@ export declare function appendProjectApprovalEvent(rootPath: string, input: Omit
|
|
|
85
85
|
*/
|
|
86
86
|
export declare function appendAcceptedProjectOutcome(rootPath: string, value: AcceptedOutcomeV0 | AcceptedOutcomeV0DraftInput): Promise<ProjectAccountabilityStateV1>;
|
|
87
87
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
88
|
+
* The classification FLOOR predicates for the guided-prompt engine live in
|
|
89
|
+
* core (`guidedAnswer.ts`) so the CLI classifier, the MCP draft preview,
|
|
90
|
+
* and this accountability backstop can never drift apart. Re-exported here
|
|
91
|
+
* for existing CLI imports.
|
|
92
92
|
*/
|
|
93
|
-
export
|
|
94
|
-
export declare function isCredentialLike(value: string): boolean;
|
|
93
|
+
export { isCredentialLike, isPathLike };
|
|
95
94
|
//# sourceMappingURL=projectAccountabilityState.d.ts.map
|
|
@@ -5,7 +5,7 @@ import { lstat, mkdir, open, readdir, realpath, rmdir, unlink } from "node:fs/pr
|
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
7
7
|
import { promisify } from "node:util";
|
|
8
|
-
import { CONFIRMED_OWNERSHIP_V0_KIND, MAX_APPROVAL_EVENTS_V0, PROJECT_ECONOMICS_V0_VERSION, appendApprovalEventV0, createAcceptedOutcomeV0, createConfirmedOwnershipV0, createProjectEconomicsReference, parseAcceptedOutcomeV0, parseApprovalEventV0, parseConfirmedOwnershipV0, readSafeStateText, resolveSafeScanRoot, UnsafeStateFileError, writeSafeStateText } from "@agent-finops/core";
|
|
8
|
+
import { CONFIRMED_OWNERSHIP_V0_KIND, isCredentialLike, isPathLike, MAX_APPROVAL_EVENTS_V0, PROJECT_ECONOMICS_V0_VERSION, appendApprovalEventV0, createAcceptedOutcomeV0, createConfirmedOwnershipV0, createProjectEconomicsReference, parseAcceptedOutcomeV0, parseApprovalEventV0, parseConfirmedOwnershipV0, readSafeStateText, resolveSafeScanRoot, UnsafeStateFileError, writeSafeStateText } from "@agent-finops/core";
|
|
9
9
|
export const PROJECT_ACCOUNTABILITY_STATE_FILE = "project-accountability.json";
|
|
10
10
|
export const PROJECT_ACCOUNTABILITY_STATE_KIND = "aibill.project_accountability_store";
|
|
11
11
|
export const PROJECT_ACCOUNTABILITY_STATE_VERSION = 1;
|
|
@@ -794,21 +794,12 @@ function noFollowFlag() {
|
|
|
794
794
|
return typeof constants.O_NOFOLLOW === "number" ? constants.O_NOFOLLOW : 0;
|
|
795
795
|
}
|
|
796
796
|
/**
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
*
|
|
797
|
+
* The classification FLOOR predicates for the guided-prompt engine live in
|
|
798
|
+
* core (`guidedAnswer.ts`) so the CLI classifier, the MCP draft preview,
|
|
799
|
+
* and this accountability backstop can never drift apart. Re-exported here
|
|
800
|
+
* for existing CLI imports.
|
|
801
801
|
*/
|
|
802
|
-
export
|
|
803
|
-
return /^(?:~?[\\/]|\.{1,2}(?:[\\/]|$)|[A-Za-z]:[\\/]|\\\\)/u.test(value) ||
|
|
804
|
-
/(?:^|[\\/])\.\.(?:[\\/]|$)/u.test(value) || value.includes("\\");
|
|
805
|
-
}
|
|
806
|
-
export function isCredentialLike(value) {
|
|
807
|
-
return /(?:sk-(?:ant-|proj-)?|sk_|gh[pousr]_|github_pat_|npm_|AIza|xox[baprs]-|glpat-|AKIA)[A-Za-z0-9_-]{8,}/i
|
|
808
|
-
.test(value) ||
|
|
809
|
-
/(?:api[_ -]?key|access[_ -]?token|auth[_ -]?token|secret|password)\s*[:=]\s*\S+/i
|
|
810
|
-
.test(value);
|
|
811
|
-
}
|
|
802
|
+
export { isCredentialLike, isPathLike };
|
|
812
803
|
function hasUnpairedSurrogate(value) {
|
|
813
804
|
for (let index = 0; index < value.length; index += 1) {
|
|
814
805
|
const code = value.charCodeAt(index);
|
package/dist/signup.d.ts
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI email capture — the launch-list signup lane (v0.9.2).
|
|
3
|
+
*
|
|
4
|
+
* Design: docs/qa-handoff/CLI_CAPTURE_DESIGN.md (see its dated placement
|
|
5
|
+
* addendum). QA verdict (its B/M fixes are mandatory):
|
|
6
|
+
* docs/qa-handoff/CLI_CAPTURE_QA_VERDICT.md.
|
|
7
|
+
*
|
|
8
|
+
* Placement (founder decision 2026-08-24): the ONE ask runs PRE-RECEIPT,
|
|
9
|
+
* DURING the first evidence scan — it fills the first-run wait instead of
|
|
10
|
+
* adding one. The receipt renders when both the human's answer (or skip /
|
|
11
|
+
* timeout / Ctrl-C) and the pipeline resolve; consent, when an email was
|
|
12
|
+
* typed, renders strictly AFTER the receipt.
|
|
13
|
+
*
|
|
14
|
+
* Hard rules encoded here:
|
|
15
|
+
* - The payload is EXACTLY {email, ref} — the deployed asktilden.com route
|
|
16
|
+
* reads `ref` (not `sourceRef`) and normalizes anything failing
|
|
17
|
+
* /^[a-z0-9][a-z0-9_-]{0,63}$/ (dots included) to "direct" (verdict B1).
|
|
18
|
+
* - Consent shows the literal payload JSON; the sent line claims only the
|
|
19
|
+
* payload layer, never "nothing else left this machine" (verdict B2).
|
|
20
|
+
* - One POST attempt, 3s timeout, no retry, no queue, and the typed email is
|
|
21
|
+
* never persisted on failure.
|
|
22
|
+
* - Every read is timeout-guarded and can never eat a skip: a timeout or
|
|
23
|
+
* Ctrl-C records NO lifetime skip (verdict M3).
|
|
24
|
+
* - Skip = two empty Enters with one declarative nudge between them; the
|
|
25
|
+
* completed pair counts as ONE lifetime skip. This is the founder-approved
|
|
26
|
+
* ceiling: no further skip friction may be added, and removal of skip is
|
|
27
|
+
* refused by design.
|
|
28
|
+
* - Never-ask state lives in ~/.aibill/signup.json (the existing home dir —
|
|
29
|
+
* verdict M5) and fails CLOSED to never-ask on corrupt/readonly state.
|
|
30
|
+
*/
|
|
31
|
+
export declare const waitlistUrl = "https://asktilden.com/api/waitlist";
|
|
32
|
+
/** Closed payload type — adding a field here must fail the creep-guard test. */
|
|
33
|
+
export type WaitlistPayload = {
|
|
34
|
+
email: string;
|
|
35
|
+
ref: string;
|
|
36
|
+
};
|
|
37
|
+
export type WaitlistRefSurface = "receipt" | "signup";
|
|
38
|
+
export declare const deployedRefPattern: RegExp;
|
|
39
|
+
export declare function normalizeWaitlistEmail(raw: string): string | undefined;
|
|
40
|
+
/** `--ref` allowlist: lowercase alphanumerics and dashes, 1–24 chars. */
|
|
41
|
+
export declare function sanitizeSignupRefTag(raw: string): string | undefined;
|
|
42
|
+
export declare function buildWaitlistRef(surface: WaitlistRefSurface, tag?: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* The exact bytes sent — key order pinned. Payload creep (adding os/plan/
|
|
45
|
+
* version data, or stuffing values into ref) fails the CI creep-guard test;
|
|
46
|
+
* see docs/qa-handoff/CLI_CAPTURE_DESIGN.md §3c before touching this.
|
|
47
|
+
*/
|
|
48
|
+
export declare function serializeWaitlistPayload(payload: WaitlistPayload): string;
|
|
49
|
+
export type WaitlistPostOutcome = "sent" | "invalid_email" | "rate_limited" | "unreachable";
|
|
50
|
+
/**
|
|
51
|
+
* Single POST, 3s timeout, one attempt, no retry, no queue. The response
|
|
52
|
+
* body is never printed (it could be an HTML error page); only the status
|
|
53
|
+
* code is mapped. Headers are the full explicit set this request adds —
|
|
54
|
+
* pinned by test so header creep fails CI too.
|
|
55
|
+
*/
|
|
56
|
+
export declare function postWaitlistSignup(payload: WaitlistPayload, options?: {
|
|
57
|
+
fetchImpl?: typeof fetch;
|
|
58
|
+
timeoutMs?: number;
|
|
59
|
+
}): Promise<WaitlistPostOutcome>;
|
|
60
|
+
export type EmailDeliverability = "ok" | "no_mx" | "disposable";
|
|
61
|
+
/** Small static blocklist of throwaway-inbox domains (exact match only). */
|
|
62
|
+
export declare const disposableEmailDomains: ReadonlySet<string>;
|
|
63
|
+
/** Exact or subdomain match against the blocklist (QA m5). */
|
|
64
|
+
export declare function isDisposableEmailDomain(domain: string): boolean;
|
|
65
|
+
export type SignupDnsResolver = {
|
|
66
|
+
resolveMx: (domain: string) => Promise<Array<{
|
|
67
|
+
exchange: string;
|
|
68
|
+
priority: number;
|
|
69
|
+
}>>;
|
|
70
|
+
resolve4: (domain: string) => Promise<string[]>;
|
|
71
|
+
};
|
|
72
|
+
export declare function assessEmailDeliverability(email: string, options?: {
|
|
73
|
+
resolver?: SignupDnsResolver;
|
|
74
|
+
timeoutMs?: number;
|
|
75
|
+
}): Promise<EmailDeliverability>;
|
|
76
|
+
export declare const signupCopy: {
|
|
77
|
+
/**
|
|
78
|
+
* Launch-week headline — TRUE only through launch day (Fri Aug 28); the
|
|
79
|
+
* date gate in signupAskBlockLines swaps in the evergreen fallback after
|
|
80
|
+
* signupLaunchWindowEndsAt so this copy can never go stale.
|
|
81
|
+
*/
|
|
82
|
+
readonly askHeadlineLaunch: readonly ["aibill launches Friday with Star.fun.", "Get the launch email + what ships next:"];
|
|
83
|
+
readonly askHeadlineFallback: readonly ["Get product updates:"];
|
|
84
|
+
readonly askFooter: "type your email, or press Enter to skip";
|
|
85
|
+
readonly askPrompt: " > ";
|
|
86
|
+
readonly waitLine: "reading your local AI evidence…";
|
|
87
|
+
/** Printed once if the scan finishes while the ask is still open. */
|
|
88
|
+
readonly receiptReadyLine: "your receipt is ready — type your email, or press Enter to see it";
|
|
89
|
+
/** Printed after the FIRST empty Enter; the second empty Enter skips. */
|
|
90
|
+
readonly skipNudgeLine: "one launch email · Enter again to skip, or type your email";
|
|
91
|
+
readonly scopeLine: "used only for updates · never shared";
|
|
92
|
+
/** Printed on the first Ctrl-C at the ask (the scan continues; M2). */
|
|
93
|
+
readonly interruptLine: "ok — skipped the ask · your receipt is still being read (Ctrl-C again to quit)";
|
|
94
|
+
/** Printed when ^C lands after the ask settled but before the receipt. */
|
|
95
|
+
readonly interruptAfterAnswerLine: "still reading your evidence · Ctrl-C again to quit";
|
|
96
|
+
/** Printed when the re-prompt budget closes the ask (no skip consumed). */
|
|
97
|
+
readonly budgetClosedLine: "moving on · npx aibill signup <email> anytime";
|
|
98
|
+
readonly consentQuestion: (payloadJson: string) => string;
|
|
99
|
+
readonly sentLine: "sent: exactly that JSON · nothing else in the payload";
|
|
100
|
+
readonly neverLine: "ok — never asking again · npx aibill signup <email> if you change your mind";
|
|
101
|
+
readonly invalidEmailLine: "that email did not validate — check it and retry";
|
|
102
|
+
readonly noMxLine: "that domain can't receive email — check the spelling";
|
|
103
|
+
readonly disposableLine: "use an address you actually check";
|
|
104
|
+
readonly rateLimitedLine: "busy — try again in a minute, or join at https://asktilden.com";
|
|
105
|
+
readonly unreachableLine: "could not reach asktilden.com — join at https://asktilden.com";
|
|
106
|
+
readonly alreadyLine: "already on the list · nothing sent twice";
|
|
107
|
+
readonly nothingSentLine: "nothing sent";
|
|
108
|
+
readonly nonInteractiveLine: "signup needs an interactive terminal — or join at https://asktilden.com";
|
|
109
|
+
readonly forgetLine: "local signup state cleared · to leave the list, reply to any email or write hello@asktilden.com";
|
|
110
|
+
readonly receiptPointer: "npx aibill signup <email> launch updates · optional · email only";
|
|
111
|
+
readonly samplePointer: "launch updates: npx aibill signup <email> · optional · email only";
|
|
112
|
+
readonly initPointer: "launch updates (optional): npx aibill signup <email>";
|
|
113
|
+
readonly statuslinePointer: "launch updates: npx aibill signup <email> · optional";
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* End of the launch-week headline window (the Friday line is true only
|
|
117
|
+
* through launch day, Fri 2026-08-28). After this instant the ask block
|
|
118
|
+
* automatically uses the evergreen fallback headline.
|
|
119
|
+
*/
|
|
120
|
+
export declare const signupLaunchWindowEndsAt = "2026-08-29T00:00:00Z";
|
|
121
|
+
/**
|
|
122
|
+
* The standout ask block: full-width rule (the receipt's own rule
|
|
123
|
+
* convention), then the headline for the current window, then the skip
|
|
124
|
+
* footer. Text lines carry the receipt's two-space indent.
|
|
125
|
+
*/
|
|
126
|
+
export declare function signupAskBlockLines(now: Date, width: number): string[];
|
|
127
|
+
/** Same clamp the receipt renderer applies (COLUMNS → tty → 72, 40..120). */
|
|
128
|
+
export declare function signupTerminalWidth(): number;
|
|
129
|
+
export type SignupStatus = "subscribed" | "never" | "deferred";
|
|
130
|
+
export type SignupState = {
|
|
131
|
+
version: 1;
|
|
132
|
+
status: SignupStatus;
|
|
133
|
+
/** Lifetime count of completed explicit skips (double-Enter / declined consent). */
|
|
134
|
+
askCount: number;
|
|
135
|
+
/**
|
|
136
|
+
* Lifetime count of ask OPENINGS (stamped even when the human never
|
|
137
|
+
* answers). Timeouts consume no skip, so this cap is what ends the asks
|
|
138
|
+
* for perpetual walk-away users (QA m10).
|
|
139
|
+
*/
|
|
140
|
+
stampCount?: number;
|
|
141
|
+
lastAskedAt?: string;
|
|
142
|
+
/** Stored only after a successful subscribe, only locally. */
|
|
143
|
+
email?: string;
|
|
144
|
+
};
|
|
145
|
+
export type SignupStateRead = {
|
|
146
|
+
kind: "fresh";
|
|
147
|
+
} | {
|
|
148
|
+
kind: "ok";
|
|
149
|
+
state: SignupState;
|
|
150
|
+
} | {
|
|
151
|
+
kind: "unreadable";
|
|
152
|
+
};
|
|
153
|
+
export declare function signupStateFilePath(homeDirectory?: string): string;
|
|
154
|
+
export declare function readSignupState(filePath: string): Promise<SignupStateRead>;
|
|
155
|
+
/** Atomic-ish write; returns false instead of throwing so callers fail closed. */
|
|
156
|
+
export declare function writeSignupState(filePath: string, state: SignupState): Promise<boolean>;
|
|
157
|
+
export declare function clearSignupState(filePath: string): Promise<boolean>;
|
|
158
|
+
/** Hard lifetime ceiling on ask openings, decided answer or not (QA m10). */
|
|
159
|
+
export declare const maximumLifetimeAskStamps = 6;
|
|
160
|
+
/**
|
|
161
|
+
* Whether the ONE ask may run. Fails closed on unreadable state; a
|
|
162
|
+
* future-dated lastAskedAt (clock moved back) counts as recently asked,
|
|
163
|
+
* never as a reason to re-ask.
|
|
164
|
+
*/
|
|
165
|
+
export declare function signupAskAllowed(read: SignupStateRead, now: Date): boolean;
|
|
166
|
+
export type SignupAskIo = {
|
|
167
|
+
/** Resolves the typed line, or undefined when the read timed out / aborted. */
|
|
168
|
+
question: (query: string, timeoutMs: number) => Promise<string | undefined>;
|
|
169
|
+
write: (line: string) => void;
|
|
170
|
+
/** Raw prompt redraw after a nudge line (no newline appended). */
|
|
171
|
+
writeRaw?: (text: string) => void;
|
|
172
|
+
};
|
|
173
|
+
export declare const signupAskTimeoutMs = 30000;
|
|
174
|
+
export type PreReceiptAskOutcome = {
|
|
175
|
+
kind: "no_ask";
|
|
176
|
+
} | {
|
|
177
|
+
kind: "skipped";
|
|
178
|
+
} | {
|
|
179
|
+
kind: "email";
|
|
180
|
+
payload: WaitlistPayload;
|
|
181
|
+
stamped: SignupState;
|
|
182
|
+
};
|
|
183
|
+
export type PreReceiptAskSession = {
|
|
184
|
+
/** Resolves when the human answered, skipped, timed out, or interrupted. */
|
|
185
|
+
outcome: Promise<PreReceiptAskOutcome>;
|
|
186
|
+
/**
|
|
187
|
+
* Ready-nudge: the pipeline finished while the ask is still open. Prints
|
|
188
|
+
* one line and re-draws the prompt; the open read's timer is NOT reset.
|
|
189
|
+
*/
|
|
190
|
+
notifyReceiptReady: () => void;
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Opens the ONE ask, or returns undefined (with zero output) when state
|
|
194
|
+
* disallows it — subsequent runs stay byte-identical to the fast path.
|
|
195
|
+
*
|
|
196
|
+
* Decision ledger (unchanged semantics, earlier placement):
|
|
197
|
+
* - timeout / Ctrl-C → no decision: lastAskedAt stamped, NO skip
|
|
198
|
+
* - Enter, then Enter again → ONE lifetime skip (nudge line between)
|
|
199
|
+
* - n / never → never ask again
|
|
200
|
+
* - typed input → email path (format + deliverability checks
|
|
201
|
+
* re-prompt without consuming skips)
|
|
202
|
+
* The consent step (literal payload JSON → y/N → single POST) runs strictly
|
|
203
|
+
* AFTER the receipt via runSignupConsentAfterReceipt.
|
|
204
|
+
*/
|
|
205
|
+
export declare function openPreReceiptSignupAsk(options: {
|
|
206
|
+
io: SignupAskIo;
|
|
207
|
+
stateFilePath: string;
|
|
208
|
+
now?: () => Date;
|
|
209
|
+
width?: number;
|
|
210
|
+
/** Lines printed before the ask block (the terminal wait line). */
|
|
211
|
+
preambleLines?: readonly string[];
|
|
212
|
+
dnsResolver?: SignupDnsResolver;
|
|
213
|
+
}): Promise<PreReceiptAskSession | undefined>;
|
|
214
|
+
/**
|
|
215
|
+
* The consent step, strictly AFTER the receipt has printed: scope line, the
|
|
216
|
+
* literal payload JSON, a typed y — then ONE POST. Failures never persist,
|
|
217
|
+
* retry, or queue the typed email.
|
|
218
|
+
*/
|
|
219
|
+
export declare function runSignupConsentAfterReceipt(options: {
|
|
220
|
+
io: SignupAskIo;
|
|
221
|
+
stateFilePath: string;
|
|
222
|
+
payload: WaitlistPayload;
|
|
223
|
+
stamped: SignupState;
|
|
224
|
+
fetchImpl?: typeof fetch;
|
|
225
|
+
}): Promise<void>;
|
|
226
|
+
/**
|
|
227
|
+
* Which argv shapes qualify for the during-scan ask: the real receipt path
|
|
228
|
+
* only — the default/quickstart command (flag-form included) — and never
|
|
229
|
+
* sample, drill-downs, JSON, help/version, or any named command (improve,
|
|
230
|
+
* report, init, …).
|
|
231
|
+
*/
|
|
232
|
+
export declare function qualifiesForPreReceiptSignupAsk(argv: readonly string[]): boolean;
|
|
233
|
+
/**
|
|
234
|
+
* Concurrency shell: run the evidence pipeline and the open ask together.
|
|
235
|
+
* The receipt renders only after BOTH resolve; a pipeline error is captured
|
|
236
|
+
* (never an unhandled rejection) and still waits for the bounded ask, so a
|
|
237
|
+
* prompt can never hang over a dead pipeline longer than its own timeout.
|
|
238
|
+
* If the pipeline settles first, the session gets the one ready-nudge.
|
|
239
|
+
*/
|
|
240
|
+
export declare function orchestratePreReceiptAsk<T>(input: {
|
|
241
|
+
session: PreReceiptAskSession | undefined;
|
|
242
|
+
runPipeline: () => Promise<T>;
|
|
243
|
+
}): Promise<{
|
|
244
|
+
pipeline: {
|
|
245
|
+
ok: true;
|
|
246
|
+
value: T;
|
|
247
|
+
} | {
|
|
248
|
+
ok: false;
|
|
249
|
+
error: unknown;
|
|
250
|
+
};
|
|
251
|
+
outcome: PreReceiptAskOutcome;
|
|
252
|
+
}>;
|
|
253
|
+
export type TerminalPreReceiptAsk = {
|
|
254
|
+
session: PreReceiptAskSession;
|
|
255
|
+
/** True when the last read ended without the user pressing Enter. */
|
|
256
|
+
needsFreshLine: () => boolean;
|
|
257
|
+
runConsent: (outcome: Extract<PreReceiptAskOutcome, {
|
|
258
|
+
kind: "email";
|
|
259
|
+
}>) => Promise<void>;
|
|
260
|
+
close: () => void;
|
|
261
|
+
};
|
|
262
|
+
/**
|
|
263
|
+
* Opens the during-scan ask on the real terminal: its own readline with
|
|
264
|
+
* per-read AbortSignal timeouts. The timeout race can never eat a typed
|
|
265
|
+
* skip — either the line resolved first (the skip is recorded) or the abort
|
|
266
|
+
* won and NOTHING is recorded; the wrong decision is unrepresentable.
|
|
267
|
+
* Ctrl-C cancels only the ask (no skip consumed, state already stamped);
|
|
268
|
+
* the receipt still renders. Returns undefined — with zero output — when
|
|
269
|
+
* signup state disallows the ask.
|
|
270
|
+
*/
|
|
271
|
+
export declare function openPreReceiptSignupAskInTerminal(): Promise<TerminalPreReceiptAsk | undefined>;
|
|
272
|
+
//# sourceMappingURL=signup.d.ts.map
|