@stripe/link-cli 0.8.2 → 0.9.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.
Files changed (3) hide show
  1. package/README.md +13 -0
  2. package/dist/cli.js +1940 -770
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -8835,19 +8835,19 @@ var require_range = __commonJS({
8835
8835
  var replaceCaret = (comp, options) => {
8836
8836
  debug("caret", comp, options);
8837
8837
  const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET];
8838
- const z10 = options.includePrerelease ? "-0" : "";
8838
+ const z13 = options.includePrerelease ? "-0" : "";
8839
8839
  return comp.replace(r, (_, M, m, p, pr) => {
8840
8840
  debug("caret", comp, _, M, m, p, pr);
8841
8841
  let ret;
8842
8842
  if (isX(M)) {
8843
8843
  ret = "";
8844
8844
  } else if (isX(m)) {
8845
- ret = `>=${M}.0.0${z10} <${+M + 1}.0.0-0`;
8845
+ ret = `>=${M}.0.0${z13} <${+M + 1}.0.0-0`;
8846
8846
  } else if (isX(p)) {
8847
8847
  if (M === "0") {
8848
- ret = `>=${M}.${m}.0${z10} <${M}.${+m + 1}.0-0`;
8848
+ ret = `>=${M}.${m}.0${z13} <${M}.${+m + 1}.0-0`;
8849
8849
  } else {
8850
- ret = `>=${M}.${m}.0${z10} <${+M + 1}.0.0-0`;
8850
+ ret = `>=${M}.${m}.0${z13} <${+M + 1}.0.0-0`;
8851
8851
  }
8852
8852
  } else if (pr) {
8853
8853
  debug("replaceCaret pr", pr);
@@ -8864,9 +8864,9 @@ var require_range = __commonJS({
8864
8864
  debug("no pr");
8865
8865
  if (M === "0") {
8866
8866
  if (m === "0") {
8867
- ret = `>=${M}.${m}.${p}${z10} <${M}.${m}.${+p + 1}-0`;
8867
+ ret = `>=${M}.${m}.${p}${z13} <${M}.${m}.${+p + 1}-0`;
8868
8868
  } else {
8869
- ret = `>=${M}.${m}.${p}${z10} <${M}.${+m + 1}.0-0`;
8869
+ ret = `>=${M}.${m}.${p}${z13} <${M}.${+m + 1}.0-0`;
8870
8870
  }
8871
8871
  } else {
8872
8872
  ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`;
@@ -11148,6 +11148,173 @@ function requireFetchImplementation(config) {
11148
11148
  }
11149
11149
  return config.fetch;
11150
11150
  }
11151
+ function isRecord(value) {
11152
+ return value !== null && typeof value === "object" && !Array.isArray(value);
11153
+ }
11154
+ function requireBoolean(value, field) {
11155
+ if (typeof value !== "boolean") {
11156
+ throw new TypeError(`Expected ${field} to be a boolean`);
11157
+ }
11158
+ return value;
11159
+ }
11160
+ function extractErrorMessage(data, rawBody) {
11161
+ if (isRecord(data)) {
11162
+ if (typeof data.error === "string") {
11163
+ return data.error;
11164
+ }
11165
+ if (isRecord(data.error)) {
11166
+ const nested = data.error;
11167
+ if (typeof nested.message === "string") {
11168
+ return nested.message;
11169
+ }
11170
+ if (typeof nested.code === "string") {
11171
+ return nested.code;
11172
+ }
11173
+ }
11174
+ if (typeof data.message === "string") {
11175
+ return data.message;
11176
+ }
11177
+ }
11178
+ return rawBody || "unknown error";
11179
+ }
11180
+ var BaseResource = class {
11181
+ verbose;
11182
+ getAccessToken;
11183
+ fetchImpl;
11184
+ endpoint;
11185
+ logger;
11186
+ constructor(options, endpointPath) {
11187
+ const config = resolveLinkSdkConfig(options);
11188
+ this.verbose = config.verbose;
11189
+ this.getAccessToken = config.getAccessToken;
11190
+ this.fetchImpl = requireFetchImplementation(config);
11191
+ this.endpoint = `${config.apiBaseUrl}${endpointPath}`;
11192
+ this.logger = config.logger;
11193
+ }
11194
+ async rawFetch(opts) {
11195
+ if (this.verbose) {
11196
+ const redactedHeaders = { ...opts.headers };
11197
+ if (redactedHeaders.Authorization)
11198
+ redactedHeaders.Authorization = "Bearer <redacted>";
11199
+ this.logger.debug(`> ${opts.method} ${opts.url}`);
11200
+ this.logger.debug(` Headers: ${JSON.stringify(redactedHeaders)}`);
11201
+ }
11202
+ let response;
11203
+ try {
11204
+ response = await this.fetchImpl(opts.url, {
11205
+ method: opts.method,
11206
+ headers: opts.headers
11207
+ });
11208
+ } catch (error) {
11209
+ throw new LinkTransportError(
11210
+ `Request failed: ${opts.method} ${opts.url}`,
11211
+ { cause: error }
11212
+ );
11213
+ }
11214
+ const rawBody = await response.text();
11215
+ let data = null;
11216
+ try {
11217
+ data = JSON.parse(rawBody);
11218
+ } catch {
11219
+ }
11220
+ if (this.verbose) {
11221
+ this.logger.debug(`< ${response.status} ${response.statusText}`);
11222
+ response.headers.forEach((value, key) => {
11223
+ this.logger.debug(` ${key}: ${value}`);
11224
+ });
11225
+ this.logger.debug(rawBody);
11226
+ }
11227
+ return { status: response.status, data, rawBody };
11228
+ }
11229
+ async apiFetch(opts) {
11230
+ const token = await this.getAccessToken();
11231
+ const authedOpts = {
11232
+ ...opts,
11233
+ headers: {
11234
+ ...opts.headers,
11235
+ Authorization: `Bearer ${token}`
11236
+ }
11237
+ };
11238
+ const res = await this.rawFetch(authedOpts);
11239
+ if (res.status === 401) {
11240
+ const refreshedToken = await this.getAccessToken({ forceRefresh: true });
11241
+ authedOpts.headers.Authorization = `Bearer ${refreshedToken}`;
11242
+ return this.rawFetch(authedOpts);
11243
+ }
11244
+ return res;
11245
+ }
11246
+ throwApiError(operation, status, data, rawBody, cause) {
11247
+ const msg = extractErrorMessage(data, rawBody);
11248
+ throw new LinkApiError(`Failed to ${operation} (${status}): ${msg}`, {
11249
+ status,
11250
+ rawBody,
11251
+ details: data,
11252
+ cause
11253
+ });
11254
+ }
11255
+ };
11256
+ function normalizeBalances(value) {
11257
+ if (!Array.isArray(value)) {
11258
+ throw new TypeError("Expected balances to be an array");
11259
+ }
11260
+ return value.map((item, index) => {
11261
+ if (!isRecord(item)) {
11262
+ throw new TypeError(`Expected balances[${index}] to be an object`);
11263
+ }
11264
+ return item;
11265
+ });
11266
+ }
11267
+ function normalizeBalancesPage(value) {
11268
+ if (!isRecord(value)) {
11269
+ throw new TypeError("Expected response body to be an object");
11270
+ }
11271
+ const { data, has_more, ...rest } = value;
11272
+ const normalized = normalizeBalances(data);
11273
+ return {
11274
+ ...rest,
11275
+ data: normalized,
11276
+ ...has_more !== void 0 ? { has_more: requireBoolean(has_more, "has_more") } : {}
11277
+ };
11278
+ }
11279
+ var BalancesResource = class extends BaseResource {
11280
+ constructor(options = {}) {
11281
+ super(options, "/balances");
11282
+ }
11283
+ buildUrl(params) {
11284
+ const url = new URL(this.endpoint);
11285
+ if (params.limit !== void 0) {
11286
+ url.searchParams.set("limit", String(params.limit));
11287
+ }
11288
+ if (params.starting_after !== void 0) {
11289
+ url.searchParams.set("starting_after", params.starting_after);
11290
+ }
11291
+ if (params.ending_before !== void 0) {
11292
+ url.searchParams.set("ending_before", params.ending_before);
11293
+ }
11294
+ return url.toString();
11295
+ }
11296
+ list(params = {}) {
11297
+ return this.listBalances(params);
11298
+ }
11299
+ async listBalances(params = {}) {
11300
+ const { status, data, rawBody } = await this.apiFetch({
11301
+ method: "GET",
11302
+ url: this.buildUrl(params)
11303
+ });
11304
+ if (status < 200 || status >= 300) {
11305
+ this.throwApiError("list balances", status, data, rawBody);
11306
+ }
11307
+ try {
11308
+ return normalizeBalancesPage(data);
11309
+ } catch (error) {
11310
+ const reason = error instanceof Error ? `: ${error.message}` : "";
11311
+ throw new LinkApiError(
11312
+ `Failed to list balances (${status}): invalid response shape${reason}`,
11313
+ { status, rawBody, details: data, cause: error }
11314
+ );
11315
+ }
11316
+ }
11317
+ };
11151
11318
  var PaymentMethodsResource = class {
11152
11319
  verbose;
11153
11320
  getAccessToken;
@@ -11318,6 +11485,68 @@ var ShippingAddressResource = class {
11318
11485
  return body?.shipping_addresses ?? [];
11319
11486
  }
11320
11487
  };
11488
+ function normalizeSources(value) {
11489
+ if (!Array.isArray(value)) {
11490
+ throw new TypeError("Expected sources to be an array");
11491
+ }
11492
+ return value.map((item, index) => {
11493
+ if (!isRecord(item)) {
11494
+ throw new TypeError(`Expected sources[${index}] to be an object`);
11495
+ }
11496
+ return item;
11497
+ });
11498
+ }
11499
+ function normalizeSourcesPage(value) {
11500
+ if (!isRecord(value)) {
11501
+ throw new TypeError("Expected response body to be an object");
11502
+ }
11503
+ const { data, has_more, ...rest } = value;
11504
+ const normalized = normalizeSources(data);
11505
+ return {
11506
+ ...rest,
11507
+ data: normalized,
11508
+ ...has_more !== void 0 ? { has_more: requireBoolean(has_more, "has_more") } : {}
11509
+ };
11510
+ }
11511
+ var SourcesResource = class extends BaseResource {
11512
+ constructor(options = {}) {
11513
+ super(options, "/sources");
11514
+ }
11515
+ buildUrl(params) {
11516
+ const url = new URL(this.endpoint);
11517
+ if (params.limit !== void 0) {
11518
+ url.searchParams.set("limit", String(params.limit));
11519
+ }
11520
+ if (params.starting_after !== void 0) {
11521
+ url.searchParams.set("starting_after", params.starting_after);
11522
+ }
11523
+ if (params.ending_before !== void 0) {
11524
+ url.searchParams.set("ending_before", params.ending_before);
11525
+ }
11526
+ return url.toString();
11527
+ }
11528
+ list(params = {}) {
11529
+ return this.listSources(params);
11530
+ }
11531
+ async listSources(params = {}) {
11532
+ const { status, data, rawBody } = await this.apiFetch({
11533
+ method: "GET",
11534
+ url: this.buildUrl(params)
11535
+ });
11536
+ if (status < 200 || status >= 300) {
11537
+ this.throwApiError("list sources", status, data, rawBody);
11538
+ }
11539
+ try {
11540
+ return normalizeSourcesPage(data);
11541
+ } catch (error) {
11542
+ const reason = error instanceof Error ? `: ${error.message}` : "";
11543
+ throw new LinkApiError(
11544
+ `Failed to list sources (${status}): invalid response shape${reason}`,
11545
+ { status, rawBody, details: data, cause: error }
11546
+ );
11547
+ }
11548
+ }
11549
+ };
11321
11550
  function normalizeSpendRequest(data) {
11322
11551
  const sr = data;
11323
11552
  if (typeof sr.shared_payment_token === "string") {
@@ -11524,6 +11753,140 @@ var SpendRequestResource = class {
11524
11753
  return normalizeSpendRequest(data);
11525
11754
  }
11526
11755
  };
11756
+ function requireString(value, field) {
11757
+ if (typeof value !== "string") {
11758
+ throw new TypeError(`Expected ${field} to be a string`);
11759
+ }
11760
+ return value;
11761
+ }
11762
+ function requireNullableString(value, field) {
11763
+ if (value === null) {
11764
+ return null;
11765
+ }
11766
+ if (typeof value !== "string") {
11767
+ throw new TypeError(`Expected ${field} to be a string or null`);
11768
+ }
11769
+ return value;
11770
+ }
11771
+ function requireNumber(value, field) {
11772
+ if (typeof value !== "number" || !Number.isFinite(value)) {
11773
+ throw new TypeError(`Expected ${field} to be a finite number`);
11774
+ }
11775
+ return value;
11776
+ }
11777
+ function requireTransactionOrigin(value, field) {
11778
+ if (value === "link" || value === "external_connection") {
11779
+ return value;
11780
+ }
11781
+ throw new TypeError(`Expected ${field} to be a transaction origin`);
11782
+ }
11783
+ function normalizeTransactions(value) {
11784
+ if (!Array.isArray(value)) {
11785
+ throw new TypeError("Expected transactions to be an array");
11786
+ }
11787
+ return value.map((item, index) => {
11788
+ if (!isRecord(item)) {
11789
+ throw new TypeError(`Expected transactions[${index}] to be an object`);
11790
+ }
11791
+ return {
11792
+ id: requireString(item.id, `transactions[${index}].id`),
11793
+ source_id: requireNullableString(
11794
+ item.source_id,
11795
+ `transactions[${index}].source_id`
11796
+ ),
11797
+ amount: requireNumber(item.amount, `transactions[${index}].amount`),
11798
+ currency: requireString(item.currency, `transactions[${index}].currency`),
11799
+ created_date: requireString(
11800
+ item.created_date,
11801
+ `transactions[${index}].created_date`
11802
+ ),
11803
+ description: requireString(
11804
+ item.description,
11805
+ `transactions[${index}].description`
11806
+ ),
11807
+ origin: requireTransactionOrigin(
11808
+ item.origin,
11809
+ `transactions[${index}].origin`
11810
+ ),
11811
+ category: requireNullableString(
11812
+ item.category,
11813
+ `transactions[${index}].category`
11814
+ ),
11815
+ status: requireString(item.status, `transactions[${index}].status`)
11816
+ };
11817
+ });
11818
+ }
11819
+ function normalizeTransactionsPage(value) {
11820
+ if (Array.isArray(value)) {
11821
+ return { data: normalizeTransactions(value) };
11822
+ }
11823
+ if (!isRecord(value)) {
11824
+ throw new TypeError("Expected response body to be an object");
11825
+ }
11826
+ const { data, has_more, ...rest } = value;
11827
+ const normalized = normalizeTransactions(data);
11828
+ return {
11829
+ ...rest,
11830
+ data: normalized,
11831
+ ...has_more !== void 0 ? { has_more: requireBoolean(has_more, "has_more") } : {}
11832
+ };
11833
+ }
11834
+ var TransactionsResource = class extends BaseResource {
11835
+ constructor(options = {}) {
11836
+ super(options, "/transactions");
11837
+ }
11838
+ buildUrl(params) {
11839
+ const url = new URL(this.endpoint);
11840
+ if (params.limit !== void 0) {
11841
+ url.searchParams.set("limit", String(params.limit));
11842
+ }
11843
+ if (params.starting_after !== void 0) {
11844
+ url.searchParams.set("starting_after", params.starting_after);
11845
+ }
11846
+ if (params.ending_before !== void 0) {
11847
+ url.searchParams.set("ending_before", params.ending_before);
11848
+ }
11849
+ if (params.start_date !== void 0) {
11850
+ url.searchParams.set("date_start", params.start_date);
11851
+ }
11852
+ if (params.end_date !== void 0) {
11853
+ url.searchParams.set("date_end", params.end_date);
11854
+ }
11855
+ if (params.category !== void 0) {
11856
+ url.searchParams.set("category", params.category);
11857
+ }
11858
+ if (params.origin !== void 0) {
11859
+ url.searchParams.set("origin", params.origin);
11860
+ }
11861
+ if (params.sources !== void 0) {
11862
+ for (const source of params.sources) {
11863
+ url.searchParams.append("sources[]", source);
11864
+ }
11865
+ }
11866
+ return url.toString();
11867
+ }
11868
+ list(params = {}) {
11869
+ return this.listTransactions(params);
11870
+ }
11871
+ async listTransactions(params = {}) {
11872
+ const { status, data, rawBody } = await this.apiFetch({
11873
+ method: "GET",
11874
+ url: this.buildUrl(params)
11875
+ });
11876
+ if (status < 200 || status >= 300) {
11877
+ this.throwApiError("list transactions", status, data, rawBody);
11878
+ }
11879
+ try {
11880
+ return normalizeTransactionsPage(data);
11881
+ } catch (error) {
11882
+ const reason = error instanceof Error ? `: ${error.message}` : "";
11883
+ throw new LinkApiError(
11884
+ `Failed to list transactions (${status}): invalid response shape${reason}`,
11885
+ { status, rawBody, details: data, cause: error }
11886
+ );
11887
+ }
11888
+ }
11889
+ };
11527
11890
  var UserInfoResource = class {
11528
11891
  verbose;
11529
11892
  getAccessToken;
@@ -11616,6 +11979,12 @@ var UserInfoResource = class {
11616
11979
  };
11617
11980
  }
11618
11981
  };
11982
+ var SOURCE_ACTIONS = [
11983
+ "read_balances",
11984
+ "read_external_transactions",
11985
+ "read_link_transactions",
11986
+ "read_source_details"
11987
+ ];
11619
11988
  var REPORT_OUTCOMES = ["success", "blocked", "abandoned"];
11620
11989
  var REPORT_TAGS = [
11621
11990
  "stripe_checkout",
@@ -11843,12 +12212,69 @@ var ReportResource = class {
11843
12212
  };
11844
12213
 
11845
12214
  // src/cli.tsx
11846
- import { Cli as Cli11 } from "incur";
12215
+ import { Cli as Cli14 } from "incur";
11847
12216
 
11848
12217
  // src/commands/auth/index.tsx
11849
12218
  import { Cli } from "incur";
11850
12219
  import { Text as Text4 } from "ink";
11851
12220
 
12221
+ // src/auth/authorization-details.ts
12222
+ var INVALID_AUTHORIZATION_DETAIL_MESSAGE = "authorization-detail must be valid JSON";
12223
+ function dedupe(values) {
12224
+ const seen = /* @__PURE__ */ new Set();
12225
+ const result = [];
12226
+ for (const value of values) {
12227
+ if (seen.has(value)) {
12228
+ continue;
12229
+ }
12230
+ seen.add(value);
12231
+ result.push(value);
12232
+ }
12233
+ return result;
12234
+ }
12235
+ function parseAuthorizationDetails(entries) {
12236
+ const parsed = [];
12237
+ for (const entry of entries ?? []) {
12238
+ try {
12239
+ parsed.push(JSON.parse(entry));
12240
+ } catch {
12241
+ throw new Error(INVALID_AUTHORIZATION_DETAIL_MESSAGE);
12242
+ }
12243
+ }
12244
+ return parsed;
12245
+ }
12246
+ function buildAuthorizationDetails(sourceActions, authorizationDetails) {
12247
+ const details = [];
12248
+ const uniqueSourceActions = dedupe(sourceActions ?? []);
12249
+ if (uniqueSourceActions.length > 0) {
12250
+ details.push({
12251
+ type: "source",
12252
+ actions: uniqueSourceActions
12253
+ });
12254
+ }
12255
+ if (authorizationDetails) {
12256
+ details.push(...authorizationDetails);
12257
+ }
12258
+ return details;
12259
+ }
12260
+
12261
+ // src/auth/scopes.ts
12262
+ var DEFAULT_SCOPES = [
12263
+ "userinfo:read",
12264
+ "payment_methods.agentic"
12265
+ ];
12266
+ var DEFAULT_SCOPE = DEFAULT_SCOPES.join(" ");
12267
+ function parseScopeTokens(scope) {
12268
+ return scope.trim().split(/\s+/).filter(Boolean);
12269
+ }
12270
+ function normalizeScopeInput(scope) {
12271
+ if (scope === void 0) {
12272
+ return void 0;
12273
+ }
12274
+ const normalized = parseScopeTokens(scope);
12275
+ return normalized.length > 0 ? normalized.join(" ") : void 0;
12276
+ }
12277
+
11852
12278
  // src/utils/poll-until.ts
11853
12279
  async function* pollUntil(options) {
11854
12280
  const { fn, isTerminal, interval, timeout, maxAttempts } = options;
@@ -11965,6 +12391,9 @@ import { jsx, jsxs } from "react/jsx-runtime";
11965
12391
  var Login = ({
11966
12392
  authResource,
11967
12393
  clientName,
12394
+ scope,
12395
+ sourceActions,
12396
+ authorizationDetails,
11968
12397
  authStorage: authStorage2 = storage,
11969
12398
  onComplete
11970
12399
  }) => {
@@ -11985,7 +12414,12 @@ var Login = ({
11985
12414
  useEffect(() => {
11986
12415
  const initAuth = async () => {
11987
12416
  try {
11988
- const authRequest = await authResource.initiateDeviceAuth(clientName);
12417
+ const authRequest = await authResource.initiateDeviceAuth({
12418
+ clientName,
12419
+ scope,
12420
+ sourceActions,
12421
+ authorizationDetails
12422
+ });
11989
12423
  setUserCode(authRequest.user_code);
11990
12424
  setVerificationUrl(authRequest.verification_url_complete);
11991
12425
  setDeviceCode(authRequest.device_code);
@@ -11996,7 +12430,7 @@ var Login = ({
11996
12430
  }
11997
12431
  };
11998
12432
  initAuth();
11999
- }, [authResource, clientName]);
12433
+ }, [authResource, authorizationDetails, clientName, scope, sourceActions]);
12000
12434
  useEffect(() => {
12001
12435
  if (status !== "waiting" || !deviceCode) return;
12002
12436
  const startPolling = async () => {
@@ -12035,17 +12469,17 @@ var Login = ({
12035
12469
  if (status === "declined") {
12036
12470
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
12037
12471
  /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2717 Authorization failed" }),
12038
- Object.entries(scopeEligibility).map(([scope, info]) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
12472
+ Object.entries(scopeEligibility).map(([scope2, info]) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
12039
12473
  /* @__PURE__ */ jsxs(Text, { children: [
12040
12474
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
12041
- scope,
12475
+ scope2,
12042
12476
  ":"
12043
12477
  ] }),
12044
12478
  " ineligible",
12045
12479
  info.ineligibility_reasons.length > 0 ? ` (${info.ineligibility_reasons.join(", ")})` : ""
12046
12480
  ] }),
12047
12481
  info.description ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: info.description }) : null
12048
- ] }, scope))
12482
+ ] }, scope2))
12049
12483
  ] });
12050
12484
  }
12051
12485
  if (status === "error") {
@@ -12169,10 +12603,18 @@ var Logout = ({
12169
12603
 
12170
12604
  // src/commands/auth/schema.ts
12171
12605
  import { z } from "incur";
12606
+ var SOURCE_ACTIONS_DESCRIPTION = SOURCE_ACTIONS.join(", ");
12172
12607
  var loginOptions = z.object({
12173
12608
  clientName: z.string().default("Link CLI").describe(
12174
12609
  "Agent or app name shown in the Link app when approving the device connection"
12175
12610
  ),
12611
+ scope: z.string().optional().describe(
12612
+ "Optional space-separated Link scopes to request. Quote the value when passing multiple scopes."
12613
+ ),
12614
+ sourceActions: z.array(z.enum(SOURCE_ACTIONS)).default([]).describe(
12615
+ `Source action to request via authorization_details (repeatable). Accepted values: ${SOURCE_ACTIONS_DESCRIPTION}.`
12616
+ ),
12617
+ authorizationDetail: z.array(z.string()).default([]).describe("Freeform authorization_details entry as raw JSON (repeatable)."),
12176
12618
  interval: z.coerce.number().default(0).describe(
12177
12619
  "Poll interval in seconds. When > 0, polls until authenticated or timeout is reached, yielding status on each attempt."
12178
12620
  ),
@@ -12328,12 +12770,30 @@ function createAuthCli(authResource, getUpdateInfo2, authStorage2, envAccessToke
12328
12770
  outputPolicy: "agent-only",
12329
12771
  async *run(c) {
12330
12772
  const clientName = c.options.clientName?.trim();
12773
+ const scope = normalizeScopeInput(c.options.scope);
12774
+ let authorizationDetails;
12331
12775
  if (!clientName || clientName.length === 0) {
12332
12776
  return c.error({
12333
12777
  code: "INVALID_INPUT",
12334
12778
  message: "client-name must be a non-empty string"
12335
12779
  });
12336
12780
  }
12781
+ if (c.options.scope !== void 0 && !scope) {
12782
+ return c.error({
12783
+ code: "INVALID_INPUT",
12784
+ message: "scope must be a non-empty string when provided"
12785
+ });
12786
+ }
12787
+ try {
12788
+ authorizationDetails = parseAuthorizationDetails(
12789
+ c.options.authorizationDetail
12790
+ );
12791
+ } catch (error) {
12792
+ return c.error({
12793
+ code: "INVALID_INPUT",
12794
+ message: error.message
12795
+ });
12796
+ }
12337
12797
  const existingAuth = storage2.getAuth();
12338
12798
  if (existingAuth?.refresh_token) {
12339
12799
  try {
@@ -12365,6 +12825,9 @@ function createAuthCli(authResource, getUpdateInfo2, authStorage2, envAccessToke
12365
12825
  {
12366
12826
  authResource,
12367
12827
  clientName,
12828
+ scope,
12829
+ sourceActions: c.options.sourceActions,
12830
+ authorizationDetails,
12368
12831
  authStorage: storage2,
12369
12832
  onComplete: () => {
12370
12833
  }
@@ -12373,7 +12836,12 @@ function createAuthCli(authResource, getUpdateInfo2, authStorage2, envAccessToke
12373
12836
  () => ({ authenticated: true, token_type: "Bearer" })
12374
12837
  );
12375
12838
  }
12376
- const authRequest = await authResource.initiateDeviceAuth(clientName);
12839
+ const authRequest = await authResource.initiateDeviceAuth({
12840
+ clientName,
12841
+ scope,
12842
+ sourceActions: c.options.sourceActions,
12843
+ authorizationDetails
12844
+ });
12377
12845
  storage2.setPendingDeviceAuth({
12378
12846
  device_code: authRequest.device_code,
12379
12847
  interval: authRequest.interval,
@@ -12503,29 +12971,200 @@ function createAuthCli(authResource, getUpdateInfo2, authStorage2, envAccessToke
12503
12971
  return cli2;
12504
12972
  }
12505
12973
 
12974
+ // src/commands/balances/index.tsx
12975
+ import { Cli as Cli2 } from "incur";
12976
+
12977
+ // src/utils/require-auth.ts
12978
+ var NOT_AUTHENTICATED_ERROR = {
12979
+ code: "NOT_AUTHENTICATED",
12980
+ message: 'Not authenticated. Run "link-cli auth login" first.',
12981
+ cta: {
12982
+ commands: [{ command: "auth login", description: "Log in to Link" }]
12983
+ }
12984
+ };
12985
+ function requireAuth(authStorage2, envAccessToken2) {
12986
+ const store = authStorage2 ?? storage;
12987
+ return (c, next) => {
12988
+ if (!envAccessToken2 && !store.isAuthenticated()) {
12989
+ return c.error(NOT_AUTHENTICATED_ERROR);
12990
+ }
12991
+ return next();
12992
+ };
12993
+ }
12994
+ function requireAuthGuard(c, authStorage2, envAccessToken2) {
12995
+ const store = authStorage2 ?? storage;
12996
+ if (!envAccessToken2 && !store.isAuthenticated()) {
12997
+ c.error(NOT_AUTHENTICATED_ERROR);
12998
+ }
12999
+ }
13000
+
13001
+ // src/commands/balances/list.tsx
13002
+ import { Box as Box4, Text as Text5 } from "ink";
13003
+ import Spinner3 from "ink-spinner";
13004
+ import { useCallback as useCallback2 } from "react";
13005
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
13006
+ var COLUMN_GAP = " ";
13007
+ var SOURCE_ID_MIN = 16;
13008
+ var SOURCE_ID_MAX = 48;
13009
+ var TYPE_WIDTH = 12;
13010
+ var CURRENT_WIDTH = 15;
13011
+ var CURRENCY_WIDTH = 8;
13012
+ function truncateCell(value, width) {
13013
+ if (value.length <= width) {
13014
+ return value;
13015
+ }
13016
+ if (width <= 3) {
13017
+ return value.slice(0, width);
13018
+ }
13019
+ return `${value.slice(0, width - 3)}...`;
13020
+ }
13021
+ function formatCell(value, width) {
13022
+ return truncateCell(value, width).padEnd(width);
13023
+ }
13024
+ function formatCents(cents) {
13025
+ const dollars = Math.abs(cents) / 100;
13026
+ const formatted = `$${dollars.toFixed(2)}`;
13027
+ return cents < 0 ? `-${formatted}` : formatted;
13028
+ }
13029
+ function sourceIdWidth(balances) {
13030
+ if (balances.length === 0) return SOURCE_ID_MIN;
13031
+ const maxLen = Math.max(...balances.map((b) => (b.source_id ?? "").length));
13032
+ return Math.min(SOURCE_ID_MAX, Math.max(SOURCE_ID_MIN, maxLen));
13033
+ }
13034
+ var BalancesList = ({
13035
+ resource,
13036
+ params,
13037
+ onComplete
13038
+ }) => {
13039
+ const action = useCallback2(
13040
+ () => resource.listBalances(params),
13041
+ [resource, params]
13042
+ );
13043
+ const { status, data: page, error } = useAsyncAction(action, onComplete);
13044
+ const balances = page?.data ?? [];
13045
+ const nextCursor = page?.has_more && balances.length > 0 ? balances[balances.length - 1].source_id : null;
13046
+ const idWidth = sourceIdWidth(balances);
13047
+ const headerRow = [
13048
+ formatCell("Source ID", idWidth),
13049
+ formatCell("Balance type", TYPE_WIDTH),
13050
+ formatCell("Current balance", CURRENT_WIDTH),
13051
+ formatCell("Currency", CURRENCY_WIDTH)
13052
+ ].join(COLUMN_GAP);
13053
+ const separatorRow = "-".repeat(headerRow.length);
13054
+ const rows = balances.map(
13055
+ (balance) => [
13056
+ formatCell(balance.source_id ?? "-", idWidth),
13057
+ formatCell(balance.type ?? "-", TYPE_WIDTH),
13058
+ formatCell(
13059
+ balance.current != null ? formatCents(balance.current) : "-",
13060
+ CURRENT_WIDTH
13061
+ ),
13062
+ formatCell(balance.currency ?? "-", CURRENCY_WIDTH)
13063
+ ].join(COLUMN_GAP)
13064
+ );
13065
+ if (status === "loading") {
13066
+ return /* @__PURE__ */ jsx5(Box4, { children: /* @__PURE__ */ jsxs4(Text5, { color: "cyan", children: [
13067
+ /* @__PURE__ */ jsx5(Spinner3, { type: "dots" }),
13068
+ " Loading balances..."
13069
+ ] }) });
13070
+ }
13071
+ if (status === "error") {
13072
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
13073
+ /* @__PURE__ */ jsx5(Text5, { color: "red", children: "Failed to load balances" }),
13074
+ /* @__PURE__ */ jsx5(Text5, { color: "red", children: error })
13075
+ ] });
13076
+ }
13077
+ if (balances.length === 0) {
13078
+ return /* @__PURE__ */ jsx5(Box4, { children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "No balances found" }) });
13079
+ }
13080
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
13081
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Balances" }),
13082
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
13083
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: headerRow }),
13084
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: separatorRow }),
13085
+ rows.map((row, index) => /* @__PURE__ */ jsx5(Text5, { children: row }, balances[index].source_id ?? `balance-${index}`))
13086
+ ] }),
13087
+ page?.has_more !== void 0 ? /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
13088
+ /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
13089
+ "has_more: ",
13090
+ String(page.has_more)
13091
+ ] }),
13092
+ typeof nextCursor === "string" && nextCursor.length > 0 ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: `next page: --starting-after ${nextCursor}` }) : null
13093
+ ] }) : null
13094
+ ] });
13095
+ };
13096
+
13097
+ // src/commands/balances/schema.ts
13098
+ import { z as z2 } from "incur";
13099
+ var listOptions = z2.object({
13100
+ limit: z2.coerce.number().int().positive().max(100).optional().describe("Maximum number of balances to return (1-100)."),
13101
+ startingAfter: z2.string().optional().describe("Cursor: return balances after this balance ID."),
13102
+ endingBefore: z2.string().optional().describe("Cursor: return balances before this balance ID.")
13103
+ });
13104
+
13105
+ // src/commands/balances/index.tsx
13106
+ import { jsx as jsx6 } from "react/jsx-runtime";
13107
+ function createBalancesCli(createResource, authStorage2, envAccessToken2) {
13108
+ const cli2 = Cli2.create("balances", {
13109
+ description: "List balances from your Link wallet"
13110
+ });
13111
+ cli2.command("list", {
13112
+ description: "List balances from your Link wallet",
13113
+ options: listOptions,
13114
+ outputPolicy: "agent-only",
13115
+ middleware: [requireAuth(authStorage2, envAccessToken2)],
13116
+ async run(c) {
13117
+ const opts = c.options;
13118
+ const resource = createResource();
13119
+ const params = {};
13120
+ if (opts.limit !== void 0) params.limit = opts.limit;
13121
+ if (opts.startingAfter !== void 0)
13122
+ params.starting_after = opts.startingAfter;
13123
+ if (opts.endingBefore !== void 0)
13124
+ params.ending_before = opts.endingBefore;
13125
+ if (!c.agent && !c.formatExplicit) {
13126
+ return renderInteractive(
13127
+ /* @__PURE__ */ jsx6(
13128
+ BalancesList,
13129
+ {
13130
+ resource,
13131
+ params,
13132
+ onComplete: () => {
13133
+ }
13134
+ }
13135
+ ),
13136
+ () => resource.listBalances(params)
13137
+ );
13138
+ }
13139
+ return resource.listBalances(params);
13140
+ }
13141
+ });
13142
+ return cli2;
13143
+ }
13144
+
12506
13145
  // src/commands/demo/index.tsx
12507
- import { Cli as Cli2, z as z2 } from "incur";
13146
+ import { Cli as Cli3, z as z3 } from "incur";
12508
13147
 
12509
13148
  // src/commands/demo/demo-runner.tsx
12510
- import { Box as Box8, Text as Text10, useApp, useInput as useInput4 } from "ink";
12511
- import { useCallback as useCallback2, useState as useState7 } from "react";
13149
+ import { Box as Box9, Text as Text11, useApp, useInput as useInput4 } from "ink";
13150
+ import { useCallback as useCallback3, useState as useState7 } from "react";
12512
13151
 
12513
13152
  // src/utils/markdown-text.tsx
12514
- import { Text as Text5 } from "ink";
12515
- import { jsx as jsx5 } from "react/jsx-runtime";
13153
+ import { Text as Text6 } from "ink";
13154
+ import { jsx as jsx7 } from "react/jsx-runtime";
12516
13155
  var MarkdownText = ({
12517
13156
  children,
12518
13157
  dimColor
12519
13158
  }) => {
12520
13159
  const parts = tokenize(children);
12521
- return /* @__PURE__ */ jsx5(Text5, { dimColor, children: parts.map((part) => {
13160
+ return /* @__PURE__ */ jsx7(Text6, { dimColor, children: parts.map((part) => {
12522
13161
  if (part.type === "bold") {
12523
- return /* @__PURE__ */ jsx5(Text5, { bold: true, children: part.text }, part.key);
13162
+ return /* @__PURE__ */ jsx7(Text6, { bold: true, children: part.text }, part.key);
12524
13163
  }
12525
13164
  if (part.type === "code") {
12526
- return /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: part.text }, part.key);
13165
+ return /* @__PURE__ */ jsx7(Text6, { color: "yellow", children: part.text }, part.key);
12527
13166
  }
12528
- return /* @__PURE__ */ jsx5(Text5, { children: part.text }, part.key);
13167
+ return /* @__PURE__ */ jsx7(Text6, { children: part.text }, part.key);
12529
13168
  }) });
12530
13169
  };
12531
13170
  function tokenize(input) {
@@ -12560,7 +13199,7 @@ function tokenize(input) {
12560
13199
  }
12561
13200
 
12562
13201
  // src/commands/spend-request/app-download-qr-codes.tsx
12563
- import { Box as Box4, Text as Text6 } from "ink";
13202
+ import { Box as Box5, Text as Text7 } from "ink";
12564
13203
  import { useMemo } from "react";
12565
13204
 
12566
13205
  // src/utils/render-qr-matrix.ts
@@ -12597,24 +13236,24 @@ function renderQrMatrix(url) {
12597
13236
  }
12598
13237
 
12599
13238
  // src/commands/spend-request/app-download-qr-codes.tsx
12600
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
13239
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
12601
13240
  var DOWNLOAD_URL = "https://link.com/download";
12602
13241
  var AppDownloadQrCodes = () => {
12603
13242
  const qrLines = useMemo(() => renderQrMatrix(DOWNLOAD_URL), []);
12604
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
12605
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Get the Link app to approve spend requests from your phone" }),
12606
- /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", alignItems: "flex-start", marginTop: 1, children: [
13243
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
13244
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "Get the Link app to approve spend requests from your phone" }),
13245
+ /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", alignItems: "flex-start", marginTop: 1, children: [
12607
13246
  qrLines.map((line, i) => (
12608
13247
  // biome-ignore lint/suspicious/noArrayIndexKey: stable static array
12609
- /* @__PURE__ */ jsx6(Text6, { children: line }, i)
13248
+ /* @__PURE__ */ jsx8(Text7, { children: line }, i)
12610
13249
  )),
12611
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: DOWNLOAD_URL })
13250
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: DOWNLOAD_URL })
12612
13251
  ] })
12613
13252
  ] });
12614
13253
  };
12615
13254
 
12616
13255
  // src/commands/demo/card-flow.tsx
12617
- import { Box as Box5, Text as Text7, useInput as useInput2 } from "ink";
13256
+ import { Box as Box6, Text as Text8, useInput as useInput2 } from "ink";
12618
13257
  import { useEffect as useEffect4, useRef as useRef2, useState as useState4 } from "react";
12619
13258
 
12620
13259
  // src/utils/poll-until-approved.ts
@@ -12779,7 +13418,7 @@ var ONBOARD = {
12779
13418
  };
12780
13419
 
12781
13420
  // src/commands/demo/card-flow.tsx
12782
- import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
13421
+ import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
12783
13422
  function formatPmLabel(pm) {
12784
13423
  return `${pm.card_details?.brand ?? pm.type} ****${pm.card_details?.last4 ?? ""}`;
12785
13424
  }
@@ -12963,22 +13602,22 @@ var CardFlow = ({
12963
13602
  ];
12964
13603
  return order.indexOf(step) > order.indexOf(target);
12965
13604
  };
12966
- const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs5(Text7, { dimColor: true, children: [
13605
+ const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
12967
13606
  "\n",
12968
13607
  ">",
12969
13608
  " ",
12970
13609
  label
12971
13610
  ] });
12972
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", gap: 1, children: [
12973
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: CARD_FLOW.title }),
12974
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
12975
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", gap: 1, children: [
12976
- /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "[testmode]" }),
12977
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: DEMO_MERCHANT_URL })
13611
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", gap: 1, children: [
13612
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: CARD_FLOW.title }),
13613
+ /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13614
+ /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", gap: 1, children: [
13615
+ /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "[testmode]" }),
13616
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: DEMO_MERCHANT_URL })
12978
13617
  ] }),
12979
- /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.intro.description }),
12980
- /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
12981
- /* @__PURE__ */ jsx7(Text7, { children: "What happens:" }),
13618
+ /* @__PURE__ */ jsx9(MarkdownText, { children: CARD_FLOW.intro.description }),
13619
+ /* @__PURE__ */ jsxs6(Box6, { marginTop: 1, flexDirection: "column", children: [
13620
+ /* @__PURE__ */ jsx9(Text8, { children: "What happens:" }),
12982
13621
  CARD_FLOW.intro.steps.map((s, i) => {
12983
13622
  const doneAfter = [
12984
13623
  "pick-pm",
@@ -12994,17 +13633,17 @@ var CardFlow = ({
12994
13633
  ];
12995
13634
  const done = pastStep(doneAfter[i]);
12996
13635
  const active = !done && (step === activeFrom[i] || pastStep(activeFrom[i]));
12997
- return done ? /* @__PURE__ */ jsxs5(Text7, { dimColor: true, strikethrough: true, children: [
13636
+ return done ? /* @__PURE__ */ jsxs6(Text8, { dimColor: true, strikethrough: true, children: [
12998
13637
  " ",
12999
13638
  i + 1,
13000
13639
  ". ",
13001
13640
  s
13002
- ] }, s) : active ? /* @__PURE__ */ jsxs5(Text7, { bold: true, color: "cyan", children: [
13641
+ ] }, s) : active ? /* @__PURE__ */ jsxs6(Text8, { bold: true, color: "cyan", children: [
13003
13642
  " ",
13004
13643
  i + 1,
13005
13644
  ". ",
13006
13645
  s
13007
- ] }, s) : /* @__PURE__ */ jsxs5(Text7, { dimColor: true, children: [
13646
+ ] }, s) : /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
13008
13647
  " ",
13009
13648
  i + 1,
13010
13649
  ". ",
@@ -13014,45 +13653,45 @@ var CardFlow = ({
13014
13653
  ] }),
13015
13654
  step === "intro" && prompt(CARD_FLOW.intro.prompt)
13016
13655
  ] }),
13017
- step === "fetch-pm" && /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Fetching payment methods from your Link wallet..." }) }),
13018
- (step === "pick-pm" || step === "explain-pm") && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13019
- step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13020
- /* @__PURE__ */ jsx7(Text7, { children: "Which payment method should we use for the demo?" }),
13021
- /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx7(Text7, { children: i === selectedPmIndex ? /* @__PURE__ */ jsxs5(Text7, { color: "cyan", bold: true, children: [
13656
+ step === "fetch-pm" && /* @__PURE__ */ jsx9(Box6, { flexDirection: "column", children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Fetching payment methods from your Link wallet..." }) }),
13657
+ (step === "pick-pm" || step === "explain-pm") && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13658
+ step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13659
+ /* @__PURE__ */ jsx9(Text8, { children: "Which payment method should we use for the demo?" }),
13660
+ /* @__PURE__ */ jsx9(Box6, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx9(Text8, { children: i === selectedPmIndex ? /* @__PURE__ */ jsxs6(Text8, { color: "cyan", bold: true, children: [
13022
13661
  ">",
13023
13662
  " ",
13024
13663
  formatPmLabel(pm),
13025
13664
  pm.is_default ? " (default)" : ""
13026
- ] }) : /* @__PURE__ */ jsxs5(Text7, { dimColor: true, children: [
13665
+ ] }) : /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
13027
13666
  " ",
13028
13667
  formatPmLabel(pm),
13029
13668
  pm.is_default ? " (default)" : ""
13030
13669
  ] }) }, pm.id)) }),
13031
- /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
13670
+ /* @__PURE__ */ jsx9(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
13032
13671
  ] }),
13033
- paymentMethod && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13034
- /* @__PURE__ */ jsxs5(Text7, { color: "green", children: [
13672
+ paymentMethod && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13673
+ /* @__PURE__ */ jsxs6(Text8, { color: "green", children: [
13035
13674
  "\u2713 Using ",
13036
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: pmLabel }),
13675
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: pmLabel }),
13037
13676
  paymentMethod.is_default ? " (default)" : ""
13038
13677
  ] }),
13039
13678
  step === "explain-pm" && prompt(CARD_FLOW.explainPm.prompt)
13040
13679
  ] })
13041
13680
  ] }),
13042
- step === "create-spend" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13043
- /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.createSpend.description }),
13044
- /* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text7, { color: "cyan", children: CARD_FLOW.createSpend.loading }) })
13681
+ step === "create-spend" && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13682
+ /* @__PURE__ */ jsx9(MarkdownText, { children: CARD_FLOW.createSpend.description }),
13683
+ /* @__PURE__ */ jsx9(Box6, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: CARD_FLOW.createSpend.loading }) })
13045
13684
  ] }),
13046
- (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13047
- /* @__PURE__ */ jsxs5(Text7, { color: "green", children: [
13685
+ (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13686
+ /* @__PURE__ */ jsxs6(Text8, { color: "green", children: [
13048
13687
  "\u2713 Spend request created (",
13049
13688
  spendRequest.id,
13050
13689
  ")"
13051
13690
  ] }),
13052
- step === "await-approval" && /* @__PURE__ */ jsxs5(Fragment, { children: [
13053
- /* @__PURE__ */ jsx7(Text7, { children: CARD_FLOW.approval.description }),
13054
- /* @__PURE__ */ jsxs5(
13055
- Box5,
13691
+ step === "await-approval" && /* @__PURE__ */ jsxs6(Fragment, { children: [
13692
+ /* @__PURE__ */ jsx9(Text8, { children: CARD_FLOW.approval.description }),
13693
+ /* @__PURE__ */ jsxs6(
13694
+ Box6,
13056
13695
  {
13057
13696
  flexDirection: "column",
13058
13697
  borderStyle: "round",
@@ -13061,21 +13700,21 @@ var CardFlow = ({
13061
13700
  paddingY: 1,
13062
13701
  marginTop: 1,
13063
13702
  children: [
13064
- /* @__PURE__ */ jsxs5(Text7, { children: [
13703
+ /* @__PURE__ */ jsxs6(Text8, { children: [
13065
13704
  "Approve at:",
13066
13705
  " ",
13067
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: approvalUrl })
13706
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
13068
13707
  ] }),
13069
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: CARD_FLOW.approval.browserHint })
13708
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: CARD_FLOW.approval.browserHint })
13070
13709
  ]
13071
13710
  }
13072
13711
  ),
13073
- /* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text7, { color: "cyan", children: CARD_FLOW.approval.loading }) })
13712
+ /* @__PURE__ */ jsx9(Box6, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: CARD_FLOW.approval.loading }) })
13074
13713
  ] }),
13075
- step === "approval-timeout" && /* @__PURE__ */ jsxs5(Fragment, { children: [
13076
- /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
13077
- /* @__PURE__ */ jsxs5(
13078
- Box5,
13714
+ step === "approval-timeout" && /* @__PURE__ */ jsxs6(Fragment, { children: [
13715
+ /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
13716
+ /* @__PURE__ */ jsxs6(
13717
+ Box6,
13079
13718
  {
13080
13719
  flexDirection: "column",
13081
13720
  borderStyle: "round",
@@ -13084,38 +13723,38 @@ var CardFlow = ({
13084
13723
  paddingY: 1,
13085
13724
  marginTop: 1,
13086
13725
  children: [
13087
- /* @__PURE__ */ jsxs5(Text7, { children: [
13726
+ /* @__PURE__ */ jsxs6(Text8, { children: [
13088
13727
  "Approve at:",
13089
13728
  " ",
13090
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: approvalUrl })
13729
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
13091
13730
  ] }),
13092
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Press [Enter] to open in browser" })
13731
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Press [Enter] to open in browser" })
13093
13732
  ]
13094
13733
  }
13095
13734
  ),
13096
- /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "r Retry polling q Quit demo" }) })
13735
+ /* @__PURE__ */ jsx9(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "r Retry polling q Quit demo" }) })
13097
13736
  ] })
13098
13737
  ] }),
13099
- (step === "show-card" || step === "open-url" || step === "done") && card && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13100
- /* @__PURE__ */ jsx7(Text7, { color: "green", children: "\u2713 Approved!" }),
13101
- /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.showCard.description }),
13102
- /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", paddingX: 2, marginTop: 1, children: /* @__PURE__ */ jsxs5(Text7, { children: [
13103
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Number " }),
13104
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: formatCardNumber(card.number) }),
13738
+ (step === "show-card" || step === "open-url" || step === "done") && card && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13739
+ /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u2713 Approved!" }),
13740
+ /* @__PURE__ */ jsx9(MarkdownText, { children: CARD_FLOW.showCard.description }),
13741
+ /* @__PURE__ */ jsx9(Box6, { flexDirection: "column", paddingX: 2, marginTop: 1, children: /* @__PURE__ */ jsxs6(Text8, { children: [
13742
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Number " }),
13743
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: formatCardNumber(card.number) }),
13105
13744
  " ",
13106
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Exp " }),
13107
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: formatExpiry(card.exp_month, card.exp_year) }),
13745
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Exp " }),
13746
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: formatExpiry(card.exp_month, card.exp_year) }),
13108
13747
  " ",
13109
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "CVC " }),
13110
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: card.cvc }),
13111
- card.billing_address?.postal_code && /* @__PURE__ */ jsxs5(Fragment, { children: [
13748
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "CVC " }),
13749
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: card.cvc }),
13750
+ card.billing_address?.postal_code && /* @__PURE__ */ jsxs6(Fragment, { children: [
13112
13751
  " ",
13113
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Zip " }),
13114
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: card.billing_address.postal_code })
13752
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Zip " }),
13753
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: card.billing_address.postal_code })
13115
13754
  ] }),
13116
- card.valid_until && /* @__PURE__ */ jsxs5(Fragment, { children: [
13755
+ card.valid_until && /* @__PURE__ */ jsxs6(Fragment, { children: [
13117
13756
  " ",
13118
- /* @__PURE__ */ jsxs5(Text7, { dimColor: true, children: [
13757
+ /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
13119
13758
  "expires",
13120
13759
  " ",
13121
13760
  new Date(card.valid_until).toLocaleTimeString([], {
@@ -13127,14 +13766,14 @@ var CardFlow = ({
13127
13766
  ] }) }),
13128
13767
  step === "show-card" && prompt(CARD_FLOW.showCard.prompt)
13129
13768
  ] }),
13130
- step === "done" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13131
- /* @__PURE__ */ jsxs5(Text7, { color: "green", children: [
13769
+ step === "done" && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13770
+ /* @__PURE__ */ jsxs6(Text8, { color: "green", children: [
13132
13771
  "\u2713 ",
13133
13772
  CARD_FLOW.done.success
13134
13773
  ] }),
13135
- /* @__PURE__ */ jsx7(Text7, { children: CARD_FLOW.done.detail })
13774
+ /* @__PURE__ */ jsx9(Text8, { children: CARD_FLOW.done.detail })
13136
13775
  ] }),
13137
- step === "error" && /* @__PURE__ */ jsxs5(Text7, { color: "red", children: [
13776
+ step === "error" && /* @__PURE__ */ jsxs6(Text8, { color: "red", children: [
13138
13777
  "Error: ",
13139
13778
  error
13140
13779
  ] })
@@ -13142,7 +13781,7 @@ var CardFlow = ({
13142
13781
  };
13143
13782
 
13144
13783
  // src/commands/demo/spt-flow.tsx
13145
- import { Box as Box7, Text as Text9, useInput as useInput3 } from "ink";
13784
+ import { Box as Box8, Text as Text10, useInput as useInput3 } from "ink";
13146
13785
  import { useEffect as useEffect6, useRef as useRef3, useState as useState6 } from "react";
13147
13786
 
13148
13787
  // src/commands/mpp/decode.ts
@@ -13224,13 +13863,13 @@ function decodeStripeChallenge(challengeHeader) {
13224
13863
  }
13225
13864
 
13226
13865
  // src/commands/mpp/pay.tsx
13227
- import { Box as Box6, Text as Text8 } from "ink";
13228
- import Spinner3 from "ink-spinner";
13866
+ import { Box as Box7, Text as Text9 } from "ink";
13867
+ import Spinner4 from "ink-spinner";
13229
13868
  import { Credential, Method } from "mppx";
13230
13869
  import { Mppx, Transport } from "mppx/client";
13231
13870
  import { Methods as StripeMethods } from "mppx/stripe";
13232
13871
  import { useEffect as useEffect5, useState as useState5 } from "react";
13233
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
13872
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
13234
13873
  function buildHeaders(data, headers) {
13235
13874
  const result = {};
13236
13875
  if (data !== void 0) {
@@ -13404,21 +14043,21 @@ function MppPay({
13404
14043
  done: "Done"
13405
14044
  };
13406
14045
  if (error) {
13407
- return /* @__PURE__ */ jsxs6(Text8, { color: "red", children: [
14046
+ return /* @__PURE__ */ jsxs7(Text9, { color: "red", children: [
13408
14047
  "Error: ",
13409
14048
  error
13410
14049
  ] });
13411
14050
  }
13412
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13413
- step !== "done" && /* @__PURE__ */ jsx8(Box6, { children: /* @__PURE__ */ jsxs6(Text8, { color: "cyan", children: [
13414
- /* @__PURE__ */ jsx8(Spinner3, { type: "dots" }),
14051
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
14052
+ step !== "done" && /* @__PURE__ */ jsx10(Box7, { children: /* @__PURE__ */ jsxs7(Text9, { color: "cyan", children: [
14053
+ /* @__PURE__ */ jsx10(Spinner4, { type: "dots" }),
13415
14054
  " ",
13416
14055
  stepLabels[step],
13417
14056
  "..."
13418
14057
  ] }) }),
13419
- result && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13420
- /* @__PURE__ */ jsxs6(
13421
- Text8,
14058
+ result && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
14059
+ /* @__PURE__ */ jsxs7(
14060
+ Text9,
13422
14061
  {
13423
14062
  color: result.status >= 400 ? "red" : result.status >= 300 ? "yellow" : "green",
13424
14063
  children: [
@@ -13427,13 +14066,13 @@ function MppPay({
13427
14066
  ]
13428
14067
  }
13429
14068
  ),
13430
- /* @__PURE__ */ jsx8(Text8, { children: result.body })
14069
+ /* @__PURE__ */ jsx10(Text9, { children: result.body })
13431
14070
  ] })
13432
14071
  ] });
13433
14072
  }
13434
14073
 
13435
14074
  // src/commands/demo/spt-flow.tsx
13436
- import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
14075
+ import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
13437
14076
  var SptFlow = ({
13438
14077
  spendRequestRepo: spendRequestRepo2,
13439
14078
  paymentMethodsResource,
@@ -13616,26 +14255,26 @@ var SptFlow = ({
13616
14255
  ];
13617
14256
  return order.indexOf(step) > order.indexOf(target);
13618
14257
  };
13619
- const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
14258
+ const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
13620
14259
  "\n",
13621
14260
  ">",
13622
14261
  " ",
13623
14262
  label
13624
14263
  ] });
13625
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", gap: 1, children: [
13626
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: SPT_FLOW.title }),
13627
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13628
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", gap: 1, children: [
13629
- /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "[testmode]" }),
13630
- /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
14264
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, children: [
14265
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "cyan", children: SPT_FLOW.title }),
14266
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14267
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "row", gap: 1, children: [
14268
+ /* @__PURE__ */ jsx11(Text10, { color: "yellow", children: "[testmode]" }),
14269
+ /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
13631
14270
  DEMO_CLIMATE_API_URL,
13632
14271
  " ",
13633
14272
  DEMO_MPP_DEV_URL
13634
14273
  ] })
13635
14274
  ] }),
13636
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.intro.description }),
13637
- /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
13638
- /* @__PURE__ */ jsx9(Text9, { children: SPT_FLOW.intro.preamble }),
14275
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.intro.description }),
14276
+ /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexDirection: "column", children: [
14277
+ /* @__PURE__ */ jsx11(Text10, { children: SPT_FLOW.intro.preamble }),
13639
14278
  SPT_FLOW.intro.steps.map((s, i) => {
13640
14279
  const doneAfter = [
13641
14280
  "pick-pm",
@@ -13654,17 +14293,17 @@ var SptFlow = ({
13654
14293
  const done = pastStep(doneAfter[i]);
13655
14294
  const active = !done && (step === activeFrom[i] || pastStep(activeFrom[i]));
13656
14295
  const label = s.replace(/`/g, "");
13657
- return done ? /* @__PURE__ */ jsxs7(Text9, { dimColor: true, strikethrough: true, children: [
14296
+ return done ? /* @__PURE__ */ jsxs8(Text10, { dimColor: true, strikethrough: true, children: [
13658
14297
  " ",
13659
14298
  i + 1,
13660
14299
  ". ",
13661
14300
  label
13662
- ] }, s) : active ? /* @__PURE__ */ jsxs7(Text9, { bold: true, color: "cyan", children: [
14301
+ ] }, s) : active ? /* @__PURE__ */ jsxs8(Text10, { bold: true, color: "cyan", children: [
13663
14302
  " ",
13664
14303
  i + 1,
13665
14304
  ". ",
13666
14305
  label
13667
- ] }, s) : /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
14306
+ ] }, s) : /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
13668
14307
  " ",
13669
14308
  i + 1,
13670
14309
  ". ",
@@ -13674,47 +14313,47 @@ var SptFlow = ({
13674
14313
  ] }),
13675
14314
  step === "intro" && prompt(SPT_FLOW.intro.prompt)
13676
14315
  ] }),
13677
- step === "fetch-pm" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "Fetching payment methods..." }) }),
13678
- step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13679
- /* @__PURE__ */ jsx9(Text9, { children: "Which payment method should we use for the demo?" }),
13680
- /* @__PURE__ */ jsx9(Box7, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx9(Text9, { children: i === selectedPmIndex ? /* @__PURE__ */ jsxs7(Text9, { color: "cyan", bold: true, children: [
14316
+ step === "fetch-pm" && /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: "Fetching payment methods..." }) }),
14317
+ step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14318
+ /* @__PURE__ */ jsx11(Text10, { children: "Which payment method should we use for the demo?" }),
14319
+ /* @__PURE__ */ jsx11(Box8, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx11(Text10, { children: i === selectedPmIndex ? /* @__PURE__ */ jsxs8(Text10, { color: "cyan", bold: true, children: [
13681
14320
  ">",
13682
14321
  " ",
13683
14322
  pm.card_details ? `${pm.card_details.brand} ****${pm.card_details.last4}` : pm.type,
13684
14323
  pm.is_default ? " (default)" : ""
13685
- ] }) : /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
14324
+ ] }) : /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
13686
14325
  " ",
13687
14326
  pm.card_details ? `${pm.card_details.brand} ****${pm.card_details.last4}` : pm.type,
13688
14327
  pm.is_default ? " (default)" : ""
13689
14328
  ] }) }, pm.id)) }),
13690
- /* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
14329
+ /* @__PURE__ */ jsx11(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
13691
14330
  ] }),
13692
- (step === "probe" || step === "explain-402") && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13693
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.probe.description }),
13694
- step === "probe" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: SPT_FLOW.probe.loading }) }),
13695
- step === "explain-402" && networkId && /* @__PURE__ */ jsxs7(Fragment2, { children: [
13696
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.probe.detail }),
13697
- /* @__PURE__ */ jsxs7(Text9, { color: "green", children: [
14331
+ (step === "probe" || step === "explain-402") && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14332
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.probe.description }),
14333
+ step === "probe" && /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: SPT_FLOW.probe.loading }) }),
14334
+ step === "explain-402" && networkId && /* @__PURE__ */ jsxs8(Fragment2, { children: [
14335
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.probe.detail }),
14336
+ /* @__PURE__ */ jsxs8(Text10, { color: "green", children: [
13698
14337
  "\u2713 Got HTTP 402 \u2014 network_id: ",
13699
- /* @__PURE__ */ jsx9(Text9, { bold: true, children: networkId })
14338
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: networkId })
13700
14339
  ] }),
13701
14340
  prompt(SPT_FLOW.probe.prompt)
13702
14341
  ] })
13703
14342
  ] }),
13704
- step === "create-spend" && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13705
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.createSpend.description }),
13706
- /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: SPT_FLOW.createSpend.loading }) })
14343
+ step === "create-spend" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14344
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.createSpend.description }),
14345
+ /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: SPT_FLOW.createSpend.loading }) })
13707
14346
  ] }),
13708
- (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13709
- /* @__PURE__ */ jsxs7(Text9, { color: "green", children: [
14347
+ (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14348
+ /* @__PURE__ */ jsxs8(Text10, { color: "green", children: [
13710
14349
  "\u2713 Spend request created (",
13711
14350
  spendRequest.id,
13712
14351
  ")"
13713
14352
  ] }),
13714
- step === "await-approval" && /* @__PURE__ */ jsxs7(Fragment2, { children: [
13715
- /* @__PURE__ */ jsx9(Text9, { children: SPT_FLOW.approval.description }),
13716
- /* @__PURE__ */ jsxs7(
13717
- Box7,
14353
+ step === "await-approval" && /* @__PURE__ */ jsxs8(Fragment2, { children: [
14354
+ /* @__PURE__ */ jsx11(Text10, { children: SPT_FLOW.approval.description }),
14355
+ /* @__PURE__ */ jsxs8(
14356
+ Box8,
13718
14357
  {
13719
14358
  flexDirection: "column",
13720
14359
  borderStyle: "round",
@@ -13723,21 +14362,21 @@ var SptFlow = ({
13723
14362
  paddingY: 1,
13724
14363
  marginTop: 1,
13725
14364
  children: [
13726
- /* @__PURE__ */ jsxs7(Text9, { children: [
14365
+ /* @__PURE__ */ jsxs8(Text10, { children: [
13727
14366
  "Approve at:",
13728
14367
  " ",
13729
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: approvalUrl })
14368
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "cyan", children: approvalUrl })
13730
14369
  ] }),
13731
- /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: SPT_FLOW.approval.browserHint })
14370
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: SPT_FLOW.approval.browserHint })
13732
14371
  ]
13733
14372
  }
13734
14373
  ),
13735
- /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: SPT_FLOW.approval.loading }) })
14374
+ /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: SPT_FLOW.approval.loading }) })
13736
14375
  ] }),
13737
- step === "approval-timeout" && /* @__PURE__ */ jsxs7(Fragment2, { children: [
13738
- /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
13739
- /* @__PURE__ */ jsxs7(
13740
- Box7,
14376
+ step === "approval-timeout" && /* @__PURE__ */ jsxs8(Fragment2, { children: [
14377
+ /* @__PURE__ */ jsx11(Text10, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
14378
+ /* @__PURE__ */ jsxs8(
14379
+ Box8,
13741
14380
  {
13742
14381
  flexDirection: "column",
13743
14382
  borderStyle: "round",
@@ -13746,35 +14385,35 @@ var SptFlow = ({
13746
14385
  paddingY: 1,
13747
14386
  marginTop: 1,
13748
14387
  children: [
13749
- /* @__PURE__ */ jsxs7(Text9, { children: [
14388
+ /* @__PURE__ */ jsxs8(Text10, { children: [
13750
14389
  "Approve at:",
13751
14390
  " ",
13752
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: approvalUrl })
14391
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "cyan", children: approvalUrl })
13753
14392
  ] }),
13754
- /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Press [Enter] to open in browser" })
14393
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "Press [Enter] to open in browser" })
13755
14394
  ]
13756
14395
  }
13757
14396
  ),
13758
- /* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "r Retry polling q Quit demo" }) })
14397
+ /* @__PURE__ */ jsx11(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "r Retry polling q Quit demo" }) })
13759
14398
  ] })
13760
14399
  ] }),
13761
- (step === "mpp-pay-gate" || step === "mpp-pay") && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13762
- /* @__PURE__ */ jsx9(Text9, { color: "green", children: "\u2713 Approved!" }),
13763
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.mppPay.description }),
14400
+ (step === "mpp-pay-gate" || step === "mpp-pay") && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14401
+ /* @__PURE__ */ jsx11(Text10, { color: "green", children: "\u2713 Approved!" }),
14402
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.mppPay.description }),
13764
14403
  step === "mpp-pay-gate" && prompt(SPT_FLOW.mppPay.prompt),
13765
- step === "mpp-pay" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: SPT_FLOW.mppPay.loading }) })
14404
+ step === "mpp-pay" && /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: SPT_FLOW.mppPay.loading }) })
13766
14405
  ] }),
13767
- step === "done" && payResult && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13768
- /* @__PURE__ */ jsxs7(Text9, { bold: true, color: "green", children: [
14406
+ step === "done" && payResult && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14407
+ /* @__PURE__ */ jsxs8(Text10, { bold: true, color: "green", children: [
13769
14408
  "\u2713 ",
13770
14409
  SPT_FLOW.done.success,
13771
14410
  " (HTTP ",
13772
14411
  payResult.status,
13773
14412
  ")"
13774
14413
  ] }),
13775
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.done.detail })
14414
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.done.detail })
13776
14415
  ] }),
13777
- step === "error" && /* @__PURE__ */ jsxs7(Text9, { color: "red", children: [
14416
+ step === "error" && /* @__PURE__ */ jsxs8(Text10, { color: "red", children: [
13778
14417
  "Error: ",
13779
14418
  error
13780
14419
  ] })
@@ -13782,7 +14421,7 @@ var SptFlow = ({
13782
14421
  };
13783
14422
 
13784
14423
  // src/commands/demo/demo-runner.tsx
13785
- import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
14424
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
13786
14425
  var DemoRunner = ({
13787
14426
  authRepo: authRepo2,
13788
14427
  spendRequestRepo: spendRequestRepo2,
@@ -13824,7 +14463,7 @@ var DemoRunner = ({
13824
14463
  setPhase("spt-flow");
13825
14464
  }
13826
14465
  });
13827
- const onCardComplete = useCallback2(
14466
+ const onCardComplete = useCallback3(
13828
14467
  (result) => {
13829
14468
  setPaymentMethodId(result.paymentMethodId);
13830
14469
  setCardSuccess(result.success);
@@ -13840,7 +14479,7 @@ var DemoRunner = ({
13840
14479
  },
13841
14480
  [runSpt, onComplete, exit]
13842
14481
  );
13843
- const onSptComplete = useCallback2(
14482
+ const onSptComplete = useCallback3(
13844
14483
  (success) => {
13845
14484
  setSptSuccess(success);
13846
14485
  setPhase("summary");
@@ -13851,12 +14490,12 @@ var DemoRunner = ({
13851
14490
  },
13852
14491
  [onComplete, exit]
13853
14492
  );
13854
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, children: [
13855
- /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
13856
- /* @__PURE__ */ jsx10(Text10, { bold: true, children: DEMO_MENU.title }),
13857
- /* @__PURE__ */ jsx10(Text10, { children: DEMO_MENU.subtitle })
14493
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, children: [
14494
+ /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14495
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: DEMO_MENU.title }),
14496
+ /* @__PURE__ */ jsx12(Text11, { children: DEMO_MENU.subtitle })
13858
14497
  ] }),
13859
- phase === "auth" && /* @__PURE__ */ jsx10(
14498
+ phase === "auth" && /* @__PURE__ */ jsx12(
13860
14499
  Login,
13861
14500
  {
13862
14501
  authResource: authRepo2,
@@ -13865,25 +14504,25 @@ var DemoRunner = ({
13865
14504
  onComplete: () => setPhase(postAuthPhase)
13866
14505
  }
13867
14506
  ),
13868
- phase === "menu" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
13869
- /* @__PURE__ */ jsx10(Text10, { children: DEMO_MENU.question }),
13870
- /* @__PURE__ */ jsx10(Box8, { flexDirection: "column", marginTop: 1, gap: 1, children: DEMO_MENU.options.map((opt, i) => /* @__PURE__ */ jsx10(Box8, { flexDirection: "column", children: i === menuIndex ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
13871
- /* @__PURE__ */ jsxs8(Text10, { color: "cyan", bold: true, children: [
14507
+ phase === "menu" && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14508
+ /* @__PURE__ */ jsx12(Text11, { children: DEMO_MENU.question }),
14509
+ /* @__PURE__ */ jsx12(Box9, { flexDirection: "column", marginTop: 1, gap: 1, children: DEMO_MENU.options.map((opt, i) => /* @__PURE__ */ jsx12(Box9, { flexDirection: "column", children: i === menuIndex ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
14510
+ /* @__PURE__ */ jsxs9(Text11, { color: "cyan", bold: true, children: [
13872
14511
  ">",
13873
14512
  " ",
13874
14513
  opt.label
13875
14514
  ] }),
13876
- /* @__PURE__ */ jsxs8(Text10, { color: "cyan", children: [
14515
+ /* @__PURE__ */ jsxs9(Text11, { color: "cyan", children: [
13877
14516
  " ",
13878
14517
  opt.description
13879
14518
  ] })
13880
- ] }) : /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
14519
+ ] }) : /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
13881
14520
  " ",
13882
14521
  opt.label
13883
14522
  ] }) }, opt.key)) }),
13884
- /* @__PURE__ */ jsx10(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: DEMO_MENU.hint }) })
14523
+ /* @__PURE__ */ jsx12(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: DEMO_MENU.hint }) })
13885
14524
  ] }),
13886
- runCard && phase !== "menu" && /* @__PURE__ */ jsx10(
14525
+ runCard && phase !== "menu" && /* @__PURE__ */ jsx12(
13887
14526
  CardFlow,
13888
14527
  {
13889
14528
  spendRequestRepo: spendRequestRepo2,
@@ -13892,19 +14531,19 @@ var DemoRunner = ({
13892
14531
  onComplete: onCardComplete
13893
14532
  }
13894
14533
  ),
13895
- phase === "card-done" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
13896
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\u2500\u2500\u2500" }),
13897
- /* @__PURE__ */ jsx10(MarkdownText, { children: DEMO_MENU.transition }),
13898
- /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
14534
+ phase === "card-done" && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14535
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "\u2500\u2500\u2500" }),
14536
+ /* @__PURE__ */ jsx12(MarkdownText, { children: DEMO_MENU.transition }),
14537
+ /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
13899
14538
  "\n",
13900
14539
  ">",
13901
14540
  " ",
13902
14541
  DEMO_MENU.transitionPrompt
13903
14542
  ] })
13904
14543
  ] }),
13905
- runSpt && (phase === "spt-flow" || phase === "summary") && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
13906
- runCard && /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\u2500\u2500\u2500" }),
13907
- /* @__PURE__ */ jsx10(
14544
+ runSpt && (phase === "spt-flow" || phase === "summary") && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14545
+ runCard && /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "\u2500\u2500\u2500" }),
14546
+ /* @__PURE__ */ jsx12(
13908
14547
  SptFlow,
13909
14548
  {
13910
14549
  spendRequestRepo: spendRequestRepo2,
@@ -13914,30 +14553,30 @@ var DemoRunner = ({
13914
14553
  }
13915
14554
  )
13916
14555
  ] }),
13917
- phase === "summary" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
13918
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\u2500\u2500\u2500" }),
13919
- /* @__PURE__ */ jsx10(Text10, { bold: true, children: "Done!" }),
13920
- cardSuccess !== null && /* @__PURE__ */ jsxs8(Text10, { color: cardSuccess ? "green" : "red", children: [
14556
+ phase === "summary" && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14557
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "\u2500\u2500\u2500" }),
14558
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Done!" }),
14559
+ cardSuccess !== null && /* @__PURE__ */ jsxs9(Text11, { color: cardSuccess ? "green" : "red", children: [
13921
14560
  cardSuccess ? "\u2713" : "\u2717",
13922
14561
  " Virtual card flow"
13923
14562
  ] }),
13924
- sptSuccess !== null && /* @__PURE__ */ jsxs8(Text10, { color: sptSuccess ? "green" : "red", children: [
14563
+ sptSuccess !== null && /* @__PURE__ */ jsxs9(Text11, { color: sptSuccess ? "green" : "red", children: [
13925
14564
  sptSuccess ? "\u2713" : "\u2717",
13926
14565
  " Machine payment flow"
13927
14566
  ] }),
13928
- /* @__PURE__ */ jsx10(AppDownloadQrCodes, {})
14567
+ /* @__PURE__ */ jsx12(AppDownloadQrCodes, {})
13929
14568
  ] })
13930
14569
  ] });
13931
14570
  };
13932
14571
 
13933
14572
  // src/commands/demo/index.tsx
13934
- import { jsx as jsx11 } from "react/jsx-runtime";
13935
- var demoOptions = z2.object({
13936
- onlyCard: z2.boolean().default(false).describe("Run only the virtual card flow"),
13937
- onlySpt: z2.boolean().default(false).describe("Run only the machine payment (SPT) flow")
14573
+ import { jsx as jsx13 } from "react/jsx-runtime";
14574
+ var demoOptions = z3.object({
14575
+ onlyCard: z3.boolean().default(false).describe("Run only the virtual card flow"),
14576
+ onlySpt: z3.boolean().default(false).describe("Run only the machine payment (SPT) flow")
13938
14577
  });
13939
14578
  function createDemoCli(authRepo2, spendRequestRepo2, createPaymentMethodsResource, authStorage2) {
13940
- return Cli2.create("demo", {
14579
+ return Cli3.create("demo", {
13941
14580
  description: "Run an interactive demo of both Link payment flows (virtual card + machine payment)",
13942
14581
  options: demoOptions,
13943
14582
  outputPolicy: "agent-only",
@@ -13950,7 +14589,7 @@ function createDemoCli(authRepo2, spendRequestRepo2, createPaymentMethodsResourc
13950
14589
  }
13951
14590
  const paymentMethodsResource = createPaymentMethodsResource();
13952
14591
  return renderInteractive(
13953
- /* @__PURE__ */ jsx11(
14592
+ /* @__PURE__ */ jsx13(
13954
14593
  DemoRunner,
13955
14594
  {
13956
14595
  authRepo: authRepo2,
@@ -13970,85 +14609,61 @@ function createDemoCli(authRepo2, spendRequestRepo2, createPaymentMethodsResourc
13970
14609
  }
13971
14610
 
13972
14611
  // src/commands/mpp/index.tsx
13973
- import { Cli as Cli3, z as z4 } from "incur";
13974
-
13975
- // src/utils/require-auth.ts
13976
- var NOT_AUTHENTICATED_ERROR = {
13977
- code: "NOT_AUTHENTICATED",
13978
- message: 'Not authenticated. Run "link-cli auth login" first.',
13979
- cta: {
13980
- commands: [{ command: "auth login", description: "Log in to Link" }]
13981
- }
13982
- };
13983
- function requireAuth(authStorage2, envAccessToken2) {
13984
- const store = authStorage2 ?? storage;
13985
- return (c, next) => {
13986
- if (!envAccessToken2 && !store.isAuthenticated()) {
13987
- return c.error(NOT_AUTHENTICATED_ERROR);
13988
- }
13989
- return next();
13990
- };
13991
- }
13992
- function requireAuthGuard(c, authStorage2, envAccessToken2) {
13993
- const store = authStorage2 ?? storage;
13994
- if (!envAccessToken2 && !store.isAuthenticated()) {
13995
- c.error(NOT_AUTHENTICATED_ERROR);
13996
- }
13997
- }
14612
+ import { Cli as Cli4, z as z5 } from "incur";
13998
14613
 
13999
14614
  // src/commands/mpp/decode-view.tsx
14000
- import { Box as Box9, Text as Text11 } from "ink";
14001
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
14615
+ import { Box as Box10, Text as Text12 } from "ink";
14616
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
14002
14617
  function DecodeChallengeView({
14003
14618
  decoded
14004
14619
  }) {
14005
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14006
- /* @__PURE__ */ jsx12(Text11, { color: "green", children: "\u2713 Stripe challenge decoded" }),
14007
- /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
14008
- /* @__PURE__ */ jsxs9(Text11, { children: [
14620
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14621
+ /* @__PURE__ */ jsx14(Text12, { color: "green", children: "\u2713 Stripe challenge decoded" }),
14622
+ /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
14623
+ /* @__PURE__ */ jsxs10(Text12, { children: [
14009
14624
  "ID: ",
14010
- /* @__PURE__ */ jsx12(Text11, { bold: true, children: decoded.id })
14625
+ /* @__PURE__ */ jsx14(Text12, { bold: true, children: decoded.id })
14011
14626
  ] }),
14012
- /* @__PURE__ */ jsxs9(Text11, { children: [
14627
+ /* @__PURE__ */ jsxs10(Text12, { children: [
14013
14628
  "Realm: ",
14014
- /* @__PURE__ */ jsx12(Text11, { bold: true, children: decoded.realm })
14629
+ /* @__PURE__ */ jsx14(Text12, { bold: true, children: decoded.realm })
14015
14630
  ] }),
14016
- /* @__PURE__ */ jsxs9(Text11, { children: [
14631
+ /* @__PURE__ */ jsxs10(Text12, { children: [
14017
14632
  "Network ID: ",
14018
- /* @__PURE__ */ jsx12(Text11, { bold: true, children: decoded.network_id })
14633
+ /* @__PURE__ */ jsx14(Text12, { bold: true, children: decoded.network_id })
14019
14634
  ] }),
14020
- /* @__PURE__ */ jsx12(Text11, { children: "Request JSON:" }),
14021
- /* @__PURE__ */ jsx12(Text11, { children: JSON.stringify(decoded.request_json, null, 2) })
14635
+ /* @__PURE__ */ jsx14(Text12, { children: "Request JSON:" }),
14636
+ /* @__PURE__ */ jsx14(Text12, { children: JSON.stringify(decoded.request_json, null, 2) })
14022
14637
  ] })
14023
14638
  ] });
14024
14639
  }
14025
14640
 
14026
14641
  // src/commands/mpp/schema.ts
14027
- import { z as z3 } from "incur";
14028
- var payOptions = z3.object({
14029
- spendRequestId: z3.string().describe(
14642
+ import { z as z4 } from "incur";
14643
+ var payOptions = z4.object({
14644
+ spendRequestId: z4.string().describe(
14030
14645
  'Approved spend request ID with credential_type "shared_payment_token"'
14031
14646
  ),
14032
- method: z3.string().optional().describe("HTTP method (default: GET, or POST if --data is provided)"),
14033
- data: z3.string().optional().describe("Request body (implies POST if --method is not set)"),
14034
- header: z3.array(z3.string()).default([]).describe('Request header in "Name: Value" format (repeatable)')
14647
+ method: z4.string().optional().describe("HTTP method (default: GET, or POST if --data is provided)"),
14648
+ data: z4.string().optional().describe("Request body (implies POST if --method is not set)"),
14649
+ header: z4.array(z4.string()).default([]).describe('Request header in "Name: Value" format (repeatable)')
14035
14650
  });
14036
- var decodeOptions = z3.object({
14037
- challenge: z3.string().describe(
14651
+ var decodeOptions = z4.object({
14652
+ challenge: z4.string().describe(
14038
14653
  "Raw WWW-Authenticate header value; may include multiple payment challenges"
14039
14654
  )
14040
14655
  });
14041
14656
 
14042
14657
  // src/commands/mpp/index.tsx
14043
- import { jsx as jsx13 } from "react/jsx-runtime";
14658
+ import { jsx as jsx15 } from "react/jsx-runtime";
14044
14659
  function createMppCli(repository, authStorage2, envAccessToken2) {
14045
- const cli2 = Cli3.create("mpp", {
14660
+ const cli2 = Cli4.create("mpp", {
14046
14661
  description: "Machine payment protocol (MPP) commands"
14047
14662
  });
14048
14663
  cli2.command("pay", {
14049
14664
  description: "Complete a machine payment protocol (MPP) payment using an approved spend request",
14050
- args: z4.object({
14051
- url: z4.string().describe("URL to pay")
14665
+ args: z5.object({
14666
+ url: z5.string().describe("URL to pay")
14052
14667
  }),
14053
14668
  options: payOptions,
14054
14669
  alias: { method: "X", data: "d", header: "H" },
@@ -14063,7 +14678,7 @@ function createMppCli(repository, authStorage2, envAccessToken2) {
14063
14678
  if (!c.agent && !c.formatExplicit) {
14064
14679
  let capturedResult = null;
14065
14680
  return renderInteractive(
14066
- /* @__PURE__ */ jsx13(
14681
+ /* @__PURE__ */ jsx15(
14067
14682
  MppPay,
14068
14683
  {
14069
14684
  url,
@@ -14102,7 +14717,7 @@ function createMppCli(repository, authStorage2, envAccessToken2) {
14102
14717
  const decoded = decodeStripeChallenge(c.options.challenge);
14103
14718
  if (!c.agent && !c.formatExplicit) {
14104
14719
  return renderInteractive(
14105
- /* @__PURE__ */ jsx13(DecodeChallengeView, { decoded }),
14720
+ /* @__PURE__ */ jsx15(DecodeChallengeView, { decoded }),
14106
14721
  () => decoded
14107
14722
  );
14108
14723
  }
@@ -14113,12 +14728,12 @@ function createMppCli(repository, authStorage2, envAccessToken2) {
14113
14728
  }
14114
14729
 
14115
14730
  // src/commands/onboard/index.tsx
14116
- import { Cli as Cli4 } from "incur";
14731
+ import { Cli as Cli5 } from "incur";
14117
14732
 
14118
14733
  // src/commands/onboard/onboard-runner.tsx
14119
- import { Box as Box10, Text as Text12, useApp as useApp2, useInput as useInput5 } from "ink";
14734
+ import { Box as Box11, Text as Text13, useApp as useApp2, useInput as useInput5 } from "ink";
14120
14735
  import { useEffect as useEffect7, useRef as useRef4, useState as useState8 } from "react";
14121
- import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
14736
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
14122
14737
  var OnboardRunner = ({
14123
14738
  authRepo: authRepo2,
14124
14739
  spendRequestRepo: spendRequestRepo2,
@@ -14184,21 +14799,21 @@ var OnboardRunner = ({
14184
14799
  const order = ["welcome", "auth", "payment-methods", "demo"];
14185
14800
  return order.indexOf(phase) > order.indexOf(target);
14186
14801
  };
14187
- const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs10(Text12, { dimColor: true, children: [
14802
+ const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
14188
14803
  "\n",
14189
14804
  ">",
14190
14805
  " ",
14191
14806
  label
14192
14807
  ] });
14193
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", gap: 1, children: [
14194
- /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14195
- /* @__PURE__ */ jsx14(Text12, { bold: true, children: ONBOARD.title }),
14196
- /* @__PURE__ */ jsx14(Text12, { children: ONBOARD.subtitle })
14808
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", gap: 1, children: [
14809
+ /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
14810
+ /* @__PURE__ */ jsx16(Text13, { bold: true, children: ONBOARD.title }),
14811
+ /* @__PURE__ */ jsx16(Text13, { children: ONBOARD.subtitle })
14197
14812
  ] }),
14198
- /* @__PURE__ */ jsx14(Box10, { flexDirection: "column", children: authSkipped || pastPhase("auth") ? /* @__PURE__ */ jsxs10(Text12, { color: "green", children: [
14813
+ /* @__PURE__ */ jsx16(Box11, { flexDirection: "column", children: authSkipped || pastPhase("auth") ? /* @__PURE__ */ jsxs11(Text13, { color: "green", children: [
14199
14814
  "\u2713 ",
14200
14815
  authSkipped ? ONBOARD.auth.alreadyLoggedIn : ONBOARD.auth.authenticated
14201
- ] }) : phase === "auth" && !storage2.isAuthenticated() ? /* @__PURE__ */ jsx14(
14816
+ ] }) : phase === "auth" && !storage2.isAuthenticated() ? /* @__PURE__ */ jsx16(
14202
14817
  Login,
14203
14818
  {
14204
14819
  authResource: authRepo2,
@@ -14207,24 +14822,24 @@ var OnboardRunner = ({
14207
14822
  onComplete: () => authResolver.current?.()
14208
14823
  }
14209
14824
  ) : null }),
14210
- pastPhase("auth") && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14211
- phase === "payment-methods" && !pmMissing && /* @__PURE__ */ jsx14(Text12, { color: "cyan", children: ONBOARD.paymentMethods.loading }),
14212
- pmMissing && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14213
- /* @__PURE__ */ jsx14(Text12, { color: "yellow", children: ONBOARD.paymentMethods.missing }),
14214
- /* @__PURE__ */ jsx14(Box10, { marginTop: 1, children: /* @__PURE__ */ jsxs10(Text12, { children: [
14825
+ pastPhase("auth") && /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
14826
+ phase === "payment-methods" && !pmMissing && /* @__PURE__ */ jsx16(Text13, { color: "cyan", children: ONBOARD.paymentMethods.loading }),
14827
+ pmMissing && /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
14828
+ /* @__PURE__ */ jsx16(Text13, { color: "yellow", children: ONBOARD.paymentMethods.missing }),
14829
+ /* @__PURE__ */ jsx16(Box11, { marginTop: 1, children: /* @__PURE__ */ jsxs11(Text13, { children: [
14215
14830
  "Visit",
14216
14831
  " ",
14217
- /* @__PURE__ */ jsx14(Text12, { bold: true, color: "cyan", children: "app.link.com/wallet" }),
14832
+ /* @__PURE__ */ jsx16(Text13, { bold: true, color: "cyan", children: "app.link.com/wallet" }),
14218
14833
  " ",
14219
14834
  "to add a payment method, then press [Enter] to continue."
14220
14835
  ] }) }),
14221
14836
  prompt(ONBOARD.paymentMethods.retryPrompt)
14222
14837
  ] }),
14223
- pastPhase("payment-methods") && /* @__PURE__ */ jsx14(Text12, { color: "green", children: "\u2713 Payment method found" })
14838
+ pastPhase("payment-methods") && /* @__PURE__ */ jsx16(Text13, { color: "green", children: "\u2713 Payment method found" })
14224
14839
  ] }),
14225
- phase === "demo" && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14226
- /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "\u2500\u2500\u2500" }),
14227
- /* @__PURE__ */ jsx14(
14840
+ phase === "demo" && /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
14841
+ /* @__PURE__ */ jsx16(Text13, { dimColor: true, children: "\u2500\u2500\u2500" }),
14842
+ /* @__PURE__ */ jsx16(
14228
14843
  DemoRunner,
14229
14844
  {
14230
14845
  authRepo: authRepo2,
@@ -14235,7 +14850,7 @@ var OnboardRunner = ({
14235
14850
  }
14236
14851
  )
14237
14852
  ] }),
14238
- error && /* @__PURE__ */ jsxs10(Text12, { color: "red", children: [
14853
+ error && /* @__PURE__ */ jsxs11(Text13, { color: "red", children: [
14239
14854
  "Error: ",
14240
14855
  error
14241
14856
  ] })
@@ -14243,9 +14858,9 @@ var OnboardRunner = ({
14243
14858
  };
14244
14859
 
14245
14860
  // src/commands/onboard/index.tsx
14246
- import { jsx as jsx15 } from "react/jsx-runtime";
14861
+ import { jsx as jsx17 } from "react/jsx-runtime";
14247
14862
  function createOnboardCli(authRepo2, spendRequestRepo2, createPaymentMethodsResource, authStorage2) {
14248
- return Cli4.create("onboard", {
14863
+ return Cli5.create("onboard", {
14249
14864
  description: "Guided setup: authenticate, verify payment methods, and demo both payment flows",
14250
14865
  outputPolicy: "agent-only",
14251
14866
  async run(c) {
@@ -14257,7 +14872,7 @@ function createOnboardCli(authRepo2, spendRequestRepo2, createPaymentMethodsReso
14257
14872
  }
14258
14873
  const paymentMethodsResource = createPaymentMethodsResource();
14259
14874
  return renderInteractive(
14260
- /* @__PURE__ */ jsx15(
14875
+ /* @__PURE__ */ jsx17(
14261
14876
  OnboardRunner,
14262
14877
  {
14263
14878
  authRepo: authRepo2,
@@ -14275,11 +14890,11 @@ function createOnboardCli(authRepo2, spendRequestRepo2, createPaymentMethodsReso
14275
14890
  }
14276
14891
 
14277
14892
  // src/commands/payment-methods/index.tsx
14278
- import { Cli as Cli5 } from "incur";
14893
+ import { Cli as Cli6 } from "incur";
14279
14894
 
14280
14895
  // src/commands/payment-methods/add.tsx
14281
- import { Box as Box11, Text as Text13, useApp as useApp3, useInput as useInput6 } from "ink";
14282
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
14896
+ import { Box as Box12, Text as Text14, useApp as useApp3, useInput as useInput6 } from "ink";
14897
+ import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
14283
14898
  var WALLET_URL = "https://app.link.com/wallet";
14284
14899
  var AddPaymentMethod = () => {
14285
14900
  const { exit } = useApp3();
@@ -14289,10 +14904,10 @@ var AddPaymentMethod = () => {
14289
14904
  exit();
14290
14905
  }
14291
14906
  });
14292
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingY: 1, children: [
14293
- /* @__PURE__ */ jsx16(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text13, { bold: true, children: "Add Payment Method" }) }),
14294
- /* @__PURE__ */ jsxs11(
14295
- Box11,
14907
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingY: 1, children: [
14908
+ /* @__PURE__ */ jsx18(Box12, { marginBottom: 1, children: /* @__PURE__ */ jsx18(Text14, { bold: true, children: "Add Payment Method" }) }),
14909
+ /* @__PURE__ */ jsxs12(
14910
+ Box12,
14296
14911
  {
14297
14912
  flexDirection: "column",
14298
14913
  borderStyle: "round",
@@ -14300,12 +14915,12 @@ var AddPaymentMethod = () => {
14300
14915
  paddingX: 2,
14301
14916
  paddingY: 1,
14302
14917
  children: [
14303
- /* @__PURE__ */ jsxs11(Text13, { children: [
14918
+ /* @__PURE__ */ jsxs12(Text14, { children: [
14304
14919
  "Open:",
14305
14920
  " ",
14306
- /* @__PURE__ */ jsx16(Text13, { bold: true, color: "cyan", children: WALLET_URL })
14921
+ /* @__PURE__ */ jsx18(Text14, { bold: true, color: "cyan", children: WALLET_URL })
14307
14922
  ] }),
14308
- /* @__PURE__ */ jsx16(Text13, { dimColor: true, children: "Press Enter to open in browser" })
14923
+ /* @__PURE__ */ jsx18(Text14, { dimColor: true, children: "Press Enter to open in browser" })
14309
14924
  ]
14310
14925
  }
14311
14926
  )
@@ -14313,48 +14928,48 @@ var AddPaymentMethod = () => {
14313
14928
  };
14314
14929
 
14315
14930
  // src/commands/payment-methods/list.tsx
14316
- import { Box as Box12, Text as Text14 } from "ink";
14317
- import Spinner4 from "ink-spinner";
14318
- import { useCallback as useCallback3 } from "react";
14319
- import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
14931
+ import { Box as Box13, Text as Text15 } from "ink";
14932
+ import Spinner5 from "ink-spinner";
14933
+ import { useCallback as useCallback4 } from "react";
14934
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
14320
14935
  var PaymentMethodsList = ({
14321
14936
  resource,
14322
14937
  onComplete
14323
14938
  }) => {
14324
- const action = useCallback3(() => resource.listPaymentMethods(), [resource]);
14939
+ const action = useCallback4(() => resource.listPaymentMethods(), [resource]);
14325
14940
  const { status, data: methods, error } = useAsyncAction(action, onComplete);
14326
14941
  if (status === "loading") {
14327
- return /* @__PURE__ */ jsx17(Box12, { children: /* @__PURE__ */ jsxs12(Text14, { color: "cyan", children: [
14328
- /* @__PURE__ */ jsx17(Spinner4, { type: "dots" }),
14942
+ return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsxs13(Text15, { color: "cyan", children: [
14943
+ /* @__PURE__ */ jsx19(Spinner5, { type: "dots" }),
14329
14944
  " Loading payment methods..."
14330
14945
  ] }) });
14331
14946
  }
14332
14947
  if (status === "error") {
14333
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
14334
- /* @__PURE__ */ jsx17(Text14, { color: "red", children: "\u2717 Failed to load payment methods" }),
14335
- /* @__PURE__ */ jsx17(Text14, { color: "red", children: error })
14948
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
14949
+ /* @__PURE__ */ jsx19(Text15, { color: "red", children: "\u2717 Failed to load payment methods" }),
14950
+ /* @__PURE__ */ jsx19(Text15, { color: "red", children: error })
14336
14951
  ] });
14337
14952
  }
14338
14953
  if (!methods || methods.length === 0) {
14339
- return /* @__PURE__ */ jsx17(Box12, { children: /* @__PURE__ */ jsx17(Text14, { dimColor: true, children: "No payment methods found" }) });
14954
+ return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: "No payment methods found" }) });
14340
14955
  }
14341
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
14342
- /* @__PURE__ */ jsx17(Text14, { bold: true, children: "Payment Methods" }),
14343
- /* @__PURE__ */ jsx17(Box12, { flexDirection: "column", marginTop: 1, children: methods.map((pm) => {
14956
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
14957
+ /* @__PURE__ */ jsx19(Text15, { bold: true, children: "Payment Methods" }),
14958
+ /* @__PURE__ */ jsx19(Box13, { flexDirection: "column", marginTop: 1, children: methods.map((pm) => {
14344
14959
  const label = pm.card_details?.brand ?? pm.bank_account_details?.bank_name ?? "Bank account";
14345
14960
  const last4 = pm.card_details?.last4 ?? pm.bank_account_details?.last4;
14346
14961
  const suffix = pm.nickname ? `(${pm.nickname})` : "";
14347
14962
  const agenticCap = pm.capabilities?.agentic_payments;
14348
14963
  const ineligible = agenticCap && !agenticCap.eligible;
14349
- return /* @__PURE__ */ jsx17(Box12, { paddingX: 2, children: /* @__PURE__ */ jsxs12(Text14, { children: [
14350
- /* @__PURE__ */ jsx17(Text14, { dimColor: true, children: pm.id }),
14964
+ return /* @__PURE__ */ jsx19(Box13, { paddingX: 2, children: /* @__PURE__ */ jsxs13(Text15, { children: [
14965
+ /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: pm.id }),
14351
14966
  " ",
14352
14967
  label,
14353
14968
  " ****",
14354
14969
  last4,
14355
14970
  suffix ? ` ${suffix}` : "",
14356
- pm.is_default ? /* @__PURE__ */ jsx17(Text14, { color: "green", children: " (default)" }) : "",
14357
- ineligible ? /* @__PURE__ */ jsxs12(Text14, { dimColor: true, children: [
14971
+ pm.is_default ? /* @__PURE__ */ jsx19(Text15, { color: "green", children: " (default)" }) : "",
14972
+ ineligible ? /* @__PURE__ */ jsxs13(Text15, { dimColor: true, children: [
14358
14973
  " ",
14359
14974
  "agentic_payments: ineligible",
14360
14975
  agenticCap.ineligibility_reasons?.length > 0 ? ` (${agenticCap.ineligibility_reasons.join(", ")})` : ""
@@ -14365,9 +14980,9 @@ var PaymentMethodsList = ({
14365
14980
  };
14366
14981
 
14367
14982
  // src/commands/payment-methods/index.tsx
14368
- import { jsx as jsx18 } from "react/jsx-runtime";
14983
+ import { jsx as jsx20 } from "react/jsx-runtime";
14369
14984
  function createPaymentMethodsCli(createResource, authStorage2, envAccessToken2) {
14370
- const cli2 = Cli5.create("payment-methods", {
14985
+ const cli2 = Cli6.create("payment-methods", {
14371
14986
  description: "Payment methods management commands"
14372
14987
  });
14373
14988
  cli2.command("list", {
@@ -14378,7 +14993,7 @@ function createPaymentMethodsCli(createResource, authStorage2, envAccessToken2)
14378
14993
  const resource = createResource();
14379
14994
  if (!c.agent && !c.formatExplicit) {
14380
14995
  return renderInteractive(
14381
- /* @__PURE__ */ jsx18(PaymentMethodsList, { resource, onComplete: () => {
14996
+ /* @__PURE__ */ jsx20(PaymentMethodsList, { resource, onComplete: () => {
14382
14997
  } }),
14383
14998
  () => resource.listPaymentMethods()
14384
14999
  );
@@ -14392,7 +15007,7 @@ function createPaymentMethodsCli(createResource, authStorage2, envAccessToken2)
14392
15007
  middleware: [requireAuth(authStorage2, envAccessToken2)],
14393
15008
  async run(c) {
14394
15009
  if (!c.agent && !c.formatExplicit) {
14395
- return renderInteractive(/* @__PURE__ */ jsx18(AddPaymentMethod, {}), () => ({
15010
+ return renderInteractive(/* @__PURE__ */ jsx20(AddPaymentMethod, {}), () => ({
14396
15011
  url: WALLET_URL
14397
15012
  }));
14398
15013
  }
@@ -14403,22 +15018,22 @@ function createPaymentMethodsCli(createResource, authStorage2, envAccessToken2)
14403
15018
  }
14404
15019
 
14405
15020
  // src/commands/report/index.tsx
14406
- import { Cli as Cli6 } from "incur";
15021
+ import { Cli as Cli7 } from "incur";
14407
15022
 
14408
15023
  // src/commands/report/schema.ts
14409
- import { z as z5 } from "incur";
14410
- var reportOptions = z5.object({
14411
- domain: z5.string().describe("Domain where the outcome occurred"),
14412
- outcome: z5.enum(REPORT_OUTCOMES).describe("What happened: success, blocked, or abandoned"),
14413
- spendRequestId: z5.string().describe("Spend request ID (lsrq_...)"),
14414
- tag: z5.array(z5.enum(REPORT_TAGS)).optional().describe("Outcome tags (repeatable)"),
14415
- step: z5.string().max(500).optional().describe("Where in the flow the agent was"),
14416
- freeformContext: z5.string().max(500).optional().describe("Additional context (max 500 chars)")
15024
+ import { z as z6 } from "incur";
15025
+ var reportOptions = z6.object({
15026
+ domain: z6.string().describe("Domain where the outcome occurred"),
15027
+ outcome: z6.enum(REPORT_OUTCOMES).describe("What happened: success, blocked, or abandoned"),
15028
+ spendRequestId: z6.string().describe("Spend request ID (lsrq_...)"),
15029
+ tag: z6.array(z6.enum(REPORT_TAGS)).optional().describe("Outcome tags (repeatable)"),
15030
+ step: z6.string().max(500).optional().describe("Where in the flow the agent was"),
15031
+ freeformContext: z6.string().max(500).optional().describe("Additional context (max 500 chars)")
14417
15032
  });
14418
15033
 
14419
15034
  // src/commands/report/index.tsx
14420
15035
  function createReportCli(createResource, authStorage2, envAccessToken2) {
14421
- const cli2 = Cli6.create("report", {
15036
+ const cli2 = Cli7.create("report", {
14422
15037
  description: "Report the outcome of an agent action on a domain. Call after every purchase attempt.",
14423
15038
  options: reportOptions,
14424
15039
  outputPolicy: "agent-only",
@@ -14443,7 +15058,7 @@ function createReportCli(createResource, authStorage2, envAccessToken2) {
14443
15058
  import {
14444
15059
  createServer
14445
15060
  } from "http";
14446
- import { Cli as Cli7, z as z6 } from "incur";
15061
+ import { Cli as Cli8, z as z7 } from "incur";
14447
15062
  async function nodeRequestToWebRequest(req, port) {
14448
15063
  const body = await new Promise((resolve) => {
14449
15064
  const chunks = [];
@@ -14469,10 +15084,10 @@ async function sendWebResponse(webRes, res) {
14469
15084
  res.end(Buffer.from(buffer));
14470
15085
  }
14471
15086
  function createServeCli(rootCli) {
14472
- return Cli7.create("serve", {
15087
+ return Cli8.create("serve", {
14473
15088
  description: "Start an HTTP server exposing link-cli as an MCP endpoint at /mcp",
14474
- options: z6.object({
14475
- port: z6.coerce.number().default(54321).describe("Port to listen on")
15089
+ options: z7.object({
15090
+ port: z7.coerce.number().default(54321).describe("Port to listen on")
14476
15091
  }),
14477
15092
  async run(c) {
14478
15093
  const { port } = c.options;
@@ -14517,13 +15132,13 @@ function createServeCli(rootCli) {
14517
15132
  }
14518
15133
 
14519
15134
  // src/commands/shipping-address/index.tsx
14520
- import { Cli as Cli8 } from "incur";
15135
+ import { Cli as Cli9 } from "incur";
14521
15136
 
14522
15137
  // src/commands/shipping-address/list.tsx
14523
- import { Box as Box13, Text as Text15 } from "ink";
14524
- import Spinner5 from "ink-spinner";
14525
- import { useCallback as useCallback4 } from "react";
14526
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
15138
+ import { Box as Box14, Text as Text16 } from "ink";
15139
+ import Spinner6 from "ink-spinner";
15140
+ import { useCallback as useCallback5 } from "react";
15141
+ import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
14527
15142
  function formatStreetLine(address) {
14528
15143
  const parts = [address.line_1, address.line_2].filter(Boolean);
14529
15144
  return parts.length > 0 ? parts.join(", ") : null;
@@ -14555,7 +15170,7 @@ var ShippingAddressList = ({
14555
15170
  resource,
14556
15171
  onComplete
14557
15172
  }) => {
14558
- const action = useCallback4(
15173
+ const action = useCallback5(
14559
15174
  () => resource.listShippingAddresses(),
14560
15175
  [resource]
14561
15176
  );
@@ -14565,40 +15180,40 @@ var ShippingAddressList = ({
14565
15180
  error
14566
15181
  } = useAsyncAction(action, onComplete);
14567
15182
  if (status === "loading") {
14568
- return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsxs13(Text15, { color: "cyan", children: [
14569
- /* @__PURE__ */ jsx19(Spinner5, { type: "dots" }),
15183
+ return /* @__PURE__ */ jsx21(Box14, { children: /* @__PURE__ */ jsxs14(Text16, { color: "cyan", children: [
15184
+ /* @__PURE__ */ jsx21(Spinner6, { type: "dots" }),
14570
15185
  " Loading shipping addresses..."
14571
15186
  ] }) });
14572
15187
  }
14573
15188
  if (status === "error") {
14574
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
14575
- /* @__PURE__ */ jsx19(Text15, { color: "red", children: "\u2717 Failed to load shipping addresses" }),
14576
- /* @__PURE__ */ jsx19(Text15, { color: "red", children: error })
15189
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
15190
+ /* @__PURE__ */ jsx21(Text16, { color: "red", children: "\u2717 Failed to load shipping addresses" }),
15191
+ /* @__PURE__ */ jsx21(Text16, { color: "red", children: error })
14577
15192
  ] });
14578
15193
  }
14579
15194
  if (!shippingAddresses || shippingAddresses.length === 0) {
14580
- return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: "No shipping addresses found" }) });
15195
+ return /* @__PURE__ */ jsx21(Box14, { children: /* @__PURE__ */ jsx21(Text16, { dimColor: true, children: "No shipping addresses found" }) });
14581
15196
  }
14582
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
14583
- /* @__PURE__ */ jsx19(Text15, { bold: true, children: "Shipping Addresses" }),
14584
- /* @__PURE__ */ jsx19(Box13, { flexDirection: "column", marginTop: 1, children: shippingAddresses.map((shippingAddress) => {
15197
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
15198
+ /* @__PURE__ */ jsx21(Text16, { bold: true, children: "Shipping Addresses" }),
15199
+ /* @__PURE__ */ jsx21(Box14, { flexDirection: "column", marginTop: 1, children: shippingAddresses.map((shippingAddress) => {
14585
15200
  const addressName = shippingAddress.address?.name;
14586
15201
  const nickname = shippingAddress.nickname ? ` (${shippingAddress.nickname})` : "";
14587
- return /* @__PURE__ */ jsxs13(
14588
- Box13,
15202
+ return /* @__PURE__ */ jsxs14(
15203
+ Box14,
14589
15204
  {
14590
15205
  flexDirection: "column",
14591
15206
  paddingX: 2,
14592
15207
  marginBottom: 1,
14593
15208
  children: [
14594
- /* @__PURE__ */ jsxs13(Text15, { children: [
14595
- /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: shippingAddress.id }),
15209
+ /* @__PURE__ */ jsxs14(Text16, { children: [
15210
+ /* @__PURE__ */ jsx21(Text16, { dimColor: true, children: shippingAddress.id }),
14596
15211
  nickname,
14597
- shippingAddress.is_default ? /* @__PURE__ */ jsx19(Text15, { color: "green", children: " (default)" }) : null
15212
+ shippingAddress.is_default ? /* @__PURE__ */ jsx21(Text16, { color: "green", children: " (default)" }) : null
14598
15213
  ] }),
14599
- /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginTop: 1, children: [
14600
- addressName ? /* @__PURE__ */ jsx19(Text15, { bold: true, children: addressName }) : null,
14601
- formatAddressLines(shippingAddress).map((line) => /* @__PURE__ */ jsx19(Text15, { children: line }, `${shippingAddress.id}:${line}`))
15214
+ /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginTop: 1, children: [
15215
+ addressName ? /* @__PURE__ */ jsx21(Text16, { bold: true, children: addressName }) : null,
15216
+ formatAddressLines(shippingAddress).map((line) => /* @__PURE__ */ jsx21(Text16, { children: line }, `${shippingAddress.id}:${line}`))
14602
15217
  ] })
14603
15218
  ]
14604
15219
  },
@@ -14609,9 +15224,9 @@ var ShippingAddressList = ({
14609
15224
  };
14610
15225
 
14611
15226
  // src/commands/shipping-address/index.tsx
14612
- import { jsx as jsx20 } from "react/jsx-runtime";
15227
+ import { jsx as jsx22 } from "react/jsx-runtime";
14613
15228
  function createShippingAddressCli(createResource, authStorage2, envAccessToken2) {
14614
- const cli2 = Cli8.create("shipping-address", {
15229
+ const cli2 = Cli9.create("shipping-address", {
14615
15230
  description: "Shipping address management commands"
14616
15231
  });
14617
15232
  cli2.command("list", {
@@ -14622,7 +15237,7 @@ function createShippingAddressCli(createResource, authStorage2, envAccessToken2)
14622
15237
  const resource = createResource();
14623
15238
  if (!c.agent && !c.formatExplicit) {
14624
15239
  return renderInteractive(
14625
- /* @__PURE__ */ jsx20(ShippingAddressList, { resource, onComplete: () => {
15240
+ /* @__PURE__ */ jsx22(ShippingAddressList, { resource, onComplete: () => {
14626
15241
  } }),
14627
15242
  () => resource.listShippingAddresses()
14628
15243
  );
@@ -14633,8 +15248,219 @@ function createShippingAddressCli(createResource, authStorage2, envAccessToken2)
14633
15248
  return cli2;
14634
15249
  }
14635
15250
 
15251
+ // src/commands/sources/index.tsx
15252
+ import { Cli as Cli10 } from "incur";
15253
+
15254
+ // src/commands/sources/list.tsx
15255
+ import { Box as Box15, Text as Text17 } from "ink";
15256
+ import Spinner7 from "ink-spinner";
15257
+ import { useCallback as useCallback6 } from "react";
15258
+ import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
15259
+ var COLUMN_GAP2 = " ";
15260
+ var HORIZONTAL_PADDING = 4;
15261
+ function truncateCell2(value, width) {
15262
+ if (value.length <= width) {
15263
+ return value;
15264
+ }
15265
+ if (width <= 3) {
15266
+ return value.slice(0, width);
15267
+ }
15268
+ return `${value.slice(0, width - 3)}...`;
15269
+ }
15270
+ function formatCell2(value, width) {
15271
+ return truncateCell2(value, width).padEnd(width);
15272
+ }
15273
+ function sourceId(source, index) {
15274
+ return typeof source.id === "string" && source.id.length > 0 ? source.id : `source-${index + 1}`;
15275
+ }
15276
+ function statusFromValue(value) {
15277
+ if (value && typeof value === "object" && !Array.isArray(value)) {
15278
+ const status = value.status;
15279
+ return typeof status === "string" ? status : null;
15280
+ }
15281
+ return null;
15282
+ }
15283
+ function formatCapabilities(source) {
15284
+ const capabilities = source.capabilities;
15285
+ if (!capabilities || typeof capabilities !== "object") {
15286
+ return "-";
15287
+ }
15288
+ const entries = Object.entries(capabilities).map(([capability, value]) => {
15289
+ const status = statusFromValue(value);
15290
+ return status ? `${capability}:${status}` : capability;
15291
+ }).sort();
15292
+ return entries.length > 0 ? entries.join(", ") : "-";
15293
+ }
15294
+ function formatExternalConnection(source) {
15295
+ const status = statusFromValue(source.external_connection);
15296
+ return status ?? "-";
15297
+ }
15298
+ function sourceRow(source, index) {
15299
+ const capabilities = formatCapabilities(source);
15300
+ const external = formatExternalConnection(source);
15301
+ return {
15302
+ key: sourceId(source, index),
15303
+ name: source.name ?? "Source",
15304
+ type: source.type ?? "-",
15305
+ id: sourceId(source, index),
15306
+ capabilities,
15307
+ external
15308
+ };
15309
+ }
15310
+ function tableColumns() {
15311
+ return [
15312
+ { label: "Name", value: (row) => row.name, minWidth: 14, maxWidth: 24 },
15313
+ { label: "Type", value: (row) => row.type, minWidth: 10, maxWidth: 14 },
15314
+ { label: "ID", value: (row) => row.id, minWidth: 16, maxWidth: 48 },
15315
+ {
15316
+ label: "Capabilities",
15317
+ value: (row) => row.capabilities,
15318
+ minWidth: 8,
15319
+ maxWidth: 48
15320
+ },
15321
+ {
15322
+ label: "External connection status",
15323
+ value: (row) => row.external,
15324
+ minWidth: 8,
15325
+ maxWidth: 36
15326
+ }
15327
+ ];
15328
+ }
15329
+ function distributeWidths(columns, availableWidth) {
15330
+ const gapWidth = COLUMN_GAP2.length * Math.max(0, columns.length - 1);
15331
+ const contentWidth2 = Math.max(columns.length, availableWidth - gapWidth);
15332
+ const widths = columns.map((column) => column.minWidth);
15333
+ let remaining = contentWidth2 - widths.reduce((total, width) => total + width, 0);
15334
+ while (remaining > 0) {
15335
+ let changed = false;
15336
+ for (let index = 0; index < columns.length && remaining > 0; index += 1) {
15337
+ if (widths[index] >= columns[index].maxWidth) {
15338
+ continue;
15339
+ }
15340
+ widths[index] += 1;
15341
+ remaining -= 1;
15342
+ changed = true;
15343
+ }
15344
+ if (!changed) {
15345
+ break;
15346
+ }
15347
+ }
15348
+ return widths;
15349
+ }
15350
+ function renderTableRows(rows, terminalWidth) {
15351
+ const columns = tableColumns();
15352
+ const availableWidth = contentWidth(terminalWidth);
15353
+ const widths = distributeWidths(columns, availableWidth);
15354
+ const headerRow = columns.map((column, index) => formatCell2(column.label, widths[index])).join(COLUMN_GAP2).slice(0, availableWidth);
15355
+ const separatorRow = "-".repeat(headerRow.length).slice(0, availableWidth);
15356
+ const bodyRows = rows.map(
15357
+ (row) => columns.map((column, index) => formatCell2(column.value(row), widths[index])).join(COLUMN_GAP2).slice(0, availableWidth)
15358
+ );
15359
+ return { headerRow, separatorRow, bodyRows };
15360
+ }
15361
+ function contentWidth(terminalWidth) {
15362
+ return Math.max(1, terminalWidth - HORIZONTAL_PADDING);
15363
+ }
15364
+ var SourcesList = ({
15365
+ resource,
15366
+ params,
15367
+ onComplete
15368
+ }) => {
15369
+ const action = useCallback6(
15370
+ () => resource.listSources(params),
15371
+ [resource, params]
15372
+ );
15373
+ const { status, data: page, error } = useAsyncAction(action, onComplete);
15374
+ const sources = page?.data ?? [];
15375
+ const nextCursor = page?.has_more && sources.length > 0 ? sources[sources.length - 1].id : null;
15376
+ const rows = sources.map(sourceRow);
15377
+ const terminalWidth = process.stdout.columns ?? 140;
15378
+ const { headerRow, separatorRow, bodyRows } = renderTableRows(
15379
+ rows,
15380
+ terminalWidth
15381
+ );
15382
+ if (status === "loading") {
15383
+ return /* @__PURE__ */ jsx23(Box15, { children: /* @__PURE__ */ jsxs15(Text17, { color: "cyan", children: [
15384
+ /* @__PURE__ */ jsx23(Spinner7, { type: "dots" }),
15385
+ " Loading sources..."
15386
+ ] }) });
15387
+ }
15388
+ if (status === "error") {
15389
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
15390
+ /* @__PURE__ */ jsx23(Text17, { color: "red", children: "Failed to load sources" }),
15391
+ /* @__PURE__ */ jsx23(Text17, { color: "red", children: error })
15392
+ ] });
15393
+ }
15394
+ if (sources.length === 0) {
15395
+ return /* @__PURE__ */ jsx23(Box15, { children: /* @__PURE__ */ jsx23(Text17, { dimColor: true, children: "No sources found" }) });
15396
+ }
15397
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
15398
+ /* @__PURE__ */ jsx23(Text17, { bold: true, children: "Sources" }),
15399
+ /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15400
+ /* @__PURE__ */ jsx23(Text17, { bold: true, children: headerRow }),
15401
+ /* @__PURE__ */ jsx23(Text17, { dimColor: true, children: separatorRow }),
15402
+ bodyRows.map((row, index) => /* @__PURE__ */ jsx23(Text17, { children: row }, rows[index].key))
15403
+ ] }),
15404
+ page?.has_more !== void 0 ? /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginTop: 1, children: [
15405
+ /* @__PURE__ */ jsxs15(Text17, { dimColor: true, children: [
15406
+ "has_more: ",
15407
+ String(page.has_more)
15408
+ ] }),
15409
+ typeof nextCursor === "string" && nextCursor.length > 0 ? /* @__PURE__ */ jsx23(Text17, { dimColor: true, children: `next page: --starting-after ${nextCursor}` }) : null
15410
+ ] }) : null
15411
+ ] });
15412
+ };
15413
+
15414
+ // src/commands/sources/schema.ts
15415
+ import { z as z8 } from "incur";
15416
+ var listOptions2 = z8.object({
15417
+ limit: z8.coerce.number().int().positive().max(100).optional().describe("Maximum number of sources to return (1-100)."),
15418
+ startingAfter: z8.string().optional().describe("Cursor: return sources after this source ID."),
15419
+ endingBefore: z8.string().optional().describe("Cursor: return sources before this source ID.")
15420
+ });
15421
+
15422
+ // src/commands/sources/index.tsx
15423
+ import { jsx as jsx24 } from "react/jsx-runtime";
15424
+ function createSourcesCli(createResource, authStorage2, envAccessToken2) {
15425
+ const cli2 = Cli10.create("sources", {
15426
+ description: "List sources from your Link wallet"
15427
+ });
15428
+ cli2.command("list", {
15429
+ description: "List sources from your Link wallet",
15430
+ options: listOptions2,
15431
+ outputPolicy: "agent-only",
15432
+ middleware: [requireAuth(authStorage2, envAccessToken2)],
15433
+ async run(c) {
15434
+ const opts = c.options;
15435
+ const resource = createResource();
15436
+ const params = {};
15437
+ if (opts.limit !== void 0) params.limit = opts.limit;
15438
+ if (opts.startingAfter !== void 0)
15439
+ params.starting_after = opts.startingAfter;
15440
+ if (opts.endingBefore !== void 0)
15441
+ params.ending_before = opts.endingBefore;
15442
+ if (!c.agent && !c.formatExplicit) {
15443
+ return renderInteractive(
15444
+ /* @__PURE__ */ jsx24(
15445
+ SourcesList,
15446
+ {
15447
+ resource,
15448
+ params,
15449
+ onComplete: () => {
15450
+ }
15451
+ }
15452
+ ),
15453
+ () => resource.listSources(params)
15454
+ );
15455
+ }
15456
+ return resource.listSources(params);
15457
+ }
15458
+ });
15459
+ return cli2;
15460
+ }
15461
+
14636
15462
  // src/commands/spend-request/index.tsx
14637
- import { Cli as Cli9, z as z9 } from "incur";
15463
+ import { Cli as Cli11, z as z11 } from "incur";
14638
15464
 
14639
15465
  // src/utils/credential-output.ts
14640
15466
  import { constants } from "fs";
@@ -14692,21 +15518,21 @@ async function writeCredentialFile(filePath, data, force) {
14692
15518
  }
14693
15519
 
14694
15520
  // src/utils/line-item-parser.ts
14695
- import { z as z7 } from "zod";
14696
- var LineItemSchema = z7.object({
14697
- name: z7.string(),
14698
- url: z7.string().optional(),
14699
- image_url: z7.string().optional(),
14700
- description: z7.string().optional(),
14701
- sku: z7.string().optional(),
14702
- quantity: z7.coerce.number().optional(),
14703
- unit_amount: z7.coerce.number().optional(),
14704
- product_url: z7.string().optional()
15521
+ import { z as z9 } from "zod";
15522
+ var LineItemSchema = z9.object({
15523
+ name: z9.string(),
15524
+ url: z9.string().optional(),
15525
+ image_url: z9.string().optional(),
15526
+ description: z9.string().optional(),
15527
+ sku: z9.string().optional(),
15528
+ quantity: z9.coerce.number().optional(),
15529
+ unit_amount: z9.coerce.number().optional(),
15530
+ product_url: z9.string().optional()
14705
15531
  }).strict();
14706
- var TotalSchema = z7.object({
14707
- type: z7.string(),
14708
- display_text: z7.string(),
14709
- amount: z7.coerce.number()
15532
+ var TotalSchema = z9.object({
15533
+ type: z9.string(),
15534
+ display_text: z9.string(),
15535
+ amount: z9.coerce.number()
14710
15536
  }).strict();
14711
15537
  function parseKvString(raw) {
14712
15538
  const result = {};
@@ -14736,7 +15562,7 @@ function parseLineItemFlag(raw) {
14736
15562
  try {
14737
15563
  return LineItemSchema.parse(obj);
14738
15564
  } catch (err) {
14739
- if (err instanceof z7.ZodError)
15565
+ if (err instanceof z9.ZodError)
14740
15566
  throw formatZodError(err, "Line item", LineItemSchema);
14741
15567
  throw err;
14742
15568
  }
@@ -14746,65 +15572,65 @@ function parseTotalFlag(raw) {
14746
15572
  try {
14747
15573
  return TotalSchema.parse(obj);
14748
15574
  } catch (err) {
14749
- if (err instanceof z7.ZodError)
15575
+ if (err instanceof z9.ZodError)
14750
15576
  throw formatZodError(err, "Total", TotalSchema);
14751
15577
  throw err;
14752
15578
  }
14753
15579
  }
14754
15580
 
14755
15581
  // src/commands/spend-request/cancel.tsx
14756
- import { Box as Box14, Text as Text16 } from "ink";
14757
- import Spinner6 from "ink-spinner";
14758
- import { useCallback as useCallback5 } from "react";
14759
- import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
15582
+ import { Box as Box16, Text as Text18 } from "ink";
15583
+ import Spinner8 from "ink-spinner";
15584
+ import { useCallback as useCallback7 } from "react";
15585
+ import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
14760
15586
  var CancelSpendRequest = ({
14761
15587
  repository,
14762
15588
  id,
14763
15589
  onComplete
14764
15590
  }) => {
14765
- const action = useCallback5(
15591
+ const action = useCallback7(
14766
15592
  () => repository.cancelSpendRequest(id),
14767
15593
  [repository, id]
14768
15594
  );
14769
15595
  const { status, data: request, error } = useAsyncAction(action, onComplete);
14770
15596
  if (status === "loading") {
14771
- return /* @__PURE__ */ jsx21(Box14, { children: /* @__PURE__ */ jsxs14(Text16, { color: "cyan", children: [
14772
- /* @__PURE__ */ jsx21(Spinner6, { type: "dots" }),
15597
+ return /* @__PURE__ */ jsx25(Box16, { children: /* @__PURE__ */ jsxs16(Text18, { color: "cyan", children: [
15598
+ /* @__PURE__ */ jsx25(Spinner8, { type: "dots" }),
14773
15599
  " Canceling spend request ",
14774
15600
  id,
14775
15601
  "..."
14776
15602
  ] }) });
14777
15603
  }
14778
15604
  if (status === "error") {
14779
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
14780
- /* @__PURE__ */ jsx21(Text16, { color: "red", children: "\u2717 Failed to cancel spend request" }),
14781
- /* @__PURE__ */ jsx21(Text16, { color: "red", children: error })
15605
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
15606
+ /* @__PURE__ */ jsx25(Text18, { color: "red", children: "\u2717 Failed to cancel spend request" }),
15607
+ /* @__PURE__ */ jsx25(Text18, { color: "red", children: error })
14782
15608
  ] });
14783
15609
  }
14784
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
14785
- /* @__PURE__ */ jsx21(Text16, { color: "green", children: "\u2713 Spend request canceled" }),
14786
- /* @__PURE__ */ jsx21(Box14, { flexDirection: "column", marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs14(Text16, { children: [
15610
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
15611
+ /* @__PURE__ */ jsx25(Text18, { color: "green", children: "\u2713 Spend request canceled" }),
15612
+ /* @__PURE__ */ jsx25(Box16, { flexDirection: "column", marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs16(Text18, { children: [
14787
15613
  "ID: ",
14788
- /* @__PURE__ */ jsx21(Text16, { bold: true, children: request?.id })
15614
+ /* @__PURE__ */ jsx25(Text18, { bold: true, children: request?.id })
14789
15615
  ] }) })
14790
15616
  ] });
14791
15617
  };
14792
15618
 
14793
15619
  // src/commands/spend-request/create.tsx
14794
- import { Box as Box16, Text as Text18 } from "ink";
14795
- import Spinner8 from "ink-spinner";
14796
- import { useCallback as useCallback6, useEffect as useEffect9, useState as useState9 } from "react";
15620
+ import { Box as Box18, Text as Text20, useApp as useApp4 } from "ink";
15621
+ import Spinner10 from "ink-spinner";
15622
+ import { useCallback as useCallback8, useEffect as useEffect9, useState as useState9 } from "react";
14797
15623
 
14798
15624
  // src/commands/spend-request/approval-waiting-view.tsx
14799
- import { Box as Box15, Text as Text17 } from "ink";
14800
- import Spinner7 from "ink-spinner";
14801
- import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
15625
+ import { Box as Box17, Text as Text19 } from "ink";
15626
+ import Spinner9 from "ink-spinner";
15627
+ import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
14802
15628
  var ApprovalWaitingView = ({
14803
15629
  status,
14804
15630
  approvalUrl
14805
- }) => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", paddingY: 1, children: [
14806
- /* @__PURE__ */ jsxs15(
14807
- Box15,
15631
+ }) => /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", paddingY: 1, children: [
15632
+ /* @__PURE__ */ jsxs17(
15633
+ Box17,
14808
15634
  {
14809
15635
  flexDirection: "column",
14810
15636
  borderStyle: "round",
@@ -14812,20 +15638,20 @@ var ApprovalWaitingView = ({
14812
15638
  paddingX: 2,
14813
15639
  paddingY: 1,
14814
15640
  children: [
14815
- /* @__PURE__ */ jsxs15(Text17, { children: [
15641
+ /* @__PURE__ */ jsxs17(Text19, { children: [
14816
15642
  "Approve at:",
14817
15643
  " ",
14818
- /* @__PURE__ */ jsx22(Text17, { bold: true, color: "cyan", children: approvalUrl })
15644
+ /* @__PURE__ */ jsx26(Text19, { bold: true, color: "cyan", children: approvalUrl })
14819
15645
  ] }),
14820
- /* @__PURE__ */ jsx22(Text17, { dimColor: true, children: "Press Enter to open in browser" })
15646
+ /* @__PURE__ */ jsx26(Text19, { dimColor: true, children: "Press Enter to open in browser" })
14821
15647
  ]
14822
15648
  }
14823
15649
  ),
14824
- /* @__PURE__ */ jsx22(AppDownloadQrCodes, {}),
14825
- /* @__PURE__ */ jsx22(Box15, { marginTop: 1, children: status === "polling" ? /* @__PURE__ */ jsxs15(Text17, { color: "cyan", children: [
14826
- /* @__PURE__ */ jsx22(Spinner7, { type: "dots" }),
15650
+ /* @__PURE__ */ jsx26(AppDownloadQrCodes, {}),
15651
+ /* @__PURE__ */ jsx26(Box17, { marginTop: 1, children: status === "polling" ? /* @__PURE__ */ jsxs17(Text19, { color: "cyan", children: [
15652
+ /* @__PURE__ */ jsx26(Spinner9, { type: "dots" }),
14827
15653
  " Waiting for approval..."
14828
- ] }) : /* @__PURE__ */ jsx22(Text17, { dimColor: true, children: "Waiting..." }) })
15654
+ ] }) : /* @__PURE__ */ jsx26(Text19, { dimColor: true, children: "Waiting..." }) })
14829
15655
  ] });
14830
15656
 
14831
15657
  // src/commands/spend-request/use-approval-polling.ts
@@ -14894,7 +15720,7 @@ function useApprovalPolling({
14894
15720
  }
14895
15721
 
14896
15722
  // src/commands/spend-request/create.tsx
14897
- import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
15723
+ import { Fragment as Fragment4, jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
14898
15724
  var CreateSpendRequest = ({
14899
15725
  repository,
14900
15726
  params,
@@ -14906,21 +15732,30 @@ var CreateSpendRequest = ({
14906
15732
  const [status, setStatus] = useState9("creating");
14907
15733
  const [request, setRequest] = useState9(null);
14908
15734
  const [error, setError] = useState9("");
15735
+ const [verificationUrl, setVerificationUrl] = useState9("");
14909
15736
  const [outputFilePath, setOutputFilePath] = useState9(null);
14910
15737
  const [fileError, setFileError] = useState9("");
14911
15738
  const approvalUrl = request?.approval_url ?? "";
14912
- const onSuccess = useCallback6(
15739
+ const { exit } = useApp4();
15740
+ const completeAndExit = useCallback8(
15741
+ (result) => {
15742
+ onComplete(result);
15743
+ exit();
15744
+ },
15745
+ [onComplete, exit]
15746
+ );
15747
+ const onSuccess = useCallback8(
14913
15748
  (result) => setRequest(result),
14914
15749
  []
14915
15750
  );
14916
- const onError = useCallback6((msg) => setError(msg), []);
15751
+ const onError = useCallback8((msg) => setError(msg), []);
14917
15752
  useApprovalPolling({
14918
15753
  status,
14919
15754
  setStatus,
14920
15755
  approvalUrl,
14921
15756
  repository,
14922
15757
  requestId: request?.id ?? null,
14923
- onComplete,
15758
+ onComplete: completeAndExit,
14924
15759
  onSuccess,
14925
15760
  onError
14926
15761
  });
@@ -14933,16 +15768,20 @@ var CreateSpendRequest = ({
14933
15768
  setStatus("waiting");
14934
15769
  } else {
14935
15770
  setStatus("success");
14936
- setTimeout(() => onComplete(result), DISPLAY_DELAY_MS);
15771
+ setTimeout(() => completeAndExit(result), DISPLAY_DELAY_MS);
14937
15772
  }
14938
15773
  } catch (err) {
14939
15774
  setError(err.message);
15775
+ if (err instanceof LinkApiError) {
15776
+ const url = err.details?.error?.verification_url;
15777
+ if (url) setVerificationUrl(url);
15778
+ }
14940
15779
  setStatus("error");
14941
- setTimeout(() => onComplete(null), DISPLAY_DELAY_MS);
15780
+ setTimeout(() => completeAndExit(null), DISPLAY_DELAY_MS);
14942
15781
  }
14943
15782
  };
14944
15783
  create();
14945
- }, [repository, params, requestApproval, onComplete]);
15784
+ }, [repository, params, requestApproval, completeAndExit]);
14946
15785
  useEffect9(() => {
14947
15786
  if (status !== "success" || !outputFile || !request?.card) return;
14948
15787
  const fileData = {
@@ -14956,101 +15795,105 @@ var CreateSpendRequest = ({
14956
15795
  writeCredentialFile(outputFile, fileData, force ?? false).then((path7) => setOutputFilePath(path7)).catch((err) => setFileError(err.message));
14957
15796
  }, [status, outputFile, force, request]);
14958
15797
  if (status === "creating") {
14959
- return /* @__PURE__ */ jsx23(Box16, { children: /* @__PURE__ */ jsxs16(Text18, { color: "cyan", children: [
14960
- /* @__PURE__ */ jsx23(Spinner8, { type: "dots" }),
15798
+ return /* @__PURE__ */ jsx27(Box18, { children: /* @__PURE__ */ jsxs18(Text20, { color: "cyan", children: [
15799
+ /* @__PURE__ */ jsx27(Spinner10, { type: "dots" }),
14961
15800
  " Creating spend request..."
14962
15801
  ] }) });
14963
15802
  }
14964
15803
  if (status === "error") {
14965
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
14966
- /* @__PURE__ */ jsx23(Text18, { color: "red", children: "\u2717 Failed to create spend request" }),
14967
- /* @__PURE__ */ jsx23(Text18, { color: "red", children: error })
15804
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
15805
+ /* @__PURE__ */ jsx27(Text20, { color: "red", children: "\u2717 Failed to create spend request" }),
15806
+ /* @__PURE__ */ jsx27(Text20, { color: "red", children: error }),
15807
+ verificationUrl && /* @__PURE__ */ jsxs18(Text20, { color: "red", children: [
15808
+ "Complete additional verification at: ",
15809
+ verificationUrl
15810
+ ] })
14968
15811
  ] });
14969
15812
  }
14970
15813
  if (status === "success") {
14971
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
14972
- /* @__PURE__ */ jsx23(Text18, { color: "green", children: "\u2713 Spend request created" }),
14973
- /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
14974
- /* @__PURE__ */ jsxs16(Text18, { children: [
15814
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
15815
+ /* @__PURE__ */ jsx27(Text20, { color: "green", children: "\u2713 Spend request created" }),
15816
+ /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15817
+ /* @__PURE__ */ jsxs18(Text20, { children: [
14975
15818
  "ID: ",
14976
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.id })
15819
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.id })
14977
15820
  ] }),
14978
- /* @__PURE__ */ jsxs16(Text18, { children: [
15821
+ /* @__PURE__ */ jsxs18(Text20, { children: [
14979
15822
  "Status: ",
14980
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.status })
15823
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.status })
14981
15824
  ] }),
14982
- /* @__PURE__ */ jsxs16(Text18, { children: [
15825
+ /* @__PURE__ */ jsxs18(Text20, { children: [
14983
15826
  "Amount:",
14984
15827
  " ",
14985
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.amount != null ? `${request.amount} ${request.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
15828
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.amount != null ? `${request.amount} ${request.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
14986
15829
  ] }),
14987
- /* @__PURE__ */ jsxs16(Text18, { children: [
15830
+ /* @__PURE__ */ jsxs18(Text20, { children: [
14988
15831
  "Merchant: ",
14989
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.merchant_name })
15832
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.merchant_name })
14990
15833
  ] }),
14991
- /* @__PURE__ */ jsxs16(Text18, { children: [
15834
+ /* @__PURE__ */ jsxs18(Text20, { children: [
14992
15835
  "Line Items:",
14993
15836
  " ",
14994
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") || "N/A" })
15837
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") || "N/A" })
14995
15838
  ] }),
14996
- request?.credential_type === "shared_payment_token" && request.shared_payment_token && /* @__PURE__ */ jsxs16(Text18, { children: [
15839
+ request?.credential_type === "shared_payment_token" && request.shared_payment_token && /* @__PURE__ */ jsxs18(Text20, { children: [
14997
15840
  "Token: ",
14998
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.shared_payment_token.id })
15841
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.shared_payment_token.id })
14999
15842
  ] })
15000
15843
  ] }),
15001
- request?.card && !outputFile && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, children: [
15002
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: "Card Details:" }),
15003
- /* @__PURE__ */ jsxs16(Text18, { children: [
15844
+ request?.card && !outputFile && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, children: [
15845
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: "Card Details:" }),
15846
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15004
15847
  " ",
15005
15848
  "Number: ",
15006
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.card.number })
15849
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.card.number })
15007
15850
  ] }),
15008
- /* @__PURE__ */ jsxs16(Text18, { children: [
15851
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15009
15852
  " ",
15010
15853
  "Brand: ",
15011
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.card.brand })
15854
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.card.brand })
15012
15855
  ] }),
15013
- /* @__PURE__ */ jsxs16(Text18, { children: [
15856
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15014
15857
  " ",
15015
15858
  "Expiry:",
15016
15859
  " ",
15017
- /* @__PURE__ */ jsxs16(Text18, { bold: true, children: [
15860
+ /* @__PURE__ */ jsxs18(Text20, { bold: true, children: [
15018
15861
  String(request.card.exp_month).padStart(2, "0"),
15019
15862
  "/",
15020
15863
  request.card.exp_year
15021
15864
  ] })
15022
15865
  ] }),
15023
- request.card.cvc && /* @__PURE__ */ jsxs16(Text18, { children: [
15866
+ request.card.cvc && /* @__PURE__ */ jsxs18(Text20, { children: [
15024
15867
  " ",
15025
15868
  "CVC: ",
15026
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.card.cvc })
15869
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.card.cvc })
15027
15870
  ] }),
15028
- request.card.valid_until && /* @__PURE__ */ jsxs16(Text18, { children: [
15871
+ request.card.valid_until && /* @__PURE__ */ jsxs18(Text20, { children: [
15029
15872
  " ",
15030
15873
  "Valid Until: ",
15031
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.card.valid_until })
15874
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.card.valid_until })
15032
15875
  ] })
15033
15876
  ] }),
15034
- request?.card && outputFile && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, children: [
15035
- outputFilePath && /* @__PURE__ */ jsxs16(Text18, { color: "green", children: [
15877
+ request?.card && outputFile && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, children: [
15878
+ outputFilePath && /* @__PURE__ */ jsxs18(Text20, { color: "green", children: [
15036
15879
  "Card credentials written to ",
15037
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: outputFilePath })
15880
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: outputFilePath })
15038
15881
  ] }),
15039
- fileError && /* @__PURE__ */ jsxs16(Text18, { color: "red", children: [
15882
+ fileError && /* @__PURE__ */ jsxs18(Text20, { color: "red", children: [
15040
15883
  "Failed to write card file: ",
15041
15884
  fileError
15042
15885
  ] })
15043
15886
  ] }),
15044
- /* @__PURE__ */ jsx23(AppDownloadQrCodes, {})
15887
+ /* @__PURE__ */ jsx27(AppDownloadQrCodes, {})
15045
15888
  ] });
15046
15889
  }
15047
- return /* @__PURE__ */ jsxs16(Fragment4, { children: [
15048
- /* @__PURE__ */ jsx23(Box16, { children: /* @__PURE__ */ jsxs16(Text18, { color: "green", children: [
15890
+ return /* @__PURE__ */ jsxs18(Fragment4, { children: [
15891
+ /* @__PURE__ */ jsx27(Box18, { children: /* @__PURE__ */ jsxs18(Text20, { color: "green", children: [
15049
15892
  "\u2713 Spend request created (ID: ",
15050
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.id }),
15893
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.id }),
15051
15894
  ")"
15052
15895
  ] }) }),
15053
- /* @__PURE__ */ jsx23(
15896
+ /* @__PURE__ */ jsx27(
15054
15897
  ApprovalWaitingView,
15055
15898
  {
15056
15899
  status,
@@ -15061,21 +15904,21 @@ var CreateSpendRequest = ({
15061
15904
  };
15062
15905
 
15063
15906
  // src/commands/spend-request/list.tsx
15064
- import { Box as Box17, Text as Text19, useApp as useApp4 } from "ink";
15065
- import Spinner9 from "ink-spinner";
15066
- import { useCallback as useCallback7 } from "react";
15067
- import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
15907
+ import { Box as Box19, Text as Text21, useApp as useApp5 } from "ink";
15908
+ import Spinner11 from "ink-spinner";
15909
+ import { useCallback as useCallback9 } from "react";
15910
+ import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
15068
15911
  var SpendRequestList = ({
15069
15912
  repository,
15070
15913
  includeHistory = false,
15071
15914
  onComplete
15072
15915
  }) => {
15073
- const { exit } = useApp4();
15074
- const action = useCallback7(
15916
+ const { exit } = useApp5();
15917
+ const action = useCallback9(
15075
15918
  () => repository.listSpendRequests({ includeHistory }),
15076
15919
  [repository, includeHistory]
15077
15920
  );
15078
- const wrappedOnComplete = useCallback7(
15921
+ const wrappedOnComplete = useCallback9(
15079
15922
  (result) => {
15080
15923
  onComplete(result);
15081
15924
  exit();
@@ -15088,29 +15931,29 @@ var SpendRequestList = ({
15088
15931
  error
15089
15932
  } = useAsyncAction(action, wrappedOnComplete);
15090
15933
  if (status === "loading") {
15091
- return /* @__PURE__ */ jsx24(Box17, { children: /* @__PURE__ */ jsxs17(Text19, { color: "cyan", children: [
15092
- /* @__PURE__ */ jsx24(Spinner9, { type: "dots" }),
15934
+ return /* @__PURE__ */ jsx28(Box19, { children: /* @__PURE__ */ jsxs19(Text21, { color: "cyan", children: [
15935
+ /* @__PURE__ */ jsx28(Spinner11, { type: "dots" }),
15093
15936
  " Loading spend requests..."
15094
15937
  ] }) });
15095
15938
  }
15096
15939
  if (status === "error") {
15097
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
15098
- /* @__PURE__ */ jsx24(Text19, { color: "red", children: "\u2717 Failed to load spend requests" }),
15099
- /* @__PURE__ */ jsx24(Text19, { color: "red", children: error })
15940
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15941
+ /* @__PURE__ */ jsx28(Text21, { color: "red", children: "\u2717 Failed to load spend requests" }),
15942
+ /* @__PURE__ */ jsx28(Text21, { color: "red", children: error })
15100
15943
  ] });
15101
15944
  }
15102
15945
  if (!requests || requests.length === 0) {
15103
- return /* @__PURE__ */ jsx24(Box17, { children: /* @__PURE__ */ jsx24(Text19, { dimColor: true, children: includeHistory ? "No spend requests found" : "No active spend requests found" }) });
15946
+ return /* @__PURE__ */ jsx28(Box19, { children: /* @__PURE__ */ jsx28(Text21, { dimColor: true, children: includeHistory ? "No spend requests found" : "No active spend requests found" }) });
15104
15947
  }
15105
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
15106
- /* @__PURE__ */ jsx24(Text19, { bold: true, children: includeHistory ? "All Spend Requests" : "Active Spend Requests" }),
15107
- /* @__PURE__ */ jsx24(Box17, { flexDirection: "column", marginTop: 1, children: requests.map((sr) => {
15948
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15949
+ /* @__PURE__ */ jsx28(Text21, { bold: true, children: includeHistory ? "All Spend Requests" : "Active Spend Requests" }),
15950
+ /* @__PURE__ */ jsx28(Box19, { flexDirection: "column", marginTop: 1, children: requests.map((sr) => {
15108
15951
  const statusColor = sr.status === "approved" ? "green" : sr.status === "pending_approval" ? "yellow" : "white";
15109
15952
  const amount = sr.amount != null ? `$${(sr.amount / 100).toFixed(2)} ${(sr.currency ?? "usd").toUpperCase()}` : "";
15110
- return /* @__PURE__ */ jsx24(Box17, { paddingX: 2, children: /* @__PURE__ */ jsxs17(Text19, { children: [
15111
- /* @__PURE__ */ jsx24(Text19, { dimColor: true, children: sr.id }),
15953
+ return /* @__PURE__ */ jsx28(Box19, { paddingX: 2, children: /* @__PURE__ */ jsxs19(Text21, { children: [
15954
+ /* @__PURE__ */ jsx28(Text21, { dimColor: true, children: sr.id }),
15112
15955
  " ",
15113
- /* @__PURE__ */ jsx24(Text19, { color: statusColor, children: sr.status }),
15956
+ /* @__PURE__ */ jsx28(Text21, { color: statusColor, children: sr.status }),
15114
15957
  sr.merchant_name ? ` ${sr.merchant_name}` : "",
15115
15958
  amount ? ` ${amount}` : ""
15116
15959
  ] }) }, sr.id);
@@ -15119,10 +15962,10 @@ var SpendRequestList = ({
15119
15962
  };
15120
15963
 
15121
15964
  // src/commands/spend-request/request-approval.tsx
15122
- import { Box as Box18, Text as Text20 } from "ink";
15123
- import Spinner10 from "ink-spinner";
15124
- import { useCallback as useCallback8, useEffect as useEffect10, useState as useState10 } from "react";
15125
- import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
15965
+ import { Box as Box20, Text as Text22, useApp as useApp6 } from "ink";
15966
+ import Spinner12 from "ink-spinner";
15967
+ import { useCallback as useCallback10, useEffect as useEffect10, useState as useState10 } from "react";
15968
+ import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
15126
15969
  var RequestApproval = ({
15127
15970
  repository,
15128
15971
  id,
@@ -15132,15 +15975,24 @@ var RequestApproval = ({
15132
15975
  const [approvalUrl, setApprovalUrl] = useState10("");
15133
15976
  const [result, setResult] = useState10(null);
15134
15977
  const [error, setError] = useState10("");
15135
- const onSuccess = useCallback8((r) => setResult(r), []);
15136
- const onError = useCallback8((msg) => setError(msg), []);
15978
+ const [verificationUrl, setVerificationUrl] = useState10("");
15979
+ const { exit } = useApp6();
15980
+ const completeAndExit = useCallback10(
15981
+ (result2) => {
15982
+ onComplete(result2);
15983
+ exit();
15984
+ },
15985
+ [onComplete, exit]
15986
+ );
15987
+ const onSuccess = useCallback10((r) => setResult(r), []);
15988
+ const onError = useCallback10((msg) => setError(msg), []);
15137
15989
  useApprovalPolling({
15138
15990
  status,
15139
15991
  setStatus,
15140
15992
  approvalUrl,
15141
15993
  repository,
15142
15994
  requestId: id,
15143
- onComplete,
15995
+ onComplete: completeAndExit,
15144
15996
  onSuccess,
15145
15997
  onError
15146
15998
  });
@@ -15152,52 +16004,64 @@ var RequestApproval = ({
15152
16004
  setStatus("waiting");
15153
16005
  } catch (err) {
15154
16006
  setError(err.message);
16007
+ if (err instanceof LinkApiError) {
16008
+ const url = err.details?.error?.verification_url;
16009
+ if (url) setVerificationUrl(url);
16010
+ }
15155
16011
  setStatus("error");
16012
+ setTimeout(() => {
16013
+ onComplete(null);
16014
+ exit();
16015
+ }, DISPLAY_DELAY_MS);
15156
16016
  }
15157
16017
  };
15158
16018
  request();
15159
- }, [repository, id]);
16019
+ }, [repository, id, exit, onComplete]);
15160
16020
  if (status === "requesting") {
15161
- return /* @__PURE__ */ jsx25(Box18, { children: /* @__PURE__ */ jsxs18(Text20, { color: "cyan", children: [
15162
- /* @__PURE__ */ jsx25(Spinner10, { type: "dots" }),
16021
+ return /* @__PURE__ */ jsx29(Box20, { children: /* @__PURE__ */ jsxs20(Text22, { color: "cyan", children: [
16022
+ /* @__PURE__ */ jsx29(Spinner12, { type: "dots" }),
15163
16023
  " Requesting approval..."
15164
16024
  ] }) });
15165
16025
  }
15166
16026
  if (status === "error") {
15167
- return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
15168
- /* @__PURE__ */ jsx25(Text20, { color: "red", children: "\u2717 Failed to request approval" }),
15169
- /* @__PURE__ */ jsx25(Text20, { color: "red", children: error })
16027
+ return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
16028
+ /* @__PURE__ */ jsx29(Text22, { color: "red", children: "\u2717 Failed to request approval" }),
16029
+ /* @__PURE__ */ jsx29(Text22, { color: "red", children: error }),
16030
+ verificationUrl && /* @__PURE__ */ jsxs20(Text22, { color: "red", children: [
16031
+ "Complete additional verification at: ",
16032
+ verificationUrl
16033
+ ] })
15170
16034
  ] });
15171
16035
  }
15172
16036
  if (status === "success") {
15173
- return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
15174
- /* @__PURE__ */ jsx25(Text20, { color: "green", children: "\u2713 Approval completed" }),
15175
- /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15176
- /* @__PURE__ */ jsxs18(Text20, { children: [
16037
+ return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
16038
+ /* @__PURE__ */ jsx29(Text22, { color: "green", children: "\u2713 Approval completed" }),
16039
+ /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16040
+ /* @__PURE__ */ jsxs20(Text22, { children: [
15177
16041
  "ID: ",
15178
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result?.id })
16042
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result?.id })
15179
16043
  ] }),
15180
- /* @__PURE__ */ jsxs18(Text20, { children: [
16044
+ /* @__PURE__ */ jsxs20(Text22, { children: [
15181
16045
  "Status: ",
15182
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result?.status })
16046
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result?.status })
15183
16047
  ] }),
15184
- /* @__PURE__ */ jsxs18(Text20, { children: [
16048
+ /* @__PURE__ */ jsxs20(Text22, { children: [
15185
16049
  "Amount:",
15186
16050
  " ",
15187
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result?.amount != null ? `${result.amount} ${result.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
16051
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result?.amount != null ? `${result.amount} ${result.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
15188
16052
  ] }),
15189
- /* @__PURE__ */ jsxs18(Text20, { children: [
16053
+ /* @__PURE__ */ jsxs20(Text22, { children: [
15190
16054
  "Merchant: ",
15191
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result?.merchant_name })
16055
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result?.merchant_name })
15192
16056
  ] }),
15193
- result?.credential_type === "shared_payment_token" && result.shared_payment_token && /* @__PURE__ */ jsxs18(Text20, { children: [
16057
+ result?.credential_type === "shared_payment_token" && result.shared_payment_token && /* @__PURE__ */ jsxs20(Text22, { children: [
15194
16058
  "Token: ",
15195
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result.shared_payment_token.id })
16059
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result.shared_payment_token.id })
15196
16060
  ] })
15197
16061
  ] })
15198
16062
  ] });
15199
16063
  }
15200
- return /* @__PURE__ */ jsx25(
16064
+ return /* @__PURE__ */ jsx29(
15201
16065
  ApprovalWaitingView,
15202
16066
  {
15203
16067
  status,
@@ -15207,10 +16071,10 @@ var RequestApproval = ({
15207
16071
  };
15208
16072
 
15209
16073
  // src/commands/spend-request/retrieve.tsx
15210
- import { Box as Box19, Text as Text21 } from "ink";
15211
- import Spinner11 from "ink-spinner";
16074
+ import { Box as Box21, Text as Text23 } from "ink";
16075
+ import Spinner13 from "ink-spinner";
15212
16076
  import { useEffect as useEffect11, useRef as useRef5, useState as useState11 } from "react";
15213
- import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
16077
+ import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
15214
16078
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
15215
16079
  "approved",
15216
16080
  "denied",
@@ -15334,121 +16198,121 @@ var RetrieveSpendRequest = ({
15334
16198
  };
15335
16199
  }, [phase, repository, id, include, timeout, onComplete]);
15336
16200
  if (phase === "fetching") {
15337
- return /* @__PURE__ */ jsx26(Box19, { children: /* @__PURE__ */ jsxs19(Text21, { color: "cyan", children: [
15338
- /* @__PURE__ */ jsx26(Spinner11, { type: "dots" }),
16201
+ return /* @__PURE__ */ jsx30(Box21, { children: /* @__PURE__ */ jsxs21(Text23, { color: "cyan", children: [
16202
+ /* @__PURE__ */ jsx30(Spinner13, { type: "dots" }),
15339
16203
  " Retrieving spend request ",
15340
16204
  id,
15341
16205
  "..."
15342
16206
  ] }) });
15343
16207
  }
15344
16208
  if (phase === "error") {
15345
- return /* @__PURE__ */ jsx26(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsxs19(Text21, { color: "red", children: [
16209
+ return /* @__PURE__ */ jsx30(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsxs21(Text23, { color: "red", children: [
15346
16210
  "\u2717 ",
15347
16211
  error
15348
16212
  ] }) });
15349
16213
  }
15350
16214
  if (phase === "timeout") {
15351
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15352
- /* @__PURE__ */ jsxs19(Text21, { color: "yellow", children: [
16215
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16216
+ /* @__PURE__ */ jsxs21(Text23, { color: "yellow", children: [
15353
16217
  "\u2717 Timed out waiting for approval after ",
15354
16218
  timeout,
15355
16219
  "s"
15356
16220
  ] }),
15357
- request && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15358
- /* @__PURE__ */ jsxs19(Text21, { children: [
16221
+ request && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16222
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15359
16223
  "ID: ",
15360
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.id })
16224
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.id })
15361
16225
  ] }),
15362
- /* @__PURE__ */ jsxs19(Text21, { children: [
16226
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15363
16227
  "Status: ",
15364
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.status })
16228
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.status })
15365
16229
  ] })
15366
16230
  ] })
15367
16231
  ] });
15368
16232
  }
15369
16233
  if (phase === "polling") {
15370
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15371
- /* @__PURE__ */ jsx26(Box19, { children: /* @__PURE__ */ jsxs19(Text21, { color: "cyan", children: [
15372
- /* @__PURE__ */ jsx26(Spinner11, { type: "dots" }),
16234
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16235
+ /* @__PURE__ */ jsx30(Box21, { children: /* @__PURE__ */ jsxs21(Text23, { color: "cyan", children: [
16236
+ /* @__PURE__ */ jsx30(Spinner13, { type: "dots" }),
15373
16237
  " Awaiting approval... (",
15374
16238
  elapsed,
15375
16239
  "s elapsed)"
15376
16240
  ] }) }),
15377
- request?.approval_url && /* @__PURE__ */ jsx26(Box19, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs19(Text21, { dimColor: true, children: [
16241
+ request?.approval_url && /* @__PURE__ */ jsx30(Box21, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs21(Text23, { dimColor: true, children: [
15378
16242
  "Approval URL: ",
15379
- /* @__PURE__ */ jsx26(Text21, { color: "cyan", children: request.approval_url })
16243
+ /* @__PURE__ */ jsx30(Text23, { color: "cyan", children: request.approval_url })
15380
16244
  ] }) })
15381
16245
  ] });
15382
16246
  }
15383
16247
  if (phase === "finalized") {
15384
16248
  const psd = request?.payment_status_details;
15385
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15386
- /* @__PURE__ */ jsxs19(Text21, { color: "yellow", children: [
16249
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16250
+ /* @__PURE__ */ jsxs21(Text23, { color: "yellow", children: [
15387
16251
  "Spend request reached terminal status: ",
15388
16252
  request?.status
15389
16253
  ] }),
15390
- /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15391
- /* @__PURE__ */ jsxs19(Text21, { children: [
16254
+ /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16255
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15392
16256
  "ID: ",
15393
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.id })
16257
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.id })
15394
16258
  ] }),
15395
- /* @__PURE__ */ jsxs19(Text21, { children: [
16259
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15396
16260
  "Status: ",
15397
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.status })
16261
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.status })
15398
16262
  ] }),
15399
- psd && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15400
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: "Payment Details:" }),
15401
- /* @__PURE__ */ jsxs19(Text21, { children: [
16263
+ psd && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16264
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: "Payment Details:" }),
16265
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15402
16266
  " ",
15403
16267
  "Outcome:",
15404
16268
  " ",
15405
- /* @__PURE__ */ jsx26(Text21, { bold: true, color: psd.outcome === "success" ? "green" : "red", children: psd.outcome })
16269
+ /* @__PURE__ */ jsx30(Text23, { bold: true, color: psd.outcome === "success" ? "green" : "red", children: psd.outcome })
15406
16270
  ] }),
15407
- psd.code && /* @__PURE__ */ jsxs19(Text21, { children: [
16271
+ psd.code && /* @__PURE__ */ jsxs21(Text23, { children: [
15408
16272
  " ",
15409
16273
  "Code: ",
15410
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: psd.code })
16274
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: psd.code })
15411
16275
  ] }),
15412
- psd.decline_code && /* @__PURE__ */ jsxs19(Text21, { children: [
16276
+ psd.decline_code && /* @__PURE__ */ jsxs21(Text23, { children: [
15413
16277
  " ",
15414
16278
  "Decline Reason: ",
15415
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: psd.decline_code })
16279
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: psd.decline_code })
15416
16280
  ] }),
15417
- /* @__PURE__ */ jsxs19(Text21, { children: [
16281
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15418
16282
  " ",
15419
16283
  "Amount:",
15420
16284
  " ",
15421
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16285
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15422
16286
  psd.amount,
15423
16287
  " ",
15424
16288
  psd.currency
15425
16289
  ] })
15426
16290
  ] }),
15427
- psd.created && /* @__PURE__ */ jsxs19(Text21, { children: [
16291
+ psd.created && /* @__PURE__ */ jsxs21(Text23, { children: [
15428
16292
  " ",
15429
16293
  "Charged At:",
15430
16294
  " ",
15431
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: new Date(psd.created * 1e3).toISOString() })
16295
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: new Date(psd.created * 1e3).toISOString() })
15432
16296
  ] }),
15433
- psd.refund_details && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15434
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16297
+ psd.refund_details && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16298
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15435
16299
  " ",
15436
16300
  "Refund:"
15437
16301
  ] }),
15438
- /* @__PURE__ */ jsxs19(Text21, { children: [
16302
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15439
16303
  " ",
15440
16304
  "Amount:",
15441
16305
  " ",
15442
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16306
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15443
16307
  psd.refund_details.amount,
15444
16308
  " ",
15445
16309
  psd.refund_details.currency
15446
16310
  ] })
15447
16311
  ] }),
15448
- /* @__PURE__ */ jsxs19(Text21, { children: [
16312
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15449
16313
  " ",
15450
16314
  "State: ",
15451
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: psd.refund_details.state })
16315
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: psd.refund_details.state })
15452
16316
  ] })
15453
16317
  ] })
15454
16318
  ] })
@@ -15456,71 +16320,71 @@ var RetrieveSpendRequest = ({
15456
16320
  ] });
15457
16321
  }
15458
16322
  if (phase === "declined") {
15459
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15460
- /* @__PURE__ */ jsx26(Text21, { color: "red", children: "\u2717 Spend request declined" }),
15461
- /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15462
- /* @__PURE__ */ jsxs19(Text21, { children: [
16323
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16324
+ /* @__PURE__ */ jsx30(Text23, { color: "red", children: "\u2717 Spend request declined" }),
16325
+ /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16326
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15463
16327
  "ID: ",
15464
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.id })
16328
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.id })
15465
16329
  ] }),
15466
- /* @__PURE__ */ jsxs19(Text21, { children: [
16330
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15467
16331
  "Status:",
15468
16332
  " ",
15469
- /* @__PURE__ */ jsx26(Text21, { bold: true, color: "red", children: request?.status })
16333
+ /* @__PURE__ */ jsx30(Text23, { bold: true, color: "red", children: request?.status })
15470
16334
  ] }),
15471
- /* @__PURE__ */ jsxs19(Text21, { children: [
16335
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15472
16336
  "Amount:",
15473
16337
  " ",
15474
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
16338
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
15475
16339
  ] }),
15476
- /* @__PURE__ */ jsxs19(Text21, { children: [
16340
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15477
16341
  "Merchant: ",
15478
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.merchant_name })
16342
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.merchant_name })
15479
16343
  ] })
15480
16344
  ] })
15481
16345
  ] });
15482
16346
  }
15483
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15484
- /* @__PURE__ */ jsx26(Text21, { color: "green", children: "\u2713 Spend request approved" }),
15485
- /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15486
- /* @__PURE__ */ jsxs19(Text21, { children: [
16347
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16348
+ /* @__PURE__ */ jsx30(Text23, { color: "green", children: "\u2713 Spend request approved" }),
16349
+ /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16350
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15487
16351
  "ID: ",
15488
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.id })
16352
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.id })
15489
16353
  ] }),
15490
- /* @__PURE__ */ jsxs19(Text21, { children: [
16354
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15491
16355
  "Status:",
15492
16356
  " ",
15493
- /* @__PURE__ */ jsx26(Text21, { bold: true, color: "green", children: request?.status })
16357
+ /* @__PURE__ */ jsx30(Text23, { bold: true, color: "green", children: request?.status })
15494
16358
  ] }),
15495
- /* @__PURE__ */ jsxs19(Text21, { children: [
16359
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15496
16360
  "Amount:",
15497
16361
  " ",
15498
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
16362
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
15499
16363
  ] }),
15500
- /* @__PURE__ */ jsxs19(Text21, { children: [
16364
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15501
16365
  "Merchant: ",
15502
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.merchant_name })
16366
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.merchant_name })
15503
16367
  ] }),
15504
- /* @__PURE__ */ jsxs19(Text21, { children: [
16368
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15505
16369
  "Line Items:",
15506
16370
  " ",
15507
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
16371
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
15508
16372
  ] }),
15509
- request?.link_pay_token && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15510
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: "Link Pay Token:" }),
15511
- /* @__PURE__ */ jsxs19(Text21, { children: [
16373
+ request?.link_pay_token && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16374
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: "Link Pay Token:" }),
16375
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15512
16376
  " ",
15513
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.link_pay_token })
16377
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.link_pay_token })
15514
16378
  ] })
15515
16379
  ] }),
15516
- request?.payment_status_details && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15517
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: "Last Payment Attempt:" }),
15518
- /* @__PURE__ */ jsxs19(Text21, { children: [
16380
+ request?.payment_status_details && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16381
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: "Last Payment Attempt:" }),
16382
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15519
16383
  " ",
15520
16384
  "Outcome:",
15521
16385
  " ",
15522
- /* @__PURE__ */ jsx26(
15523
- Text21,
16386
+ /* @__PURE__ */ jsx30(
16387
+ Text23,
15524
16388
  {
15525
16389
  bold: true,
15526
16390
  color: request.payment_status_details.outcome === "success" ? "green" : "red",
@@ -15528,79 +16392,79 @@ var RetrieveSpendRequest = ({
15528
16392
  }
15529
16393
  )
15530
16394
  ] }),
15531
- request.payment_status_details.code && /* @__PURE__ */ jsxs19(Text21, { children: [
16395
+ request.payment_status_details.code && /* @__PURE__ */ jsxs21(Text23, { children: [
15532
16396
  " ",
15533
16397
  "Code:",
15534
16398
  " ",
15535
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.payment_status_details.code })
16399
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.payment_status_details.code })
15536
16400
  ] }),
15537
- request.payment_status_details.decline_code && /* @__PURE__ */ jsxs19(Text21, { children: [
16401
+ request.payment_status_details.decline_code && /* @__PURE__ */ jsxs21(Text23, { children: [
15538
16402
  " ",
15539
16403
  "Decline Reason:",
15540
16404
  " ",
15541
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.payment_status_details.decline_code })
16405
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.payment_status_details.decline_code })
15542
16406
  ] })
15543
16407
  ] }),
15544
- request?.shared_payment_token && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15545
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16408
+ request?.shared_payment_token && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16409
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15546
16410
  "\x1B]8;;https://docs.stripe.com/agentic-commerce/concepts/shared-payment-tokens\x07",
15547
16411
  "Shared Payment Token",
15548
16412
  "\x1B]8;;\x07",
15549
16413
  ":"
15550
16414
  ] }),
15551
- /* @__PURE__ */ jsxs19(Text21, { children: [
16415
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15552
16416
  " ",
15553
16417
  "Token: ",
15554
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.shared_payment_token.id })
16418
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.shared_payment_token.id })
15555
16419
  ] })
15556
16420
  ] }),
15557
- request?.card && !outputFile && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15558
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: "Card Details:" }),
15559
- /* @__PURE__ */ jsxs19(Text21, { children: [
16421
+ request?.card && !outputFile && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16422
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: "Card Details:" }),
16423
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15560
16424
  " ",
15561
16425
  "Number: ",
15562
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.card.number })
16426
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.card.number })
15563
16427
  ] }),
15564
- /* @__PURE__ */ jsxs19(Text21, { children: [
16428
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15565
16429
  " ",
15566
16430
  "Brand: ",
15567
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.card.brand })
16431
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.card.brand })
15568
16432
  ] }),
15569
- /* @__PURE__ */ jsxs19(Text21, { children: [
16433
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15570
16434
  " ",
15571
16435
  "Expiry:",
15572
16436
  " ",
15573
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16437
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15574
16438
  String(request?.card.exp_month).padStart(2, "0"),
15575
16439
  "/",
15576
16440
  request?.card.exp_year
15577
16441
  ] })
15578
16442
  ] }),
15579
- request?.card.cvc && /* @__PURE__ */ jsxs19(Text21, { children: [
16443
+ request?.card.cvc && /* @__PURE__ */ jsxs21(Text23, { children: [
15580
16444
  " ",
15581
16445
  "CVC: ",
15582
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.card.cvc })
16446
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.card.cvc })
15583
16447
  ] }),
15584
- request?.card.valid_until && /* @__PURE__ */ jsxs19(Text21, { children: [
16448
+ request?.card.valid_until && /* @__PURE__ */ jsxs21(Text23, { children: [
15585
16449
  " ",
15586
16450
  "Valid Until: ",
15587
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.card.valid_until })
16451
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.card.valid_until })
15588
16452
  ] }),
15589
- request?.card.billing_address && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15590
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: " Billing Address:" }),
15591
- /* @__PURE__ */ jsxs19(Text21, { children: [
16453
+ request?.card.billing_address && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16454
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: " Billing Address:" }),
16455
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15592
16456
  " ",
15593
16457
  request.card.billing_address.name
15594
16458
  ] }),
15595
- /* @__PURE__ */ jsxs19(Text21, { children: [
16459
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15596
16460
  " ",
15597
16461
  request.card.billing_address.line1
15598
16462
  ] }),
15599
- request.card.billing_address.line2 && /* @__PURE__ */ jsxs19(Text21, { children: [
16463
+ request.card.billing_address.line2 && /* @__PURE__ */ jsxs21(Text23, { children: [
15600
16464
  " ",
15601
16465
  request.card.billing_address.line2
15602
16466
  ] }),
15603
- /* @__PURE__ */ jsxs19(Text21, { children: [
16467
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15604
16468
  " ",
15605
16469
  [
15606
16470
  request.card.billing_address.city,
@@ -15608,18 +16472,18 @@ var RetrieveSpendRequest = ({
15608
16472
  request.card.billing_address.postal_code
15609
16473
  ].filter(Boolean).join(", ")
15610
16474
  ] }),
15611
- /* @__PURE__ */ jsxs19(Text21, { children: [
16475
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15612
16476
  " ",
15613
16477
  request.card.billing_address.country
15614
16478
  ] })
15615
16479
  ] })
15616
16480
  ] }),
15617
- request?.card && outputFile && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15618
- outputFilePath && /* @__PURE__ */ jsxs19(Text21, { color: "green", children: [
16481
+ request?.card && outputFile && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16482
+ outputFilePath && /* @__PURE__ */ jsxs21(Text23, { color: "green", children: [
15619
16483
  "Card credentials written to ",
15620
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: outputFilePath })
16484
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: outputFilePath })
15621
16485
  ] }),
15622
- fileError && /* @__PURE__ */ jsxs19(Text21, { color: "red", children: [
16486
+ fileError && /* @__PURE__ */ jsxs21(Text23, { color: "red", children: [
15623
16487
  "Failed to write card file: ",
15624
16488
  fileError
15625
16489
  ] })
@@ -15629,140 +16493,143 @@ var RetrieveSpendRequest = ({
15629
16493
  };
15630
16494
 
15631
16495
  // src/commands/spend-request/schema.ts
15632
- import { z as z8 } from "incur";
15633
- var createOptions = z8.object({
15634
- paymentMethodId: z8.string().optional().describe("Payment method ID"),
15635
- credentialType: z8.enum(["shared_payment_token", "card"]).default("card").describe(
16496
+ import { z as z10 } from "incur";
16497
+ var createOptions = z10.object({
16498
+ paymentMethodId: z10.string().optional().describe("Payment method ID"),
16499
+ credentialType: z10.enum(["shared_payment_token", "card"]).default("card").describe(
15636
16500
  '"card" for checkout forms/Stripe Elements; "shared_payment_token" for HTTP 402/machine payment flows'
15637
16501
  ),
15638
- networkId: z8.string().optional().describe(
16502
+ networkId: z10.string().optional().describe(
15639
16503
  "Network ID (required for shared_payment_token) \u2014 use `link-cli mpp decode` to extract"
15640
16504
  ),
15641
- amount: z8.coerce.number().int().positive().max(5e5).describe("Amount in cents, max 500000 ($5,000.00)"),
15642
- currency: z8.string().length(3).default("usd").describe("Currency code"),
15643
- merchantName: z8.string().optional().describe(
16505
+ amount: z10.coerce.number().int().positive().max(5e5).describe("Amount in cents, max 500000 ($5,000.00)"),
16506
+ currency: z10.string().length(3).default("usd").describe("Currency code"),
16507
+ merchantName: z10.string().optional().describe(
15644
16508
  "Merchant name (required for card; forbidden for shared_payment_token)"
15645
16509
  ),
15646
- merchantUrl: z8.string().optional().describe(
16510
+ merchantUrl: z10.string().optional().describe(
15647
16511
  "Merchant URL (required for card; forbidden for shared_payment_token)"
15648
16512
  ),
15649
- context: z8.string().min(100).describe(
16513
+ context: z10.string().min(100).describe(
15650
16514
  "Min 100 chars \u2014 describe the purchase and rationale; the user reads this when approving"
15651
16515
  ),
15652
- lineItem: z8.array(z8.union([z8.string(), z8.record(z8.string(), z8.unknown())])).default([]).describe(
16516
+ lineItem: z10.array(z10.union([z10.string(), z10.record(z10.string(), z10.unknown())])).default([]).describe(
15653
16517
  'Line item (repeatable, key:value format). Keys: name (required), quantity, unit_amount, description, sku, url, image_url, product_url. Example: "name:Shoes,unit_amount:5000,quantity:2"'
15654
16518
  ),
15655
- total: z8.array(z8.union([z8.string(), z8.record(z8.string(), z8.unknown())])).default([]).describe(
16519
+ total: z10.array(z10.union([z10.string(), z10.record(z10.string(), z10.unknown())])).default([]).describe(
15656
16520
  'Total (repeatable, key:value format). Keys: type (required; one of: subtotal, tax, total, items_base_amount, items_discount, discount, fulfillment, shipping, fee, gift_wrap, tip, store_credit), display_text (required), amount (required). Example: "type:total,display_text:Total,amount:5000"'
15657
16521
  ),
15658
- requestApproval: z8.boolean().default(true).describe("Request approval and poll until approved/denied/expired"),
15659
- test: z8.boolean().default(false).describe(
16522
+ requestApproval: z10.boolean().default(true).describe("Request approval and poll until approved/denied/expired"),
16523
+ test: z10.boolean().default(false).describe(
15660
16524
  "Use test mode (creates testmode credentials from test card data)"
15661
16525
  ),
15662
- approve: z8.boolean().default(false).describe(""),
15663
- outputFile: z8.string().optional().describe(
16526
+ approve: z10.boolean().default(false).describe(""),
16527
+ outputFile: z10.string().optional().describe(
15664
16528
  "Write full card credentials to this file path; stdout shows redacted card data only"
15665
16529
  ),
15666
- force: z8.boolean().default(false).describe("Overwrite output file if it already exists")
16530
+ force: z10.boolean().default(false).describe("Overwrite output file if it already exists"),
16531
+ approvalDetail: z10.union([z10.string(), z10.record(z10.string(), z10.unknown())]).optional().describe(
16532
+ "Approval details object (MCP/agent: pass as object; CLI: pass as JSON string). Required fields: approved_at (unix timestamp), approval_method (click|programmatic|voice), app_name, external_user_id. Optional: ip_address, user_agent, device_type (mobile|web), agent_log_id, external_user_name, external_session_id, authentication_method (biometric_face|biometric_fingerprint|passkey)."
16533
+ )
15667
16534
  });
15668
- var listOptions = z8.object({
15669
- includeHistory: z8.boolean().default(false).describe("Include expired and terminal spend requests")
16535
+ var listOptions3 = z10.object({
16536
+ includeHistory: z10.boolean().default(false).describe("Include expired and terminal spend requests")
15670
16537
  });
15671
- var retrieveOptions = z8.object({
15672
- timeout: z8.coerce.number().default(600).describe(
16538
+ var retrieveOptions = z10.object({
16539
+ timeout: z10.coerce.number().default(600).describe(
15673
16540
  "Polling timeout in seconds. When reached during active polling, exits non-zero with POLLING_TIMEOUT. Default exceeds the server-side spend-request expiry so polling outlives the request itself."
15674
16541
  ),
15675
- interval: z8.coerce.number().default(0).describe(
16542
+ interval: z10.coerce.number().default(0).describe(
15676
16543
  "Poll interval in seconds. When > 0, polls until status is terminal, timeout is reached, or max attempts are exhausted."
15677
16544
  ),
15678
- maxAttempts: z8.coerce.number().default(0).describe(
16545
+ maxAttempts: z10.coerce.number().default(0).describe(
15679
16546
  "Max poll attempts. 0 = unlimited. Exhaustion during active polling exits non-zero with POLLING_TIMEOUT."
15680
16547
  ),
15681
- include: z8.array(z8.string()).default([]).describe("Include extra data (repeatable, e.g. --include card)"),
15682
- outputFile: z8.string().optional().describe(
16548
+ include: z10.array(z10.string()).default([]).describe("Include extra data (repeatable, e.g. --include card)"),
16549
+ outputFile: z10.string().optional().describe(
15683
16550
  "Write full card credentials to this file path; stdout shows redacted card data only"
15684
16551
  ),
15685
- force: z8.boolean().default(false).describe("Overwrite output file if it already exists")
16552
+ force: z10.boolean().default(false).describe("Overwrite output file if it already exists")
15686
16553
  });
15687
- var updateOptions = z8.object({
15688
- paymentMethodId: z8.string().optional().describe("Payment method ID"),
15689
- amount: z8.coerce.number().optional().describe("Amount in cents"),
15690
- merchantUrl: z8.string().optional().describe("Merchant URL"),
15691
- profileId: z8.string().optional().describe("Profile ID"),
15692
- merchantId: z8.string().optional().describe("Merchant ID"),
15693
- currency: z8.string().optional().describe("Currency code"),
15694
- lineItem: z8.array(z8.union([z8.string(), z8.record(z8.string(), z8.unknown())])).default([]).describe(
16554
+ var updateOptions = z10.object({
16555
+ paymentMethodId: z10.string().optional().describe("Payment method ID"),
16556
+ amount: z10.coerce.number().optional().describe("Amount in cents"),
16557
+ merchantUrl: z10.string().optional().describe("Merchant URL"),
16558
+ profileId: z10.string().optional().describe("Profile ID"),
16559
+ merchantId: z10.string().optional().describe("Merchant ID"),
16560
+ currency: z10.string().optional().describe("Currency code"),
16561
+ lineItem: z10.array(z10.union([z10.string(), z10.record(z10.string(), z10.unknown())])).default([]).describe(
15695
16562
  'Line item (repeatable, key:value format). Keys: name (required), quantity, unit_amount, description, sku, url, image_url, product_url. Example: "name:Shoes,unit_amount:5000,quantity:2"'
15696
16563
  ),
15697
- total: z8.array(z8.union([z8.string(), z8.record(z8.string(), z8.unknown())])).default([]).describe(
16564
+ total: z10.array(z10.union([z10.string(), z10.record(z10.string(), z10.unknown())])).default([]).describe(
15698
16565
  'Total (repeatable, key:value format). Keys: type (required; one of: subtotal, tax, total, items_base_amount, items_discount, discount, fulfillment, shipping, fee, gift_wrap, tip, store_credit), display_text (required), amount (required). Example: "type:total,display_text:Total,amount:5000"'
15699
16566
  )
15700
16567
  });
15701
16568
 
15702
16569
  // src/commands/spend-request/update.tsx
15703
- import { Box as Box20, Text as Text22 } from "ink";
15704
- import Spinner12 from "ink-spinner";
15705
- import { useCallback as useCallback9 } from "react";
15706
- import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
16570
+ import { Box as Box22, Text as Text24 } from "ink";
16571
+ import Spinner14 from "ink-spinner";
16572
+ import { useCallback as useCallback11 } from "react";
16573
+ import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
15707
16574
  var UpdateSpendRequest = ({
15708
16575
  repository,
15709
16576
  id,
15710
16577
  params,
15711
16578
  onComplete
15712
16579
  }) => {
15713
- const action = useCallback9(
16580
+ const action = useCallback11(
15714
16581
  () => repository.updateSpendRequest(id, params),
15715
16582
  [repository, id, params]
15716
16583
  );
15717
16584
  const { status, data: request, error } = useAsyncAction(action, onComplete);
15718
16585
  if (status === "loading") {
15719
- return /* @__PURE__ */ jsx27(Box20, { children: /* @__PURE__ */ jsxs20(Text22, { color: "cyan", children: [
15720
- /* @__PURE__ */ jsx27(Spinner12, { type: "dots" }),
16586
+ return /* @__PURE__ */ jsx31(Box22, { children: /* @__PURE__ */ jsxs22(Text24, { color: "cyan", children: [
16587
+ /* @__PURE__ */ jsx31(Spinner14, { type: "dots" }),
15721
16588
  " Updating spend request ",
15722
16589
  id,
15723
16590
  "..."
15724
16591
  ] }) });
15725
16592
  }
15726
16593
  if (status === "error") {
15727
- return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
15728
- /* @__PURE__ */ jsx27(Text22, { color: "red", children: "\u2717 Failed to update spend request" }),
15729
- /* @__PURE__ */ jsx27(Text22, { color: "red", children: error })
16594
+ return /* @__PURE__ */ jsxs22(Box22, { flexDirection: "column", children: [
16595
+ /* @__PURE__ */ jsx31(Text24, { color: "red", children: "\u2717 Failed to update spend request" }),
16596
+ /* @__PURE__ */ jsx31(Text24, { color: "red", children: error })
15730
16597
  ] });
15731
16598
  }
15732
- return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
15733
- /* @__PURE__ */ jsx27(Text22, { color: "green", children: "\u2713 Spend request updated" }),
15734
- /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15735
- /* @__PURE__ */ jsxs20(Text22, { children: [
16599
+ return /* @__PURE__ */ jsxs22(Box22, { flexDirection: "column", children: [
16600
+ /* @__PURE__ */ jsx31(Text24, { color: "green", children: "\u2713 Spend request updated" }),
16601
+ /* @__PURE__ */ jsxs22(Box22, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16602
+ /* @__PURE__ */ jsxs22(Text24, { children: [
15736
16603
  "ID: ",
15737
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: request?.id })
16604
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: request?.id })
15738
16605
  ] }),
15739
- /* @__PURE__ */ jsxs20(Text22, { children: [
16606
+ /* @__PURE__ */ jsxs22(Text24, { children: [
15740
16607
  "Status: ",
15741
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: request?.status })
16608
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: request?.status })
15742
16609
  ] }),
15743
- /* @__PURE__ */ jsxs20(Text22, { children: [
16610
+ /* @__PURE__ */ jsxs22(Text24, { children: [
15744
16611
  "Amount:",
15745
16612
  " ",
15746
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: (() => {
16613
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: (() => {
15747
16614
  const t = request?.totals.find((t2) => t2.type === "total");
15748
16615
  return t ? String(t.amount) : "N/A";
15749
16616
  })() })
15750
16617
  ] }),
15751
- /* @__PURE__ */ jsxs20(Text22, { children: [
16618
+ /* @__PURE__ */ jsxs22(Text24, { children: [
15752
16619
  "Merchant: ",
15753
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: request?.merchant_name })
16620
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: request?.merchant_name })
15754
16621
  ] }),
15755
- /* @__PURE__ */ jsxs20(Text22, { children: [
16622
+ /* @__PURE__ */ jsxs22(Text24, { children: [
15756
16623
  "Line Items:",
15757
16624
  " ",
15758
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
16625
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
15759
16626
  ] })
15760
16627
  ] })
15761
16628
  ] });
15762
16629
  };
15763
16630
 
15764
16631
  // src/commands/spend-request/index.tsx
15765
- import { jsx as jsx28 } from "react/jsx-runtime";
16632
+ import { jsx as jsx32 } from "react/jsx-runtime";
15766
16633
  async function applyOutputFile(request, outputFile, force) {
15767
16634
  if (!outputFile || !request.card) return request;
15768
16635
  const fileData = {
@@ -15781,19 +16648,19 @@ async function applyOutputFile(request, outputFile, force) {
15781
16648
  };
15782
16649
  }
15783
16650
  function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
15784
- const cli2 = Cli9.create("spend-request", {
16651
+ const cli2 = Cli11.create("spend-request", {
15785
16652
  description: "Spend request management commands"
15786
16653
  });
15787
16654
  cli2.command("list", {
15788
16655
  description: "List spend requests. By default returns only active requests (created, pending_approval, approved). Use --include-history to return all spend requests including expired and terminal states.",
15789
16656
  outputPolicy: "agent-only",
15790
- options: listOptions,
16657
+ options: listOptions3,
15791
16658
  middleware: [requireAuth(authStorage2, envAccessToken2)],
15792
16659
  async run(c) {
15793
16660
  const opts = { includeHistory: c.options.includeHistory ?? false };
15794
16661
  if (!c.agent && !c.formatExplicit) {
15795
16662
  return renderInteractive(
15796
- /* @__PURE__ */ jsx28(
16663
+ /* @__PURE__ */ jsx32(
15797
16664
  SpendRequestList,
15798
16665
  {
15799
16666
  repository,
@@ -15857,6 +16724,7 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
15857
16724
  const totals = opts.total?.length ? opts.total.map(
15858
16725
  (item) => typeof item === "string" ? parseTotalFlag(item) : item
15859
16726
  ) : void 0;
16727
+ const approvalDetails = opts.approvalDetail !== void 0 ? typeof opts.approvalDetail === "string" ? JSON.parse(opts.approvalDetail) : opts.approvalDetail : void 0;
15860
16728
  const createParams = {
15861
16729
  payment_details: opts.paymentMethodId,
15862
16730
  credential_type: credentialType,
@@ -15870,14 +16738,15 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
15870
16738
  totals,
15871
16739
  request_approval: requestApproval || void 0,
15872
16740
  test: opts.test ? true : void 0,
15873
- approve: opts.approve ? true : void 0
16741
+ approve: opts.approve ? true : void 0,
16742
+ approval_details: approvalDetails
15874
16743
  };
15875
16744
  const outputFile = opts.outputFile;
15876
16745
  const forceOverwrite = opts.force;
15877
16746
  if (!c.agent && !c.formatExplicit) {
15878
- let capturedResult = null;
16747
+ let capturedResult = void 0;
15879
16748
  return renderInteractive(
15880
- /* @__PURE__ */ jsx28(
16749
+ /* @__PURE__ */ jsx32(
15881
16750
  CreateSpendRequest,
15882
16751
  {
15883
16752
  repository,
@@ -15891,13 +16760,28 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
15891
16760
  }
15892
16761
  ),
15893
16762
  () => {
15894
- if (!capturedResult)
16763
+ if (capturedResult === void 0)
15895
16764
  throw new Error("Component exited without producing a result");
16765
+ if (capturedResult === null) process.exit(1);
15896
16766
  return capturedResult;
15897
16767
  }
15898
16768
  );
15899
16769
  }
15900
- const created = await repository.createSpendRequest(createParams);
16770
+ let created;
16771
+ try {
16772
+ created = await repository.createSpendRequest(createParams);
16773
+ } catch (err) {
16774
+ if (err instanceof LinkApiError) {
16775
+ const apiErr = err.details;
16776
+ if (apiErr?.error?.verification_url) {
16777
+ return c.error({
16778
+ code: err.code,
16779
+ message: `${err.message} Verification URL: ${apiErr.error.verification_url}`
16780
+ });
16781
+ }
16782
+ }
16783
+ throw err;
16784
+ }
15901
16785
  if (!requestApproval) {
15902
16786
  try {
15903
16787
  yield await applyOutputFile(created, outputFile, forceOverwrite);
@@ -15922,8 +16806,8 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
15922
16806
  });
15923
16807
  cli2.command("update", {
15924
16808
  description: "Update a spend request",
15925
- args: z9.object({
15926
- id: z9.string().describe("Spend request ID")
16809
+ args: z11.object({
16810
+ id: z11.string().describe("Spend request ID")
15927
16811
  }),
15928
16812
  options: updateOptions,
15929
16813
  outputPolicy: "agent-only",
@@ -15951,7 +16835,7 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
15951
16835
  if (!c.agent && !c.formatExplicit) {
15952
16836
  let capturedResult = null;
15953
16837
  return renderInteractive(
15954
- /* @__PURE__ */ jsx28(
16838
+ /* @__PURE__ */ jsx32(
15955
16839
  UpdateSpendRequest,
15956
16840
  {
15957
16841
  repository,
@@ -15974,17 +16858,17 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
15974
16858
  });
15975
16859
  cli2.command("request-approval", {
15976
16860
  description: "Request approval for a spend request",
15977
- args: z9.object({
15978
- id: z9.string().describe("Spend request ID")
16861
+ args: z11.object({
16862
+ id: z11.string().describe("Spend request ID")
15979
16863
  }),
15980
16864
  outputPolicy: "agent-only",
15981
16865
  async *run(c) {
15982
16866
  requireAuthGuard(c, authStorage2, envAccessToken2);
15983
16867
  const id = c.args.id;
15984
16868
  if (!c.agent && !c.formatExplicit) {
15985
- let capturedResult = null;
16869
+ let capturedResult = void 0;
15986
16870
  return renderInteractive(
15987
- /* @__PURE__ */ jsx28(
16871
+ /* @__PURE__ */ jsx32(
15988
16872
  RequestApproval,
15989
16873
  {
15990
16874
  repository,
@@ -15995,13 +16879,28 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
15995
16879
  }
15996
16880
  ),
15997
16881
  () => {
15998
- if (!capturedResult)
16882
+ if (capturedResult === void 0)
15999
16883
  throw new Error("Component exited without producing a result");
16884
+ if (capturedResult === null) process.exit(1);
16000
16885
  return capturedResult;
16001
16886
  }
16002
16887
  );
16003
16888
  }
16004
- const approval = await repository.requestApproval(id);
16889
+ let approval;
16890
+ try {
16891
+ approval = await repository.requestApproval(id);
16892
+ } catch (err) {
16893
+ if (err instanceof LinkApiError) {
16894
+ const apiErr = err.details;
16895
+ if (apiErr?.error?.verification_url) {
16896
+ return c.error({
16897
+ code: err.code,
16898
+ message: `${err.message} Verification URL: ${apiErr.error.verification_url}`
16899
+ });
16900
+ }
16901
+ }
16902
+ throw err;
16903
+ }
16005
16904
  yield {
16006
16905
  ...approval,
16007
16906
  instruction: `Present the approval_url to the user and ask them to approve in the Link app. Then call \`spend-request retrieve ${id} --interval 2 --max-attempts 300\` to poll until approved. Do not wait for the user to reply \u2014 start polling immediately.`,
@@ -16014,8 +16913,8 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16014
16913
  });
16015
16914
  cli2.command("retrieve", {
16016
16915
  description: "Retrieve a spend request",
16017
- args: z9.object({
16018
- id: z9.string().describe("Spend request ID")
16916
+ args: z11.object({
16917
+ id: z11.string().describe("Spend request ID")
16019
16918
  }),
16020
16919
  options: retrieveOptions,
16021
16920
  outputPolicy: "agent-only",
@@ -16033,7 +16932,7 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16033
16932
  if (!c.agent && !c.formatExplicit) {
16034
16933
  let capturedResult = null;
16035
16934
  return renderInteractive(
16036
- /* @__PURE__ */ jsx28(
16935
+ /* @__PURE__ */ jsx32(
16037
16936
  RetrieveSpendRequest,
16038
16937
  {
16039
16938
  repository,
@@ -16105,8 +17004,8 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16105
17004
  });
16106
17005
  cli2.command("cancel", {
16107
17006
  description: "Cancel a spend request",
16108
- args: z9.object({
16109
- id: z9.string().describe("Spend request ID")
17007
+ args: z11.object({
17008
+ id: z11.string().describe("Spend request ID")
16110
17009
  }),
16111
17010
  outputPolicy: "agent-only",
16112
17011
  middleware: [requireAuth(authStorage2, envAccessToken2)],
@@ -16115,7 +17014,7 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16115
17014
  if (!c.agent && !c.formatExplicit) {
16116
17015
  let capturedResult = null;
16117
17016
  return renderInteractive(
16118
- /* @__PURE__ */ jsx28(
17017
+ /* @__PURE__ */ jsx32(
16119
17018
  CancelSpendRequest,
16120
17019
  {
16121
17020
  repository,
@@ -16138,55 +17037,221 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16138
17037
  return cli2;
16139
17038
  }
16140
17039
 
17040
+ // src/commands/transactions/index.tsx
17041
+ import { Cli as Cli12 } from "incur";
17042
+
17043
+ // src/commands/transactions/list.tsx
17044
+ import { Box as Box23, Text as Text25 } from "ink";
17045
+ import Spinner15 from "ink-spinner";
17046
+ import { useCallback as useCallback12 } from "react";
17047
+ import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
17048
+ var COLUMN_GAP3 = " ";
17049
+ var DATE_WIDTH = 10;
17050
+ var AMOUNT_WIDTH = 13;
17051
+ var STATUS_WIDTH = 10;
17052
+ var CATEGORY_WIDTH = 16;
17053
+ var MIN_DESCRIPTION_WIDTH = 16;
17054
+ var HORIZONTAL_PADDING2 = 4;
17055
+ function formatAmount(amount, currency) {
17056
+ const currencyCode = currency.toUpperCase();
17057
+ try {
17058
+ const formatter = new Intl.NumberFormat("en-US", {
17059
+ style: "currency",
17060
+ currency: currencyCode
17061
+ });
17062
+ const fractionDigits = formatter.resolvedOptions().maximumFractionDigits ?? 2;
17063
+ return formatter.format(amount / 10 ** fractionDigits);
17064
+ } catch {
17065
+ return `${amount} ${currency}`;
17066
+ }
17067
+ }
17068
+ function truncateCell3(value, width) {
17069
+ if (value.length <= width) {
17070
+ return value;
17071
+ }
17072
+ if (width <= 3) {
17073
+ return value.slice(0, width);
17074
+ }
17075
+ return `${value.slice(0, width - 3)}...`;
17076
+ }
17077
+ function formatCell3(value, width, align = "left") {
17078
+ const truncated = truncateCell3(value, width);
17079
+ return align === "right" ? truncated.padStart(width) : truncated.padEnd(width);
17080
+ }
17081
+ var TransactionsList = ({
17082
+ resource,
17083
+ params,
17084
+ onComplete
17085
+ }) => {
17086
+ const action = useCallback12(
17087
+ () => resource.listTransactions(params),
17088
+ [resource, params]
17089
+ );
17090
+ const { status, data: page, error } = useAsyncAction(action, onComplete);
17091
+ const transactions = page?.data ?? [];
17092
+ const nextCursor = page?.has_more && transactions.length > 0 ? transactions[transactions.length - 1].id : null;
17093
+ const terminalWidth = process.stdout.columns ?? 100;
17094
+ const descriptionWidth = Math.max(
17095
+ MIN_DESCRIPTION_WIDTH,
17096
+ terminalWidth - HORIZONTAL_PADDING2 - DATE_WIDTH - AMOUNT_WIDTH - STATUS_WIDTH - CATEGORY_WIDTH - COLUMN_GAP3.length * 4
17097
+ );
17098
+ const headerRow = [
17099
+ formatCell3("Date", DATE_WIDTH),
17100
+ formatCell3("Amount", AMOUNT_WIDTH, "right"),
17101
+ formatCell3("Status", STATUS_WIDTH),
17102
+ formatCell3("Category", CATEGORY_WIDTH),
17103
+ formatCell3("Description", descriptionWidth)
17104
+ ].join(COLUMN_GAP3);
17105
+ const separatorRow = "-".repeat(headerRow.length);
17106
+ const rows = transactions.map(
17107
+ (txn) => [
17108
+ formatCell3(txn.created_date, DATE_WIDTH),
17109
+ formatCell3(formatAmount(txn.amount, txn.currency), AMOUNT_WIDTH, "right"),
17110
+ formatCell3(txn.status, STATUS_WIDTH),
17111
+ formatCell3(txn.category ?? "", CATEGORY_WIDTH),
17112
+ formatCell3(txn.description, descriptionWidth)
17113
+ ].join(COLUMN_GAP3)
17114
+ );
17115
+ if (status === "loading") {
17116
+ return /* @__PURE__ */ jsx33(Box23, { children: /* @__PURE__ */ jsxs23(Text25, { color: "cyan", children: [
17117
+ /* @__PURE__ */ jsx33(Spinner15, { type: "dots" }),
17118
+ " Loading transactions..."
17119
+ ] }) });
17120
+ }
17121
+ if (status === "error") {
17122
+ return /* @__PURE__ */ jsxs23(Box23, { flexDirection: "column", children: [
17123
+ /* @__PURE__ */ jsx33(Text25, { color: "red", children: "Failed to load transactions" }),
17124
+ /* @__PURE__ */ jsx33(Text25, { color: "red", children: error })
17125
+ ] });
17126
+ }
17127
+ if (transactions.length === 0) {
17128
+ return /* @__PURE__ */ jsx33(Box23, { children: /* @__PURE__ */ jsx33(Text25, { dimColor: true, children: "No transactions found" }) });
17129
+ }
17130
+ return /* @__PURE__ */ jsxs23(Box23, { flexDirection: "column", children: [
17131
+ /* @__PURE__ */ jsx33(Text25, { bold: true, children: "Transactions" }),
17132
+ /* @__PURE__ */ jsxs23(Box23, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
17133
+ /* @__PURE__ */ jsx33(Text25, { bold: true, children: headerRow }),
17134
+ /* @__PURE__ */ jsx33(Text25, { dimColor: true, children: separatorRow }),
17135
+ rows.map((row, index) => /* @__PURE__ */ jsx33(Text25, { children: row }, transactions[index].id))
17136
+ ] }),
17137
+ page?.has_more !== void 0 ? /* @__PURE__ */ jsxs23(Box23, { flexDirection: "column", marginTop: 1, children: [
17138
+ /* @__PURE__ */ jsxs23(Text25, { dimColor: true, children: [
17139
+ "has_more: ",
17140
+ String(page.has_more)
17141
+ ] }),
17142
+ nextCursor ? /* @__PURE__ */ jsx33(Text25, { dimColor: true, children: `next page: --starting-after ${nextCursor}` }) : null
17143
+ ] }) : null
17144
+ ] });
17145
+ };
17146
+
17147
+ // src/commands/transactions/schema.ts
17148
+ import { z as z12 } from "incur";
17149
+ var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
17150
+ var listOptions4 = z12.object({
17151
+ limit: z12.coerce.number().int().positive().max(100).optional().describe("Maximum number of transactions to return (1-100)."),
17152
+ startingAfter: z12.string().optional().describe("Cursor: return transactions after this transaction ID."),
17153
+ endingBefore: z12.string().optional().describe("Cursor: return transactions before this transaction ID."),
17154
+ startDate: z12.string().regex(ISO_DATE_REGEX, "Date must be in YYYY-MM-DD format.").optional().describe("Only include transactions on or after this YYYY-MM-DD date."),
17155
+ endDate: z12.string().regex(ISO_DATE_REGEX, "Date must be in YYYY-MM-DD format.").optional().describe("Only include transactions on or before this YYYY-MM-DD date."),
17156
+ category: z12.string().optional().describe("Filter by transaction category."),
17157
+ origin: z12.enum(["link", "external_connection"]).optional().describe("Filter by transaction origin: link or external_connection."),
17158
+ source: z12.array(z12.string()).default([]).describe("Filter by source ID. Repeat to include multiple sources.")
17159
+ });
17160
+
17161
+ // src/commands/transactions/index.tsx
17162
+ import { jsx as jsx34 } from "react/jsx-runtime";
17163
+ function createTransactionsCli(createResource, authStorage2, envAccessToken2) {
17164
+ const cli2 = Cli12.create("transactions", {
17165
+ description: "List transactions from Link and external accounts"
17166
+ });
17167
+ cli2.command("list", {
17168
+ description: "List transactions from Link and external accounts, including non-Link activity",
17169
+ options: listOptions4,
17170
+ outputPolicy: "agent-only",
17171
+ middleware: [requireAuth(authStorage2, envAccessToken2)],
17172
+ async run(c) {
17173
+ const opts = c.options;
17174
+ const resource = createResource();
17175
+ const params = {};
17176
+ if (opts.limit !== void 0) params.limit = opts.limit;
17177
+ if (opts.startingAfter !== void 0)
17178
+ params.starting_after = opts.startingAfter;
17179
+ if (opts.endingBefore !== void 0)
17180
+ params.ending_before = opts.endingBefore;
17181
+ if (opts.startDate !== void 0) params.start_date = opts.startDate;
17182
+ if (opts.endDate !== void 0) params.end_date = opts.endDate;
17183
+ if (opts.category !== void 0) params.category = opts.category;
17184
+ if (opts.origin !== void 0) params.origin = opts.origin;
17185
+ if (opts.source.length > 0) params.sources = opts.source;
17186
+ if (!c.agent && !c.formatExplicit) {
17187
+ return renderInteractive(
17188
+ /* @__PURE__ */ jsx34(
17189
+ TransactionsList,
17190
+ {
17191
+ resource,
17192
+ params,
17193
+ onComplete: () => {
17194
+ }
17195
+ }
17196
+ ),
17197
+ () => resource.listTransactions(params)
17198
+ );
17199
+ }
17200
+ return resource.listTransactions(params);
17201
+ }
17202
+ });
17203
+ return cli2;
17204
+ }
17205
+
16141
17206
  // src/commands/user-info/index.tsx
16142
- import { Cli as Cli10 } from "incur";
17207
+ import { Cli as Cli13 } from "incur";
16143
17208
 
16144
17209
  // src/commands/user-info/retrieve.tsx
16145
- import { Box as Box21, Text as Text23 } from "ink";
16146
- import Spinner13 from "ink-spinner";
16147
- import { useCallback as useCallback10 } from "react";
16148
- import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
17210
+ import { Box as Box24, Text as Text26 } from "ink";
17211
+ import Spinner16 from "ink-spinner";
17212
+ import { useCallback as useCallback13 } from "react";
17213
+ import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
16149
17214
  var UserInfoRetrieve = ({
16150
17215
  resource,
16151
17216
  onComplete
16152
17217
  }) => {
16153
- const action = useCallback10(() => resource.retrieve(), [resource]);
17218
+ const action = useCallback13(() => resource.retrieve(), [resource]);
16154
17219
  const { status, data: userInfo, error } = useAsyncAction(action, onComplete);
16155
17220
  if (status === "loading") {
16156
- return /* @__PURE__ */ jsx29(Box21, { children: /* @__PURE__ */ jsxs21(Text23, { color: "cyan", children: [
16157
- /* @__PURE__ */ jsx29(Spinner13, { type: "dots" }),
17221
+ return /* @__PURE__ */ jsx35(Box24, { children: /* @__PURE__ */ jsxs24(Text26, { color: "cyan", children: [
17222
+ /* @__PURE__ */ jsx35(Spinner16, { type: "dots" }),
16158
17223
  " Loading user info..."
16159
17224
  ] }) });
16160
17225
  }
16161
17226
  if (status === "error") {
16162
- return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16163
- /* @__PURE__ */ jsx29(Text23, { color: "red", children: "\u2717 Failed to load user info" }),
16164
- /* @__PURE__ */ jsx29(Text23, { color: "red", children: error })
17227
+ return /* @__PURE__ */ jsxs24(Box24, { flexDirection: "column", children: [
17228
+ /* @__PURE__ */ jsx35(Text26, { color: "red", children: "\u2717 Failed to load user info" }),
17229
+ /* @__PURE__ */ jsx35(Text26, { color: "red", children: error })
16165
17230
  ] });
16166
17231
  }
16167
- return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16168
- /* @__PURE__ */ jsx29(Text23, { bold: true, children: "User Info" }),
16169
- /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16170
- /* @__PURE__ */ jsxs21(Text23, { children: [
16171
- /* @__PURE__ */ jsx29(Text23, { dimColor: true, children: "Email: " }),
16172
- userInfo?.email ?? /* @__PURE__ */ jsx29(Text23, { dimColor: true, children: "Not set" })
17232
+ return /* @__PURE__ */ jsxs24(Box24, { flexDirection: "column", children: [
17233
+ /* @__PURE__ */ jsx35(Text26, { bold: true, children: "User Info" }),
17234
+ /* @__PURE__ */ jsxs24(Box24, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
17235
+ /* @__PURE__ */ jsxs24(Text26, { children: [
17236
+ /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Email: " }),
17237
+ userInfo?.email ?? /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Not set" })
16173
17238
  ] }),
16174
- /* @__PURE__ */ jsxs21(Text23, { children: [
16175
- /* @__PURE__ */ jsx29(Text23, { dimColor: true, children: "Name: " }),
16176
- userInfo?.name ?? /* @__PURE__ */ jsx29(Text23, { dimColor: true, children: "Not set" })
17239
+ /* @__PURE__ */ jsxs24(Text26, { children: [
17240
+ /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Name: " }),
17241
+ userInfo?.name ?? /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Not set" })
16177
17242
  ] }),
16178
- /* @__PURE__ */ jsxs21(Text23, { children: [
16179
- /* @__PURE__ */ jsx29(Text23, { dimColor: true, children: "Phone: " }),
16180
- userInfo?.phone ?? /* @__PURE__ */ jsx29(Text23, { dimColor: true, children: "Not set" })
17243
+ /* @__PURE__ */ jsxs24(Text26, { children: [
17244
+ /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Phone: " }),
17245
+ userInfo?.phone ?? /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Not set" })
16181
17246
  ] })
16182
17247
  ] })
16183
17248
  ] });
16184
17249
  };
16185
17250
 
16186
17251
  // src/commands/user-info/index.tsx
16187
- import { jsx as jsx30 } from "react/jsx-runtime";
17252
+ import { jsx as jsx36 } from "react/jsx-runtime";
16188
17253
  function createUserInfoCli(createResource, authStorage2, envAccessToken2) {
16189
- const cli2 = Cli10.create("user-info", {
17254
+ const cli2 = Cli13.create("user-info", {
16190
17255
  description: "User information commands"
16191
17256
  });
16192
17257
  cli2.command("retrieve", {
@@ -16197,7 +17262,7 @@ function createUserInfoCli(createResource, authStorage2, envAccessToken2) {
16197
17262
  const resource = createResource();
16198
17263
  if (!c.agent && !c.formatExplicit) {
16199
17264
  return renderInteractive(
16200
- /* @__PURE__ */ jsx30(UserInfoRetrieve, { resource, onComplete: () => {
17265
+ /* @__PURE__ */ jsx36(UserInfoRetrieve, { resource, onComplete: () => {
16201
17266
  } }),
16202
17267
  () => resource.retrieve()
16203
17268
  );
@@ -16248,11 +17313,55 @@ function requireFetchImplementation2(config) {
16248
17313
 
16249
17314
  // src/auth/auth-resource.ts
16250
17315
  var CLIENT_ID = "lwlpk_U7Qy7ThG69STZk";
16251
- var DEFAULT_SCOPE = "userinfo:read payment_methods.agentic";
16252
17316
  function formatOAuthError(prefix, status, data, rawBody) {
16253
17317
  const err = data;
16254
17318
  return `${prefix} (${status}): ${err?.error_description ?? err?.error ?? (rawBody || "unknown error")}`;
16255
17319
  }
17320
+ function appendAuthorizationDetailValue(params, key, value) {
17321
+ if (Array.isArray(value)) {
17322
+ for (const entry of value) {
17323
+ appendAuthorizationDetailValue(params, `${key}[]`, entry);
17324
+ }
17325
+ return;
17326
+ }
17327
+ if (value !== null && typeof value === "object") {
17328
+ for (const [entryKey, entryValue] of Object.entries(value)) {
17329
+ appendAuthorizationDetailValue(params, `${key}[${entryKey}]`, entryValue);
17330
+ }
17331
+ return;
17332
+ }
17333
+ params.append(key, String(value));
17334
+ }
17335
+ function buildDeviceCodeForm(clientName, options) {
17336
+ const connectionLabel = `${clientName} on ${hostname()}`;
17337
+ const params = new URLSearchParams({
17338
+ client_id: CLIENT_ID,
17339
+ scope: options.scope ?? DEFAULT_SCOPE,
17340
+ connection_label: connectionLabel,
17341
+ client_hint: clientName
17342
+ });
17343
+ const authorizationDetails = buildAuthorizationDetails(
17344
+ options.sourceActions,
17345
+ options.authorizationDetails
17346
+ );
17347
+ for (const detail of authorizationDetails) {
17348
+ appendAuthorizationDetailValue(params, "authorization_details[]", detail);
17349
+ }
17350
+ return params;
17351
+ }
17352
+ function serializeFormBody(params) {
17353
+ return params instanceof URLSearchParams ? params.toString() : new URLSearchParams(params).toString();
17354
+ }
17355
+ function serializeRedactedFormBody(params) {
17356
+ const redacted = new URLSearchParams(params);
17357
+ if (redacted.has("device_code")) {
17358
+ redacted.set("device_code", "<redacted>");
17359
+ }
17360
+ if (redacted.has("refresh_token")) {
17361
+ redacted.set("refresh_token", "<redacted>");
17362
+ }
17363
+ return redacted.toString();
17364
+ }
16256
17365
  var LinkAuthResource = class {
16257
17366
  config;
16258
17367
  fetchImpl;
@@ -16262,12 +17371,9 @@ var LinkAuthResource = class {
16262
17371
  }
16263
17372
  async postForm(url, params) {
16264
17373
  if (this.config.verbose) {
16265
- const redacted = { ...params };
16266
- if (redacted.device_code) redacted.device_code = "<redacted>";
16267
- if (redacted.refresh_token) redacted.refresh_token = "<redacted>";
16268
17374
  this.config.logger.debug(
16269
17375
  `> POST ${url}
16270
- ${JSON.stringify(redacted, null, 2)}`
17376
+ ${serializeRedactedFormBody(params)}`
16271
17377
  );
16272
17378
  }
16273
17379
  let response;
@@ -16278,7 +17384,7 @@ ${JSON.stringify(redacted, null, 2)}`
16278
17384
  ...this.config.defaultHeaders,
16279
17385
  "Content-Type": "application/x-www-form-urlencoded"
16280
17386
  },
16281
- body: new URLSearchParams(params).toString()
17387
+ body: serializeFormBody(params)
16282
17388
  });
16283
17389
  } catch (error) {
16284
17390
  throw new LinkTransportError(`Request failed: POST ${url}`, {
@@ -16300,16 +17406,12 @@ ${JSON.stringify(redacted, null, 2)}`
16300
17406
  }
16301
17407
  return { status: response.status, data, rawBody };
16302
17408
  }
16303
- async initiateDeviceAuth(clientName) {
16304
- const effectiveName = clientName ?? this.config.clientName;
17409
+ async initiateDeviceAuth(options = {}) {
17410
+ const effectiveName = options.clientName ?? this.config.clientName;
17411
+ const params = buildDeviceCodeForm(effectiveName, options);
16305
17412
  const { status, data, rawBody } = await this.postForm(
16306
17413
  `${this.config.authBaseUrl}/device/code`,
16307
- {
16308
- client_id: CLIENT_ID,
16309
- scope: DEFAULT_SCOPE,
16310
- connection_label: `${effectiveName} on ${hostname()}`,
16311
- client_hint: effectiveName
16312
- }
17414
+ params
16313
17415
  );
16314
17416
  if (status < 200 || status >= 300) {
16315
17417
  throw new LinkApiError(
@@ -16488,6 +17590,9 @@ var ResourceFactory = class {
16488
17590
  paymentMethodsResource;
16489
17591
  shippingAddressResource;
16490
17592
  userInfoResource;
17593
+ transactionsResource;
17594
+ sourcesResource;
17595
+ balancesResource;
16491
17596
  webBotAuthResource;
16492
17597
  reportResource;
16493
17598
  constructor(options = {}) {
@@ -16602,6 +17707,48 @@ var ResourceFactory = class {
16602
17707
  );
16603
17708
  return this.userInfoResource;
16604
17709
  }
17710
+ createTransactionsResource() {
17711
+ if (this.transactionsResource) {
17712
+ return this.transactionsResource;
17713
+ }
17714
+ const getAccessToken = this.createSdkAccessTokenProvider();
17715
+ this.transactionsResource = sanitizeResource(
17716
+ new TransactionsResource({
17717
+ verbose: this.verbose,
17718
+ defaultHeaders: this.defaultHeaders,
17719
+ getAccessToken
17720
+ })
17721
+ );
17722
+ return this.transactionsResource;
17723
+ }
17724
+ createSourcesResource() {
17725
+ if (this.sourcesResource) {
17726
+ return this.sourcesResource;
17727
+ }
17728
+ const getAccessToken = this.createSdkAccessTokenProvider();
17729
+ this.sourcesResource = sanitizeResource(
17730
+ new SourcesResource({
17731
+ verbose: this.verbose,
17732
+ defaultHeaders: this.defaultHeaders,
17733
+ getAccessToken
17734
+ })
17735
+ );
17736
+ return this.sourcesResource;
17737
+ }
17738
+ createBalancesResource() {
17739
+ if (this.balancesResource) {
17740
+ return this.balancesResource;
17741
+ }
17742
+ const getAccessToken = this.createSdkAccessTokenProvider();
17743
+ this.balancesResource = sanitizeResource(
17744
+ new BalancesResource({
17745
+ verbose: this.verbose,
17746
+ defaultHeaders: this.defaultHeaders,
17747
+ getAccessToken
17748
+ })
17749
+ );
17750
+ return this.balancesResource;
17751
+ }
16605
17752
  createWebBotAuthResource() {
16606
17753
  if (this.webBotAuthResource) {
16607
17754
  return this.webBotAuthResource;
@@ -16703,12 +17850,16 @@ function cacheUpdateInfo(value, ttlMs = UPDATE_CACHE_TTL_MS) {
16703
17850
  }
16704
17851
 
16705
17852
  // src/cli.tsx
16706
- var cliVersion = "0.8.2";
17853
+ var cliVersion = "0.9.0";
16707
17854
  var cliName = "@stripe/link-cli";
16708
17855
  var defaultHeaders = {
16709
17856
  "User-Agent": `link-cli/${cliVersion}`
16710
17857
  };
16711
- var verbose = process.argv.includes("--verbose");
17858
+ var verboseIndex = process.argv.indexOf("--verbose");
17859
+ var verbose = verboseIndex !== -1;
17860
+ if (verboseIndex !== -1) {
17861
+ process.argv.splice(verboseIndex, 1);
17862
+ }
16712
17863
  var authFileIndex = process.argv.indexOf("--auth");
16713
17864
  var credentialFilePath = authFileIndex !== -1 ? process.argv[authFileIndex + 1] : process.env.LINK_AUTH_FILE;
16714
17865
  if (authFileIndex !== -1) {
@@ -16728,7 +17879,24 @@ var factory = new ResourceFactory({
16728
17879
  });
16729
17880
  var authRepo = factory.createAuthResource();
16730
17881
  var spendRequestRepo = factory.createSpendRequestResource();
16731
- var cli = Cli11.create("link-cli", {
17882
+ var requestedCommand = process.argv[2];
17883
+ var hiddenCli = requestedCommand === "transactions" ? createTransactionsCli(
17884
+ () => factory.createTransactionsResource(),
17885
+ authStorage,
17886
+ envAccessToken
17887
+ ) : requestedCommand === "sources" ? createSourcesCli(
17888
+ () => factory.createSourcesResource(),
17889
+ authStorage,
17890
+ envAccessToken
17891
+ ) : requestedCommand === "balances" ? createBalancesCli(
17892
+ () => factory.createBalancesResource(),
17893
+ authStorage,
17894
+ envAccessToken
17895
+ ) : null;
17896
+ if (hiddenCli) {
17897
+ process.argv.splice(2, 1);
17898
+ }
17899
+ var cli = hiddenCli ?? Cli14.create("link-cli", {
16732
17900
  description: "Create a secure, one-time payment credential from a Link wallet to let agents complete purchases on behalf of users.",
16733
17901
  version: cliVersion
16734
17902
  });
@@ -16745,58 +17913,60 @@ if (!isAgent && process.stdout.isTTY) {
16745
17913
  process.stderr.write(renderInteractiveUpdateNotice(updateInfo));
16746
17914
  }
16747
17915
  }
16748
- cli.command(
16749
- createAuthCli(authRepo, getUpdateInfo, authStorage, envAccessToken)
16750
- );
16751
- cli.command(
16752
- createSpendRequestCli(spendRequestRepo, authStorage, envAccessToken)
16753
- );
16754
- cli.command(
16755
- createPaymentMethodsCli(
16756
- () => factory.createPaymentMethodsResource(),
16757
- authStorage,
16758
- envAccessToken
16759
- )
16760
- );
16761
- cli.command(
16762
- createShippingAddressCli(
16763
- () => factory.createShippingAddressResource(),
16764
- authStorage,
16765
- envAccessToken
16766
- )
16767
- );
16768
- cli.command(
16769
- createUserInfoCli(
16770
- () => factory.createUserInfoResource(),
16771
- authStorage,
16772
- envAccessToken
16773
- )
16774
- );
16775
- cli.command(createMppCli(spendRequestRepo, authStorage, envAccessToken));
16776
- cli.command(
16777
- createReportCli(
16778
- () => factory.createReportResource(),
16779
- authStorage,
16780
- envAccessToken
16781
- )
16782
- );
16783
- cli.command(
16784
- createDemoCli(
16785
- authRepo,
16786
- spendRequestRepo,
16787
- () => factory.createPaymentMethodsResource(),
16788
- authStorage
16789
- )
16790
- );
16791
- cli.command(
16792
- createOnboardCli(
16793
- authRepo,
16794
- spendRequestRepo,
16795
- () => factory.createPaymentMethodsResource(),
16796
- authStorage
16797
- )
16798
- );
16799
- cli.command(createServeCli(cli));
17916
+ if (!hiddenCli) {
17917
+ cli.command(
17918
+ createAuthCli(authRepo, getUpdateInfo, authStorage, envAccessToken)
17919
+ );
17920
+ cli.command(
17921
+ createSpendRequestCli(spendRequestRepo, authStorage, envAccessToken)
17922
+ );
17923
+ cli.command(
17924
+ createPaymentMethodsCli(
17925
+ () => factory.createPaymentMethodsResource(),
17926
+ authStorage,
17927
+ envAccessToken
17928
+ )
17929
+ );
17930
+ cli.command(
17931
+ createShippingAddressCli(
17932
+ () => factory.createShippingAddressResource(),
17933
+ authStorage,
17934
+ envAccessToken
17935
+ )
17936
+ );
17937
+ cli.command(
17938
+ createUserInfoCli(
17939
+ () => factory.createUserInfoResource(),
17940
+ authStorage,
17941
+ envAccessToken
17942
+ )
17943
+ );
17944
+ cli.command(createMppCli(spendRequestRepo, authStorage, envAccessToken));
17945
+ cli.command(
17946
+ createReportCli(
17947
+ () => factory.createReportResource(),
17948
+ authStorage,
17949
+ envAccessToken
17950
+ )
17951
+ );
17952
+ cli.command(
17953
+ createDemoCli(
17954
+ authRepo,
17955
+ spendRequestRepo,
17956
+ () => factory.createPaymentMethodsResource(),
17957
+ authStorage
17958
+ )
17959
+ );
17960
+ cli.command(
17961
+ createOnboardCli(
17962
+ authRepo,
17963
+ spendRequestRepo,
17964
+ () => factory.createPaymentMethodsResource(),
17965
+ authStorage
17966
+ )
17967
+ );
17968
+ cli.command(createServeCli(cli));
17969
+ }
16800
17970
  cli.serve();
16801
17971
  var cli_default = cli;
16802
17972
  export {