@stripe/link-cli 0.8.3 → 0.10.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 +16 -2
  2. package/dist/cli.js +1934 -966
  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 z11 = 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${z11} <${+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${z11} <${M}.${+m + 1}.0-0`;
8848
+ ret = `>=${M}.${m}.0${z13} <${M}.${+m + 1}.0-0`;
8849
8849
  } else {
8850
- ret = `>=${M}.${m}.0${z11} <${+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}${z11} <${M}.${m}.${+p + 1}-0`;
8867
+ ret = `>=${M}.${m}.${p}${z13} <${M}.${m}.${+p + 1}-0`;
8868
8868
  } else {
8869
- ret = `>=${M}.${m}.${p}${z11} <${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,178 @@ 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.sources !== void 0) {
11286
+ for (const source of params.sources) {
11287
+ url.searchParams.append("sources[]", source);
11288
+ }
11289
+ }
11290
+ if (params.limit !== void 0) {
11291
+ url.searchParams.set("limit", String(params.limit));
11292
+ }
11293
+ if (params.starting_after !== void 0) {
11294
+ url.searchParams.set("starting_after", params.starting_after);
11295
+ }
11296
+ if (params.ending_before !== void 0) {
11297
+ url.searchParams.set("ending_before", params.ending_before);
11298
+ }
11299
+ return url.toString();
11300
+ }
11301
+ list(params = {}) {
11302
+ return this.listBalances(params);
11303
+ }
11304
+ async listBalances(params = {}) {
11305
+ const { status, data, rawBody } = await this.apiFetch({
11306
+ method: "GET",
11307
+ url: this.buildUrl(params)
11308
+ });
11309
+ if (status < 200 || status >= 300) {
11310
+ this.throwApiError("list balances", status, data, rawBody);
11311
+ }
11312
+ try {
11313
+ return normalizeBalancesPage(data);
11314
+ } catch (error) {
11315
+ const reason = error instanceof Error ? `: ${error.message}` : "";
11316
+ throw new LinkApiError(
11317
+ `Failed to list balances (${status}): invalid response shape${reason}`,
11318
+ { status, rawBody, details: data, cause: error }
11319
+ );
11320
+ }
11321
+ }
11322
+ };
11151
11323
  var PaymentMethodsResource = class {
11152
11324
  verbose;
11153
11325
  getAccessToken;
@@ -11318,6 +11490,68 @@ var ShippingAddressResource = class {
11318
11490
  return body?.shipping_addresses ?? [];
11319
11491
  }
11320
11492
  };
11493
+ function normalizeSources(value) {
11494
+ if (!Array.isArray(value)) {
11495
+ throw new TypeError("Expected sources to be an array");
11496
+ }
11497
+ return value.map((item, index) => {
11498
+ if (!isRecord(item)) {
11499
+ throw new TypeError(`Expected sources[${index}] to be an object`);
11500
+ }
11501
+ return item;
11502
+ });
11503
+ }
11504
+ function normalizeSourcesPage(value) {
11505
+ if (!isRecord(value)) {
11506
+ throw new TypeError("Expected response body to be an object");
11507
+ }
11508
+ const { data, has_more, ...rest } = value;
11509
+ const normalized = normalizeSources(data);
11510
+ return {
11511
+ ...rest,
11512
+ data: normalized,
11513
+ ...has_more !== void 0 ? { has_more: requireBoolean(has_more, "has_more") } : {}
11514
+ };
11515
+ }
11516
+ var SourcesResource = class extends BaseResource {
11517
+ constructor(options = {}) {
11518
+ super(options, "/sources");
11519
+ }
11520
+ buildUrl(params) {
11521
+ const url = new URL(this.endpoint);
11522
+ if (params.limit !== void 0) {
11523
+ url.searchParams.set("limit", String(params.limit));
11524
+ }
11525
+ if (params.starting_after !== void 0) {
11526
+ url.searchParams.set("starting_after", params.starting_after);
11527
+ }
11528
+ if (params.ending_before !== void 0) {
11529
+ url.searchParams.set("ending_before", params.ending_before);
11530
+ }
11531
+ return url.toString();
11532
+ }
11533
+ list(params = {}) {
11534
+ return this.listSources(params);
11535
+ }
11536
+ async listSources(params = {}) {
11537
+ const { status, data, rawBody } = await this.apiFetch({
11538
+ method: "GET",
11539
+ url: this.buildUrl(params)
11540
+ });
11541
+ if (status < 200 || status >= 300) {
11542
+ this.throwApiError("list sources", status, data, rawBody);
11543
+ }
11544
+ try {
11545
+ return normalizeSourcesPage(data);
11546
+ } catch (error) {
11547
+ const reason = error instanceof Error ? `: ${error.message}` : "";
11548
+ throw new LinkApiError(
11549
+ `Failed to list sources (${status}): invalid response shape${reason}`,
11550
+ { status, rawBody, details: data, cause: error }
11551
+ );
11552
+ }
11553
+ }
11554
+ };
11321
11555
  function normalizeSpendRequest(data) {
11322
11556
  const sr = data;
11323
11557
  if (typeof sr.shared_payment_token === "string") {
@@ -11524,9 +11758,6 @@ var SpendRequestResource = class {
11524
11758
  return normalizeSpendRequest(data);
11525
11759
  }
11526
11760
  };
11527
- function isRecord(value) {
11528
- return value !== null && typeof value === "object" && !Array.isArray(value);
11529
- }
11530
11761
  function requireString(value, field) {
11531
11762
  if (typeof value !== "string") {
11532
11763
  throw new TypeError(`Expected ${field} to be a string`);
@@ -11548,12 +11779,6 @@ function requireNumber(value, field) {
11548
11779
  }
11549
11780
  return value;
11550
11781
  }
11551
- function requireBoolean(value, field) {
11552
- if (typeof value !== "boolean") {
11553
- throw new TypeError(`Expected ${field} to be a boolean`);
11554
- }
11555
- return value;
11556
- }
11557
11782
  function requireTransactionOrigin(value, field) {
11558
11783
  if (value === "link" || value === "external_connection") {
11559
11784
  return value;
@@ -11611,71 +11836,9 @@ function normalizeTransactionsPage(value) {
11611
11836
  ...has_more !== void 0 ? { has_more: requireBoolean(has_more, "has_more") } : {}
11612
11837
  };
11613
11838
  }
11614
- var TransactionsResource = class {
11615
- verbose;
11616
- getAccessToken;
11617
- fetchImpl;
11618
- endpoint;
11619
- logger;
11839
+ var TransactionsResource = class extends BaseResource {
11620
11840
  constructor(options = {}) {
11621
- const config = resolveLinkSdkConfig(options);
11622
- this.verbose = config.verbose;
11623
- this.getAccessToken = config.getAccessToken;
11624
- this.fetchImpl = requireFetchImplementation(config);
11625
- this.endpoint = `${config.apiBaseUrl}/transactions`;
11626
- this.logger = config.logger;
11627
- }
11628
- async rawFetch(opts) {
11629
- if (this.verbose) {
11630
- const redactedHeaders = { ...opts.headers };
11631
- if (redactedHeaders.Authorization)
11632
- redactedHeaders.Authorization = "Bearer <redacted>";
11633
- this.logger.debug(`> ${opts.method} ${opts.url}`);
11634
- this.logger.debug(` Headers: ${JSON.stringify(redactedHeaders)}`);
11635
- }
11636
- let response;
11637
- try {
11638
- response = await this.fetchImpl(opts.url, {
11639
- method: opts.method,
11640
- headers: opts.headers
11641
- });
11642
- } catch (error) {
11643
- throw new LinkTransportError(
11644
- `Request failed: ${opts.method} ${opts.url}`,
11645
- { cause: error }
11646
- );
11647
- }
11648
- const rawBody = await response.text();
11649
- let data = null;
11650
- try {
11651
- data = JSON.parse(rawBody);
11652
- } catch {
11653
- }
11654
- if (this.verbose) {
11655
- this.logger.debug(`< ${response.status} ${response.statusText}`);
11656
- response.headers.forEach((value, key) => {
11657
- this.logger.debug(` ${key}: ${value}`);
11658
- });
11659
- this.logger.debug(rawBody);
11660
- }
11661
- return { status: response.status, data, rawBody };
11662
- }
11663
- async apiFetch(opts) {
11664
- const token = await this.getAccessToken();
11665
- const authedOpts = {
11666
- ...opts,
11667
- headers: {
11668
- ...opts.headers,
11669
- Authorization: `Bearer ${token}`
11670
- }
11671
- };
11672
- const res = await this.rawFetch(authedOpts);
11673
- if (res.status === 401) {
11674
- const refreshedToken = await this.getAccessToken({ forceRefresh: true });
11675
- authedOpts.headers.Authorization = `Bearer ${refreshedToken}`;
11676
- return this.rawFetch(authedOpts);
11677
- }
11678
- return res;
11841
+ super(options, "/transactions");
11679
11842
  }
11680
11843
  buildUrl(params) {
11681
11844
  const url = new URL(this.endpoint);
@@ -11716,19 +11879,14 @@ var TransactionsResource = class {
11716
11879
  url: this.buildUrl(params)
11717
11880
  });
11718
11881
  if (status < 200 || status >= 300) {
11719
- const body = data;
11720
- const msg = body?.error ?? body?.message ?? (rawBody || "unknown error");
11721
- throw new LinkApiError(
11722
- `Failed to list transactions (${status}): ${msg}`,
11723
- { status, rawBody, details: data }
11724
- );
11882
+ this.throwApiError("list transactions", status, data, rawBody);
11725
11883
  }
11726
11884
  try {
11727
11885
  return normalizeTransactionsPage(data);
11728
11886
  } catch (error) {
11729
11887
  const reason = error instanceof Error ? `: ${error.message}` : "";
11730
11888
  throw new LinkApiError(
11731
- `Failed to list transactions (200): invalid response shape${reason}`,
11889
+ `Failed to list transactions (${status}): invalid response shape${reason}`,
11732
11890
  { status, rawBody, details: data, cause: error }
11733
11891
  );
11734
11892
  }
@@ -11826,6 +11984,12 @@ var UserInfoResource = class {
11826
11984
  };
11827
11985
  }
11828
11986
  };
11987
+ var SOURCE_ACTIONS = [
11988
+ "read_balances",
11989
+ "read_external_transactions",
11990
+ "read_link_transactions",
11991
+ "read_source_details"
11992
+ ];
11829
11993
  var REPORT_OUTCOMES = ["success", "blocked", "abandoned"];
11830
11994
  var REPORT_TAGS = [
11831
11995
  "stripe_checkout",
@@ -12053,12 +12217,69 @@ var ReportResource = class {
12053
12217
  };
12054
12218
 
12055
12219
  // src/cli.tsx
12056
- import { Cli as Cli12 } from "incur";
12220
+ import { Cli as Cli14 } from "incur";
12057
12221
 
12058
12222
  // src/commands/auth/index.tsx
12059
12223
  import { Cli } from "incur";
12060
12224
  import { Text as Text4 } from "ink";
12061
12225
 
12226
+ // src/auth/authorization-details.ts
12227
+ var INVALID_AUTHORIZATION_DETAIL_MESSAGE = "authorization-detail must be valid JSON";
12228
+ function dedupe(values) {
12229
+ const seen = /* @__PURE__ */ new Set();
12230
+ const result = [];
12231
+ for (const value of values) {
12232
+ if (seen.has(value)) {
12233
+ continue;
12234
+ }
12235
+ seen.add(value);
12236
+ result.push(value);
12237
+ }
12238
+ return result;
12239
+ }
12240
+ function parseAuthorizationDetails(entries) {
12241
+ const parsed = [];
12242
+ for (const entry of entries ?? []) {
12243
+ try {
12244
+ parsed.push(JSON.parse(entry));
12245
+ } catch {
12246
+ throw new Error(INVALID_AUTHORIZATION_DETAIL_MESSAGE);
12247
+ }
12248
+ }
12249
+ return parsed;
12250
+ }
12251
+ function buildAuthorizationDetails(sourceActions, authorizationDetails) {
12252
+ const details = [];
12253
+ const uniqueSourceActions = dedupe(sourceActions ?? []);
12254
+ if (uniqueSourceActions.length > 0) {
12255
+ details.push({
12256
+ type: "source",
12257
+ actions: uniqueSourceActions
12258
+ });
12259
+ }
12260
+ if (authorizationDetails) {
12261
+ details.push(...authorizationDetails);
12262
+ }
12263
+ return details;
12264
+ }
12265
+
12266
+ // src/auth/scopes.ts
12267
+ var DEFAULT_SCOPES = [
12268
+ "userinfo:read",
12269
+ "payment_methods.agentic"
12270
+ ];
12271
+ var DEFAULT_SCOPE = DEFAULT_SCOPES.join(" ");
12272
+ function parseScopeTokens(scope) {
12273
+ return scope.trim().split(/\s+/).filter(Boolean);
12274
+ }
12275
+ function normalizeScopeInput(scope) {
12276
+ if (scope === void 0) {
12277
+ return void 0;
12278
+ }
12279
+ const normalized = parseScopeTokens(scope);
12280
+ return normalized.length > 0 ? normalized.join(" ") : void 0;
12281
+ }
12282
+
12062
12283
  // src/utils/poll-until.ts
12063
12284
  async function* pollUntil(options) {
12064
12285
  const { fn, isTerminal, interval, timeout, maxAttempts } = options;
@@ -12175,6 +12396,9 @@ import { jsx, jsxs } from "react/jsx-runtime";
12175
12396
  var Login = ({
12176
12397
  authResource,
12177
12398
  clientName,
12399
+ scope,
12400
+ sourceActions,
12401
+ authorizationDetails,
12178
12402
  authStorage: authStorage2 = storage,
12179
12403
  onComplete
12180
12404
  }) => {
@@ -12195,7 +12419,12 @@ var Login = ({
12195
12419
  useEffect(() => {
12196
12420
  const initAuth = async () => {
12197
12421
  try {
12198
- const authRequest = await authResource.initiateDeviceAuth(clientName);
12422
+ const authRequest = await authResource.initiateDeviceAuth({
12423
+ clientName,
12424
+ scope,
12425
+ sourceActions,
12426
+ authorizationDetails
12427
+ });
12199
12428
  setUserCode(authRequest.user_code);
12200
12429
  setVerificationUrl(authRequest.verification_url_complete);
12201
12430
  setDeviceCode(authRequest.device_code);
@@ -12206,7 +12435,7 @@ var Login = ({
12206
12435
  }
12207
12436
  };
12208
12437
  initAuth();
12209
- }, [authResource, clientName]);
12438
+ }, [authResource, authorizationDetails, clientName, scope, sourceActions]);
12210
12439
  useEffect(() => {
12211
12440
  if (status !== "waiting" || !deviceCode) return;
12212
12441
  const startPolling = async () => {
@@ -12245,17 +12474,17 @@ var Login = ({
12245
12474
  if (status === "declined") {
12246
12475
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
12247
12476
  /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2717 Authorization failed" }),
12248
- Object.entries(scopeEligibility).map(([scope, info]) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
12477
+ Object.entries(scopeEligibility).map(([scope2, info]) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
12249
12478
  /* @__PURE__ */ jsxs(Text, { children: [
12250
12479
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
12251
- scope,
12480
+ scope2,
12252
12481
  ":"
12253
12482
  ] }),
12254
12483
  " ineligible",
12255
12484
  info.ineligibility_reasons.length > 0 ? ` (${info.ineligibility_reasons.join(", ")})` : ""
12256
12485
  ] }),
12257
12486
  info.description ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: info.description }) : null
12258
- ] }, scope))
12487
+ ] }, scope2))
12259
12488
  ] });
12260
12489
  }
12261
12490
  if (status === "error") {
@@ -12379,10 +12608,18 @@ var Logout = ({
12379
12608
 
12380
12609
  // src/commands/auth/schema.ts
12381
12610
  import { z } from "incur";
12611
+ var SOURCE_ACTIONS_DESCRIPTION = SOURCE_ACTIONS.join(", ");
12382
12612
  var loginOptions = z.object({
12383
12613
  clientName: z.string().default("Link CLI").describe(
12384
12614
  "Agent or app name shown in the Link app when approving the device connection"
12385
12615
  ),
12616
+ scope: z.string().optional().describe(
12617
+ "Optional space-separated Link scopes to request. Quote the value when passing multiple scopes."
12618
+ ),
12619
+ sourceActions: z.array(z.enum(SOURCE_ACTIONS)).default([]).describe(
12620
+ `Source action to request via authorization_details (repeatable). Accepted values: ${SOURCE_ACTIONS_DESCRIPTION}.`
12621
+ ),
12622
+ authorizationDetail: z.array(z.string()).default([]).describe("Freeform authorization_details entry as raw JSON (repeatable)."),
12386
12623
  interval: z.coerce.number().default(0).describe(
12387
12624
  "Poll interval in seconds. When > 0, polls until authenticated or timeout is reached, yielding status on each attempt."
12388
12625
  ),
@@ -12538,12 +12775,30 @@ function createAuthCli(authResource, getUpdateInfo2, authStorage2, envAccessToke
12538
12775
  outputPolicy: "agent-only",
12539
12776
  async *run(c) {
12540
12777
  const clientName = c.options.clientName?.trim();
12778
+ const scope = normalizeScopeInput(c.options.scope);
12779
+ let authorizationDetails;
12541
12780
  if (!clientName || clientName.length === 0) {
12542
12781
  return c.error({
12543
12782
  code: "INVALID_INPUT",
12544
12783
  message: "client-name must be a non-empty string"
12545
12784
  });
12546
12785
  }
12786
+ if (c.options.scope !== void 0 && !scope) {
12787
+ return c.error({
12788
+ code: "INVALID_INPUT",
12789
+ message: "scope must be a non-empty string when provided"
12790
+ });
12791
+ }
12792
+ try {
12793
+ authorizationDetails = parseAuthorizationDetails(
12794
+ c.options.authorizationDetail
12795
+ );
12796
+ } catch (error) {
12797
+ return c.error({
12798
+ code: "INVALID_INPUT",
12799
+ message: error.message
12800
+ });
12801
+ }
12547
12802
  const existingAuth = storage2.getAuth();
12548
12803
  if (existingAuth?.refresh_token) {
12549
12804
  try {
@@ -12575,6 +12830,9 @@ function createAuthCli(authResource, getUpdateInfo2, authStorage2, envAccessToke
12575
12830
  {
12576
12831
  authResource,
12577
12832
  clientName,
12833
+ scope,
12834
+ sourceActions: c.options.sourceActions,
12835
+ authorizationDetails,
12578
12836
  authStorage: storage2,
12579
12837
  onComplete: () => {
12580
12838
  }
@@ -12583,7 +12841,12 @@ function createAuthCli(authResource, getUpdateInfo2, authStorage2, envAccessToke
12583
12841
  () => ({ authenticated: true, token_type: "Bearer" })
12584
12842
  );
12585
12843
  }
12586
- const authRequest = await authResource.initiateDeviceAuth(clientName);
12844
+ const authRequest = await authResource.initiateDeviceAuth({
12845
+ clientName,
12846
+ scope,
12847
+ sourceActions: c.options.sourceActions,
12848
+ authorizationDetails
12849
+ });
12587
12850
  storage2.setPendingDeviceAuth({
12588
12851
  device_code: authRequest.device_code,
12589
12852
  interval: authRequest.interval,
@@ -12713,29 +12976,202 @@ function createAuthCli(authResource, getUpdateInfo2, authStorage2, envAccessToke
12713
12976
  return cli2;
12714
12977
  }
12715
12978
 
12979
+ // src/commands/balances/index.tsx
12980
+ import { Cli as Cli2 } from "incur";
12981
+
12982
+ // src/utils/require-auth.ts
12983
+ var NOT_AUTHENTICATED_ERROR = {
12984
+ code: "NOT_AUTHENTICATED",
12985
+ message: 'Not authenticated. Run "link-cli auth login" first.',
12986
+ cta: {
12987
+ commands: [{ command: "auth login", description: "Log in to Link" }]
12988
+ }
12989
+ };
12990
+ function requireAuth(authStorage2, envAccessToken2) {
12991
+ const store = authStorage2 ?? storage;
12992
+ return (c, next) => {
12993
+ if (!envAccessToken2 && !store.isAuthenticated()) {
12994
+ return c.error(NOT_AUTHENTICATED_ERROR);
12995
+ }
12996
+ return next();
12997
+ };
12998
+ }
12999
+ function requireAuthGuard(c, authStorage2, envAccessToken2) {
13000
+ const store = authStorage2 ?? storage;
13001
+ if (!envAccessToken2 && !store.isAuthenticated()) {
13002
+ c.error(NOT_AUTHENTICATED_ERROR);
13003
+ }
13004
+ }
13005
+
13006
+ // src/commands/balances/list.tsx
13007
+ import { Box as Box4, Text as Text5 } from "ink";
13008
+ import Spinner3 from "ink-spinner";
13009
+ import { useCallback as useCallback2 } from "react";
13010
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
13011
+ var COLUMN_GAP = " ";
13012
+ var SOURCE_ID_MIN = 16;
13013
+ var SOURCE_ID_MAX = 48;
13014
+ var TYPE_WIDTH = 12;
13015
+ var CURRENT_WIDTH = 15;
13016
+ var CURRENCY_WIDTH = 8;
13017
+ function truncateCell(value, width) {
13018
+ if (value.length <= width) {
13019
+ return value;
13020
+ }
13021
+ if (width <= 3) {
13022
+ return value.slice(0, width);
13023
+ }
13024
+ return `${value.slice(0, width - 3)}...`;
13025
+ }
13026
+ function formatCell(value, width) {
13027
+ return truncateCell(value, width).padEnd(width);
13028
+ }
13029
+ function formatCents(cents) {
13030
+ const dollars = Math.abs(cents) / 100;
13031
+ const formatted = `$${dollars.toFixed(2)}`;
13032
+ return cents < 0 ? `-${formatted}` : formatted;
13033
+ }
13034
+ function sourceIdWidth(balances) {
13035
+ if (balances.length === 0) return SOURCE_ID_MIN;
13036
+ const maxLen = Math.max(...balances.map((b) => (b.source_id ?? "").length));
13037
+ return Math.min(SOURCE_ID_MAX, Math.max(SOURCE_ID_MIN, maxLen));
13038
+ }
13039
+ var BalancesList = ({
13040
+ resource,
13041
+ params,
13042
+ onComplete
13043
+ }) => {
13044
+ const action = useCallback2(
13045
+ () => resource.listBalances(params),
13046
+ [resource, params]
13047
+ );
13048
+ const { status, data: page, error } = useAsyncAction(action, onComplete);
13049
+ const balances = page?.data ?? [];
13050
+ const nextCursor = page?.has_more && balances.length > 0 ? balances[balances.length - 1].source_id : null;
13051
+ const idWidth = sourceIdWidth(balances);
13052
+ const headerRow = [
13053
+ formatCell("Source ID", idWidth),
13054
+ formatCell("Balance type", TYPE_WIDTH),
13055
+ formatCell("Current balance", CURRENT_WIDTH),
13056
+ formatCell("Currency", CURRENCY_WIDTH)
13057
+ ].join(COLUMN_GAP);
13058
+ const separatorRow = "-".repeat(headerRow.length);
13059
+ const rows = balances.map(
13060
+ (balance) => [
13061
+ formatCell(balance.source_id ?? "-", idWidth),
13062
+ formatCell(balance.type ?? "-", TYPE_WIDTH),
13063
+ formatCell(
13064
+ balance.current != null ? formatCents(balance.current) : "-",
13065
+ CURRENT_WIDTH
13066
+ ),
13067
+ formatCell(balance.currency ?? "-", CURRENCY_WIDTH)
13068
+ ].join(COLUMN_GAP)
13069
+ );
13070
+ if (status === "loading") {
13071
+ return /* @__PURE__ */ jsx5(Box4, { children: /* @__PURE__ */ jsxs4(Text5, { color: "cyan", children: [
13072
+ /* @__PURE__ */ jsx5(Spinner3, { type: "dots" }),
13073
+ " Loading balances..."
13074
+ ] }) });
13075
+ }
13076
+ if (status === "error") {
13077
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
13078
+ /* @__PURE__ */ jsx5(Text5, { color: "red", children: "Failed to load balances" }),
13079
+ /* @__PURE__ */ jsx5(Text5, { color: "red", children: error })
13080
+ ] });
13081
+ }
13082
+ if (balances.length === 0) {
13083
+ return /* @__PURE__ */ jsx5(Box4, { children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "No balances found" }) });
13084
+ }
13085
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
13086
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Balances" }),
13087
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
13088
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: headerRow }),
13089
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: separatorRow }),
13090
+ rows.map((row, index) => /* @__PURE__ */ jsx5(Text5, { children: row }, balances[index].source_id ?? `balance-${index}`))
13091
+ ] }),
13092
+ page?.has_more !== void 0 ? /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
13093
+ /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
13094
+ "has_more: ",
13095
+ String(page.has_more)
13096
+ ] }),
13097
+ typeof nextCursor === "string" && nextCursor.length > 0 ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: `next page: --starting-after ${nextCursor}` }) : null
13098
+ ] }) : null
13099
+ ] });
13100
+ };
13101
+
13102
+ // src/commands/balances/schema.ts
13103
+ import { z as z2 } from "incur";
13104
+ var listOptions = z2.object({
13105
+ source: z2.array(z2.string()).default([]).describe("Filter by source ID. Repeat to include multiple sources."),
13106
+ limit: z2.coerce.number().int().positive().max(100).optional().describe("Maximum number of balances to return (1-100)."),
13107
+ startingAfter: z2.string().optional().describe("Cursor: return balances after this balance ID."),
13108
+ endingBefore: z2.string().optional().describe("Cursor: return balances before this balance ID.")
13109
+ });
13110
+
13111
+ // src/commands/balances/index.tsx
13112
+ import { jsx as jsx6 } from "react/jsx-runtime";
13113
+ function createBalancesCli(createResource, authStorage2, envAccessToken2) {
13114
+ const cli2 = Cli2.create("balances", {
13115
+ description: "List balances from your Link wallet"
13116
+ });
13117
+ cli2.command("list", {
13118
+ description: "List balances from your Link wallet",
13119
+ options: listOptions,
13120
+ outputPolicy: "agent-only",
13121
+ middleware: [requireAuth(authStorage2, envAccessToken2)],
13122
+ async run(c) {
13123
+ const opts = c.options;
13124
+ const resource = createResource();
13125
+ const params = {};
13126
+ if (opts.source.length > 0) params.sources = opts.source;
13127
+ if (opts.limit !== void 0) params.limit = opts.limit;
13128
+ if (opts.startingAfter !== void 0)
13129
+ params.starting_after = opts.startingAfter;
13130
+ if (opts.endingBefore !== void 0)
13131
+ params.ending_before = opts.endingBefore;
13132
+ if (!c.agent && !c.formatExplicit) {
13133
+ return renderInteractive(
13134
+ /* @__PURE__ */ jsx6(
13135
+ BalancesList,
13136
+ {
13137
+ resource,
13138
+ params,
13139
+ onComplete: () => {
13140
+ }
13141
+ }
13142
+ ),
13143
+ () => resource.listBalances(params)
13144
+ );
13145
+ }
13146
+ return resource.listBalances(params);
13147
+ }
13148
+ });
13149
+ return cli2;
13150
+ }
13151
+
12716
13152
  // src/commands/demo/index.tsx
12717
- import { Cli as Cli2, z as z2 } from "incur";
13153
+ import { Cli as Cli3, z as z3 } from "incur";
12718
13154
 
12719
13155
  // src/commands/demo/demo-runner.tsx
12720
- import { Box as Box8, Text as Text10, useApp, useInput as useInput4 } from "ink";
12721
- import { useCallback as useCallback2, useState as useState7 } from "react";
13156
+ import { Box as Box9, Text as Text11, useApp, useInput as useInput4 } from "ink";
13157
+ import { useCallback as useCallback3, useState as useState7 } from "react";
12722
13158
 
12723
13159
  // src/utils/markdown-text.tsx
12724
- import { Text as Text5 } from "ink";
12725
- import { jsx as jsx5 } from "react/jsx-runtime";
13160
+ import { Text as Text6 } from "ink";
13161
+ import { jsx as jsx7 } from "react/jsx-runtime";
12726
13162
  var MarkdownText = ({
12727
13163
  children,
12728
13164
  dimColor
12729
13165
  }) => {
12730
13166
  const parts = tokenize(children);
12731
- return /* @__PURE__ */ jsx5(Text5, { dimColor, children: parts.map((part) => {
13167
+ return /* @__PURE__ */ jsx7(Text6, { dimColor, children: parts.map((part) => {
12732
13168
  if (part.type === "bold") {
12733
- return /* @__PURE__ */ jsx5(Text5, { bold: true, children: part.text }, part.key);
13169
+ return /* @__PURE__ */ jsx7(Text6, { bold: true, children: part.text }, part.key);
12734
13170
  }
12735
13171
  if (part.type === "code") {
12736
- return /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: part.text }, part.key);
13172
+ return /* @__PURE__ */ jsx7(Text6, { color: "yellow", children: part.text }, part.key);
12737
13173
  }
12738
- return /* @__PURE__ */ jsx5(Text5, { children: part.text }, part.key);
13174
+ return /* @__PURE__ */ jsx7(Text6, { children: part.text }, part.key);
12739
13175
  }) });
12740
13176
  };
12741
13177
  function tokenize(input) {
@@ -12770,7 +13206,7 @@ function tokenize(input) {
12770
13206
  }
12771
13207
 
12772
13208
  // src/commands/spend-request/app-download-qr-codes.tsx
12773
- import { Box as Box4, Text as Text6 } from "ink";
13209
+ import { Box as Box5, Text as Text7 } from "ink";
12774
13210
  import { useMemo } from "react";
12775
13211
 
12776
13212
  // src/utils/render-qr-matrix.ts
@@ -12807,24 +13243,24 @@ function renderQrMatrix(url) {
12807
13243
  }
12808
13244
 
12809
13245
  // src/commands/spend-request/app-download-qr-codes.tsx
12810
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
13246
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
12811
13247
  var DOWNLOAD_URL = "https://link.com/download";
12812
13248
  var AppDownloadQrCodes = () => {
12813
13249
  const qrLines = useMemo(() => renderQrMatrix(DOWNLOAD_URL), []);
12814
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
12815
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Get the Link app to approve spend requests from your phone" }),
12816
- /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", alignItems: "flex-start", marginTop: 1, children: [
13250
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
13251
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "Get the Link app to approve spend requests from your phone" }),
13252
+ /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", alignItems: "flex-start", marginTop: 1, children: [
12817
13253
  qrLines.map((line, i) => (
12818
13254
  // biome-ignore lint/suspicious/noArrayIndexKey: stable static array
12819
- /* @__PURE__ */ jsx6(Text6, { children: line }, i)
13255
+ /* @__PURE__ */ jsx8(Text7, { children: line }, i)
12820
13256
  )),
12821
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: DOWNLOAD_URL })
13257
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: DOWNLOAD_URL })
12822
13258
  ] })
12823
13259
  ] });
12824
13260
  };
12825
13261
 
12826
13262
  // src/commands/demo/card-flow.tsx
12827
- import { Box as Box5, Text as Text7, useInput as useInput2 } from "ink";
13263
+ import { Box as Box6, Text as Text8, useInput as useInput2 } from "ink";
12828
13264
  import { useEffect as useEffect4, useRef as useRef2, useState as useState4 } from "react";
12829
13265
 
12830
13266
  // src/utils/poll-until-approved.ts
@@ -12989,7 +13425,7 @@ var ONBOARD = {
12989
13425
  };
12990
13426
 
12991
13427
  // src/commands/demo/card-flow.tsx
12992
- import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
13428
+ import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
12993
13429
  function formatPmLabel(pm) {
12994
13430
  return `${pm.card_details?.brand ?? pm.type} ****${pm.card_details?.last4 ?? ""}`;
12995
13431
  }
@@ -13173,22 +13609,22 @@ var CardFlow = ({
13173
13609
  ];
13174
13610
  return order.indexOf(step) > order.indexOf(target);
13175
13611
  };
13176
- const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs5(Text7, { dimColor: true, children: [
13612
+ const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
13177
13613
  "\n",
13178
13614
  ">",
13179
13615
  " ",
13180
13616
  label
13181
13617
  ] });
13182
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", gap: 1, children: [
13183
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: CARD_FLOW.title }),
13184
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13185
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", gap: 1, children: [
13186
- /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "[testmode]" }),
13187
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: DEMO_MERCHANT_URL })
13618
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", gap: 1, children: [
13619
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: CARD_FLOW.title }),
13620
+ /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13621
+ /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", gap: 1, children: [
13622
+ /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "[testmode]" }),
13623
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: DEMO_MERCHANT_URL })
13188
13624
  ] }),
13189
- /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.intro.description }),
13190
- /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
13191
- /* @__PURE__ */ jsx7(Text7, { children: "What happens:" }),
13625
+ /* @__PURE__ */ jsx9(MarkdownText, { children: CARD_FLOW.intro.description }),
13626
+ /* @__PURE__ */ jsxs6(Box6, { marginTop: 1, flexDirection: "column", children: [
13627
+ /* @__PURE__ */ jsx9(Text8, { children: "What happens:" }),
13192
13628
  CARD_FLOW.intro.steps.map((s, i) => {
13193
13629
  const doneAfter = [
13194
13630
  "pick-pm",
@@ -13204,17 +13640,17 @@ var CardFlow = ({
13204
13640
  ];
13205
13641
  const done = pastStep(doneAfter[i]);
13206
13642
  const active = !done && (step === activeFrom[i] || pastStep(activeFrom[i]));
13207
- return done ? /* @__PURE__ */ jsxs5(Text7, { dimColor: true, strikethrough: true, children: [
13643
+ return done ? /* @__PURE__ */ jsxs6(Text8, { dimColor: true, strikethrough: true, children: [
13208
13644
  " ",
13209
13645
  i + 1,
13210
13646
  ". ",
13211
13647
  s
13212
- ] }, s) : active ? /* @__PURE__ */ jsxs5(Text7, { bold: true, color: "cyan", children: [
13648
+ ] }, s) : active ? /* @__PURE__ */ jsxs6(Text8, { bold: true, color: "cyan", children: [
13213
13649
  " ",
13214
13650
  i + 1,
13215
13651
  ". ",
13216
13652
  s
13217
- ] }, s) : /* @__PURE__ */ jsxs5(Text7, { dimColor: true, children: [
13653
+ ] }, s) : /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
13218
13654
  " ",
13219
13655
  i + 1,
13220
13656
  ". ",
@@ -13224,45 +13660,45 @@ var CardFlow = ({
13224
13660
  ] }),
13225
13661
  step === "intro" && prompt(CARD_FLOW.intro.prompt)
13226
13662
  ] }),
13227
- step === "fetch-pm" && /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Fetching payment methods from your Link wallet..." }) }),
13228
- (step === "pick-pm" || step === "explain-pm") && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13229
- step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13230
- /* @__PURE__ */ jsx7(Text7, { children: "Which payment method should we use for the demo?" }),
13231
- /* @__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: [
13663
+ step === "fetch-pm" && /* @__PURE__ */ jsx9(Box6, { flexDirection: "column", children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Fetching payment methods from your Link wallet..." }) }),
13664
+ (step === "pick-pm" || step === "explain-pm") && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13665
+ step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13666
+ /* @__PURE__ */ jsx9(Text8, { children: "Which payment method should we use for the demo?" }),
13667
+ /* @__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: [
13232
13668
  ">",
13233
13669
  " ",
13234
13670
  formatPmLabel(pm),
13235
13671
  pm.is_default ? " (default)" : ""
13236
- ] }) : /* @__PURE__ */ jsxs5(Text7, { dimColor: true, children: [
13672
+ ] }) : /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
13237
13673
  " ",
13238
13674
  formatPmLabel(pm),
13239
13675
  pm.is_default ? " (default)" : ""
13240
13676
  ] }) }, pm.id)) }),
13241
- /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
13677
+ /* @__PURE__ */ jsx9(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
13242
13678
  ] }),
13243
- paymentMethod && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13244
- /* @__PURE__ */ jsxs5(Text7, { color: "green", children: [
13679
+ paymentMethod && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13680
+ /* @__PURE__ */ jsxs6(Text8, { color: "green", children: [
13245
13681
  "\u2713 Using ",
13246
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: pmLabel }),
13682
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: pmLabel }),
13247
13683
  paymentMethod.is_default ? " (default)" : ""
13248
13684
  ] }),
13249
13685
  step === "explain-pm" && prompt(CARD_FLOW.explainPm.prompt)
13250
13686
  ] })
13251
13687
  ] }),
13252
- step === "create-spend" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13253
- /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.createSpend.description }),
13254
- /* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text7, { color: "cyan", children: CARD_FLOW.createSpend.loading }) })
13688
+ step === "create-spend" && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13689
+ /* @__PURE__ */ jsx9(MarkdownText, { children: CARD_FLOW.createSpend.description }),
13690
+ /* @__PURE__ */ jsx9(Box6, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: CARD_FLOW.createSpend.loading }) })
13255
13691
  ] }),
13256
- (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13257
- /* @__PURE__ */ jsxs5(Text7, { color: "green", children: [
13692
+ (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13693
+ /* @__PURE__ */ jsxs6(Text8, { color: "green", children: [
13258
13694
  "\u2713 Spend request created (",
13259
13695
  spendRequest.id,
13260
13696
  ")"
13261
13697
  ] }),
13262
- step === "await-approval" && /* @__PURE__ */ jsxs5(Fragment, { children: [
13263
- /* @__PURE__ */ jsx7(Text7, { children: CARD_FLOW.approval.description }),
13264
- /* @__PURE__ */ jsxs5(
13265
- Box5,
13698
+ step === "await-approval" && /* @__PURE__ */ jsxs6(Fragment, { children: [
13699
+ /* @__PURE__ */ jsx9(Text8, { children: CARD_FLOW.approval.description }),
13700
+ /* @__PURE__ */ jsxs6(
13701
+ Box6,
13266
13702
  {
13267
13703
  flexDirection: "column",
13268
13704
  borderStyle: "round",
@@ -13271,21 +13707,21 @@ var CardFlow = ({
13271
13707
  paddingY: 1,
13272
13708
  marginTop: 1,
13273
13709
  children: [
13274
- /* @__PURE__ */ jsxs5(Text7, { children: [
13710
+ /* @__PURE__ */ jsxs6(Text8, { children: [
13275
13711
  "Approve at:",
13276
13712
  " ",
13277
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: approvalUrl })
13713
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
13278
13714
  ] }),
13279
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: CARD_FLOW.approval.browserHint })
13715
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: CARD_FLOW.approval.browserHint })
13280
13716
  ]
13281
13717
  }
13282
13718
  ),
13283
- /* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text7, { color: "cyan", children: CARD_FLOW.approval.loading }) })
13719
+ /* @__PURE__ */ jsx9(Box6, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: CARD_FLOW.approval.loading }) })
13284
13720
  ] }),
13285
- step === "approval-timeout" && /* @__PURE__ */ jsxs5(Fragment, { children: [
13286
- /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
13287
- /* @__PURE__ */ jsxs5(
13288
- Box5,
13721
+ step === "approval-timeout" && /* @__PURE__ */ jsxs6(Fragment, { children: [
13722
+ /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
13723
+ /* @__PURE__ */ jsxs6(
13724
+ Box6,
13289
13725
  {
13290
13726
  flexDirection: "column",
13291
13727
  borderStyle: "round",
@@ -13294,38 +13730,38 @@ var CardFlow = ({
13294
13730
  paddingY: 1,
13295
13731
  marginTop: 1,
13296
13732
  children: [
13297
- /* @__PURE__ */ jsxs5(Text7, { children: [
13733
+ /* @__PURE__ */ jsxs6(Text8, { children: [
13298
13734
  "Approve at:",
13299
13735
  " ",
13300
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: approvalUrl })
13736
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
13301
13737
  ] }),
13302
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Press [Enter] to open in browser" })
13738
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Press [Enter] to open in browser" })
13303
13739
  ]
13304
13740
  }
13305
13741
  ),
13306
- /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "r Retry polling q Quit demo" }) })
13742
+ /* @__PURE__ */ jsx9(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "r Retry polling q Quit demo" }) })
13307
13743
  ] })
13308
13744
  ] }),
13309
- (step === "show-card" || step === "open-url" || step === "done") && card && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13310
- /* @__PURE__ */ jsx7(Text7, { color: "green", children: "\u2713 Approved!" }),
13311
- /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.showCard.description }),
13312
- /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", paddingX: 2, marginTop: 1, children: /* @__PURE__ */ jsxs5(Text7, { children: [
13313
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Number " }),
13314
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: formatCardNumber(card.number) }),
13745
+ (step === "show-card" || step === "open-url" || step === "done") && card && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13746
+ /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u2713 Approved!" }),
13747
+ /* @__PURE__ */ jsx9(MarkdownText, { children: CARD_FLOW.showCard.description }),
13748
+ /* @__PURE__ */ jsx9(Box6, { flexDirection: "column", paddingX: 2, marginTop: 1, children: /* @__PURE__ */ jsxs6(Text8, { children: [
13749
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Number " }),
13750
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: formatCardNumber(card.number) }),
13315
13751
  " ",
13316
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Exp " }),
13317
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: formatExpiry(card.exp_month, card.exp_year) }),
13752
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Exp " }),
13753
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: formatExpiry(card.exp_month, card.exp_year) }),
13318
13754
  " ",
13319
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "CVC " }),
13320
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: card.cvc }),
13321
- card.billing_address?.postal_code && /* @__PURE__ */ jsxs5(Fragment, { children: [
13755
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "CVC " }),
13756
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: card.cvc }),
13757
+ card.billing_address?.postal_code && /* @__PURE__ */ jsxs6(Fragment, { children: [
13322
13758
  " ",
13323
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Zip " }),
13324
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: card.billing_address.postal_code })
13759
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Zip " }),
13760
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: card.billing_address.postal_code })
13325
13761
  ] }),
13326
- card.valid_until && /* @__PURE__ */ jsxs5(Fragment, { children: [
13762
+ card.valid_until && /* @__PURE__ */ jsxs6(Fragment, { children: [
13327
13763
  " ",
13328
- /* @__PURE__ */ jsxs5(Text7, { dimColor: true, children: [
13764
+ /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
13329
13765
  "expires",
13330
13766
  " ",
13331
13767
  new Date(card.valid_until).toLocaleTimeString([], {
@@ -13337,14 +13773,14 @@ var CardFlow = ({
13337
13773
  ] }) }),
13338
13774
  step === "show-card" && prompt(CARD_FLOW.showCard.prompt)
13339
13775
  ] }),
13340
- step === "done" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
13341
- /* @__PURE__ */ jsxs5(Text7, { color: "green", children: [
13776
+ step === "done" && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13777
+ /* @__PURE__ */ jsxs6(Text8, { color: "green", children: [
13342
13778
  "\u2713 ",
13343
13779
  CARD_FLOW.done.success
13344
13780
  ] }),
13345
- /* @__PURE__ */ jsx7(Text7, { children: CARD_FLOW.done.detail })
13781
+ /* @__PURE__ */ jsx9(Text8, { children: CARD_FLOW.done.detail })
13346
13782
  ] }),
13347
- step === "error" && /* @__PURE__ */ jsxs5(Text7, { color: "red", children: [
13783
+ step === "error" && /* @__PURE__ */ jsxs6(Text8, { color: "red", children: [
13348
13784
  "Error: ",
13349
13785
  error
13350
13786
  ] })
@@ -13352,7 +13788,7 @@ var CardFlow = ({
13352
13788
  };
13353
13789
 
13354
13790
  // src/commands/demo/spt-flow.tsx
13355
- import { Box as Box7, Text as Text9, useInput as useInput3 } from "ink";
13791
+ import { Box as Box8, Text as Text10, useInput as useInput3 } from "ink";
13356
13792
  import { useEffect as useEffect6, useRef as useRef3, useState as useState6 } from "react";
13357
13793
 
13358
13794
  // src/commands/mpp/decode.ts
@@ -13385,11 +13821,11 @@ function getMethodDetails(request) {
13385
13821
  }
13386
13822
  function resolveStripeChallenge(challenges) {
13387
13823
  const stripeChallenge = challenges.find(
13388
- (challenge) => challenge.method === "stripe" && challenge.intent === "charge"
13824
+ (challenge) => challenge.method === "stripe" && (challenge.intent === "charge" || challenge.intent === "session")
13389
13825
  );
13390
13826
  if (!stripeChallenge) {
13391
13827
  throw new Error(
13392
- "WWW-Authenticate header does not include a stripe charge challenge"
13828
+ "WWW-Authenticate header does not include a stripe charge or session challenge"
13393
13829
  );
13394
13830
  }
13395
13831
  if (typeof stripeChallenge.request !== "object" || stripeChallenge.request == null || Array.isArray(stripeChallenge.request)) {
@@ -13424,7 +13860,7 @@ function decodeStripeChallenge(challengeHeader) {
13424
13860
  id: challenge.id,
13425
13861
  realm: challenge.realm,
13426
13862
  method: "stripe",
13427
- intent: "charge",
13863
+ intent: challenge.intent,
13428
13864
  description: challenge.description,
13429
13865
  digest: challenge.digest,
13430
13866
  expires: challenge.expires,
@@ -13434,13 +13870,13 @@ function decodeStripeChallenge(challengeHeader) {
13434
13870
  }
13435
13871
 
13436
13872
  // src/commands/mpp/pay.tsx
13437
- import { Box as Box6, Text as Text8 } from "ink";
13438
- import Spinner3 from "ink-spinner";
13873
+ import { Box as Box7, Text as Text9 } from "ink";
13874
+ import Spinner4 from "ink-spinner";
13439
13875
  import { Credential, Method } from "mppx";
13440
13876
  import { Mppx, Transport } from "mppx/client";
13441
13877
  import { Methods as StripeMethods } from "mppx/stripe";
13442
13878
  import { useEffect as useEffect5, useState as useState5 } from "react";
13443
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
13879
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
13444
13880
  function buildHeaders(data, headers) {
13445
13881
  const result = {};
13446
13882
  if (data !== void 0) {
@@ -13469,8 +13905,19 @@ function createStripePaymentClient(spt) {
13469
13905
  });
13470
13906
  }
13471
13907
  });
13908
+ const stripeSession = Method.toClient(
13909
+ { ...StripeMethods.charge, intent: "session" },
13910
+ {
13911
+ async createCredential({ challenge }) {
13912
+ return Credential.serialize({
13913
+ challenge,
13914
+ payload: { action: "open", grantedToken: spt }
13915
+ });
13916
+ }
13917
+ }
13918
+ );
13472
13919
  return Mppx.create({
13473
- methods: [stripeCharge],
13920
+ methods: [stripeCharge, stripeSession],
13474
13921
  polyfill: false,
13475
13922
  transport: Transport.from({
13476
13923
  name: "stripe-http",
@@ -13488,7 +13935,7 @@ function createStripePaymentClient(spt) {
13488
13935
  })
13489
13936
  });
13490
13937
  }
13491
- async function runMppPay(url, spendRequestId, method, data, headers, repository) {
13938
+ async function runMppPayWithSpendRequest(url, spendRequestId, method, data, headers, repository) {
13492
13939
  const spendRequest = await repository.getSpendRequest(spendRequestId, {
13493
13940
  include: ["shared_payment_token"]
13494
13941
  });
@@ -13509,7 +13956,15 @@ async function runMppPay(url, spendRequestId, method, data, headers, repository)
13509
13956
  if (!spendRequest.shared_payment_token) {
13510
13957
  throw new Error("Spend request does not have a shared payment token");
13511
13958
  }
13512
- const spt = spendRequest.shared_payment_token.id;
13959
+ return payWithSpt(
13960
+ url,
13961
+ spendRequest.shared_payment_token.id,
13962
+ method,
13963
+ data,
13964
+ headers
13965
+ );
13966
+ }
13967
+ async function payWithSpt(url, spt, method, data, headers) {
13513
13968
  const httpMethod = method ?? (data !== void 0 ? "POST" : "GET");
13514
13969
  const requestHeaders = buildHeaders(data, headers);
13515
13970
  const initialResponse = await fetch(url, {
@@ -13529,7 +13984,102 @@ async function runMppPay(url, spendRequestId, method, data, headers, repository)
13529
13984
  Authorization: authHeader
13530
13985
  }
13531
13986
  });
13532
- return readPayResult(retryResponse);
13987
+ return readPayResult(retryResponse);
13988
+ }
13989
+ async function runMppPayFullFlow(opts) {
13990
+ const {
13991
+ url,
13992
+ method,
13993
+ data,
13994
+ headers,
13995
+ context,
13996
+ amountOverride,
13997
+ paymentMethodId,
13998
+ test,
13999
+ repository,
14000
+ paymentMethodsFactory,
14001
+ onStep,
14002
+ onApprovalUrl
14003
+ } = opts;
14004
+ const httpMethod = method ?? (data !== void 0 ? "POST" : "GET");
14005
+ const requestHeaders = buildHeaders(data, headers);
14006
+ onStep?.("probing");
14007
+ const probeResponse = await fetch(url, {
14008
+ method: httpMethod,
14009
+ body: data,
14010
+ headers: requestHeaders
14011
+ });
14012
+ if (probeResponse.status !== 402) {
14013
+ return readPayResult(probeResponse);
14014
+ }
14015
+ const wwwAuth = probeResponse.headers.get("www-authenticate");
14016
+ if (!wwwAuth) {
14017
+ throw new Error("URL returned 402 but no WWW-Authenticate header");
14018
+ }
14019
+ const decoded = decodeStripeChallenge(wwwAuth);
14020
+ const networkId = decoded.network_id;
14021
+ const challengeAmount = decoded.request_json.amount ? Number(decoded.request_json.amount) : void 0;
14022
+ const challengeCurrency = decoded.request_json.currency ?? "usd";
14023
+ const amount = amountOverride ?? challengeAmount;
14024
+ if (!amount) {
14025
+ throw new Error(
14026
+ "Could not determine amount from 402 challenge. Pass --amount explicitly."
14027
+ );
14028
+ }
14029
+ let pmId = paymentMethodId;
14030
+ if (!pmId) {
14031
+ onStep?.("creating");
14032
+ const pmResource = paymentMethodsFactory();
14033
+ const methods = await pmResource.list();
14034
+ if (!methods.length) {
14035
+ throw new Error(
14036
+ "No payment methods found. Add one with `link-cli payment-methods add`."
14037
+ );
14038
+ }
14039
+ pmId = methods[0].id;
14040
+ }
14041
+ onStep?.("creating");
14042
+ const spendRequest = await repository.createSpendRequest({
14043
+ payment_details: pmId,
14044
+ credential_type: "shared_payment_token",
14045
+ network_id: networkId,
14046
+ amount,
14047
+ currency: challengeCurrency,
14048
+ context,
14049
+ request_approval: true,
14050
+ test: test || void 0
14051
+ });
14052
+ onStep?.("approving");
14053
+ if (spendRequest.approval_url) {
14054
+ onApprovalUrl?.(spendRequest.approval_url);
14055
+ }
14056
+ const approved = await pollUntilApproved(repository, spendRequest.id);
14057
+ if (approved.status !== "approved") {
14058
+ throw new Error(
14059
+ `Spend request was not approved (status: ${approved.status})`
14060
+ );
14061
+ }
14062
+ onStep?.("signing");
14063
+ let withSpt = await repository.getSpendRequest(spendRequest.id, {
14064
+ include: ["shared_payment_token"]
14065
+ });
14066
+ for (let i = 0; i < 3 && withSpt && !withSpt.shared_payment_token; i++) {
14067
+ await new Promise((r) => setTimeout(r, 1e3));
14068
+ withSpt = await repository.getSpendRequest(spendRequest.id, {
14069
+ include: ["shared_payment_token"]
14070
+ });
14071
+ }
14072
+ if (!withSpt?.shared_payment_token) {
14073
+ throw new Error("Failed to retrieve shared payment token");
14074
+ }
14075
+ onStep?.("submitting");
14076
+ return payWithSpt(
14077
+ url,
14078
+ withSpt.shared_payment_token.id,
14079
+ method,
14080
+ data,
14081
+ headers
14082
+ );
13533
14083
  }
13534
14084
  function MppPay({
13535
14085
  url,
@@ -13537,66 +14087,55 @@ function MppPay({
13537
14087
  method,
13538
14088
  data,
13539
14089
  headers,
14090
+ context,
14091
+ amountOverride,
14092
+ paymentMethodId,
14093
+ test,
13540
14094
  repository,
14095
+ paymentMethodsFactory,
13541
14096
  onComplete
13542
14097
  }) {
13543
- const [step, setStep] = useState5("retrieving");
14098
+ const [step, setStep] = useState5(
14099
+ spendRequestId ? "signing" : "probing"
14100
+ );
13544
14101
  const [result, setResult] = useState5(null);
13545
14102
  const [error, setError] = useState5(null);
14103
+ const [approvalUrl, setApprovalUrl] = useState5(null);
13546
14104
  useEffect5(() => {
13547
14105
  (async () => {
13548
14106
  try {
13549
- setStep("retrieving");
13550
- const spendRequest = await repository.getSpendRequest(spendRequestId, {
13551
- include: ["shared_payment_token"]
13552
- });
13553
- if (!spendRequest) {
13554
- throw new Error(`Spend request ${spendRequestId} not found`);
13555
- }
13556
- if (spendRequest.credential_type !== "shared_payment_token") {
13557
- const type = spendRequest.credential_type ?? "card";
13558
- throw new Error(
13559
- `Spend request ${spendRequestId} must have credential_type 'shared_payment_token' (current: '${type}')`
14107
+ let payResult;
14108
+ if (spendRequestId) {
14109
+ setStep("signing");
14110
+ payResult = await runMppPayWithSpendRequest(
14111
+ url,
14112
+ spendRequestId,
14113
+ method,
14114
+ data,
14115
+ headers,
14116
+ repository
13560
14117
  );
13561
- }
13562
- if (spendRequest.status !== "approved") {
13563
- throw new Error(
13564
- `Spend request must be approved (current status: ${spendRequest.status})`
13565
- );
13566
- }
13567
- if (!spendRequest.shared_payment_token) {
13568
- throw new Error("Spend request does not have a shared payment token");
13569
- }
13570
- const spt = spendRequest.shared_payment_token.id;
13571
- const httpMethod = method ?? (data !== void 0 ? "POST" : "GET");
13572
- const requestHeaders = buildHeaders(data, headers);
13573
- setStep("probing");
13574
- const initialResponse = await fetch(url, {
13575
- method: httpMethod,
13576
- body: data,
13577
- headers: requestHeaders
13578
- });
13579
- if (initialResponse.status !== 402) {
13580
- const payResult2 = await readPayResult(initialResponse);
13581
- setResult(payResult2);
13582
- setStep("done");
13583
- onComplete(payResult2);
13584
- return;
13585
- }
13586
- setStep("signing");
13587
- const authHeader = await createStripePaymentClient(spt).createCredential(
13588
- initialResponse
13589
- );
13590
- setStep("submitting");
13591
- const retryResponse = await fetch(url, {
13592
- method: httpMethod,
13593
- body: data,
13594
- headers: {
13595
- ...requestHeaders,
13596
- Authorization: authHeader
14118
+ } else {
14119
+ if (!context) {
14120
+ throw new Error(
14121
+ "--context is required for the full MPP flow (min 100 chars)"
14122
+ );
13597
14123
  }
13598
- });
13599
- const payResult = await readPayResult(retryResponse);
14124
+ payResult = await runMppPayFullFlow({
14125
+ url,
14126
+ method,
14127
+ data,
14128
+ headers,
14129
+ context,
14130
+ amountOverride,
14131
+ paymentMethodId,
14132
+ test: test ?? false,
14133
+ repository,
14134
+ paymentMethodsFactory,
14135
+ onStep: setStep,
14136
+ onApprovalUrl: (u) => setApprovalUrl(u)
14137
+ });
14138
+ }
13600
14139
  setResult(payResult);
13601
14140
  setStep("done");
13602
14141
  onComplete(payResult);
@@ -13605,30 +14144,51 @@ function MppPay({
13605
14144
  onComplete(null);
13606
14145
  }
13607
14146
  })();
13608
- }, [url, spendRequestId, method, data, headers, repository, onComplete]);
14147
+ }, [
14148
+ url,
14149
+ spendRequestId,
14150
+ method,
14151
+ data,
14152
+ headers,
14153
+ context,
14154
+ amountOverride,
14155
+ paymentMethodId,
14156
+ test,
14157
+ repository,
14158
+ paymentMethodsFactory,
14159
+ onComplete
14160
+ ]);
13609
14161
  const stepLabels = {
13610
- retrieving: "Retrieving spend request",
13611
- probing: "Probing URL",
14162
+ probing: "Probing URL for 402 challenge",
14163
+ creating: "Creating spend request",
14164
+ approving: "Waiting for approval",
13612
14165
  signing: "Signing credential",
13613
14166
  submitting: "Submitting payment",
13614
14167
  done: "Done"
13615
14168
  };
13616
14169
  if (error) {
13617
- return /* @__PURE__ */ jsxs6(Text8, { color: "red", children: [
14170
+ return /* @__PURE__ */ jsxs7(Text9, { color: "red", children: [
13618
14171
  "Error: ",
13619
14172
  error
13620
14173
  ] });
13621
14174
  }
13622
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13623
- step !== "done" && /* @__PURE__ */ jsx8(Box6, { children: /* @__PURE__ */ jsxs6(Text8, { color: "cyan", children: [
13624
- /* @__PURE__ */ jsx8(Spinner3, { type: "dots" }),
13625
- " ",
13626
- stepLabels[step],
13627
- "..."
13628
- ] }) }),
13629
- result && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
13630
- /* @__PURE__ */ jsxs6(
13631
- Text8,
14175
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
14176
+ step !== "done" && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
14177
+ /* @__PURE__ */ jsx10(Box7, { children: /* @__PURE__ */ jsxs7(Text9, { color: "cyan", children: [
14178
+ /* @__PURE__ */ jsx10(Spinner4, { type: "dots" }),
14179
+ " ",
14180
+ stepLabels[step],
14181
+ "..."
14182
+ ] }) }),
14183
+ step === "approving" && approvalUrl && /* @__PURE__ */ jsx10(Box7, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs7(Text9, { children: [
14184
+ "Approve in Link app:",
14185
+ " ",
14186
+ /* @__PURE__ */ jsx10(Text9, { bold: true, color: "blue", children: approvalUrl })
14187
+ ] }) })
14188
+ ] }),
14189
+ result && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
14190
+ /* @__PURE__ */ jsxs7(
14191
+ Text9,
13632
14192
  {
13633
14193
  color: result.status >= 400 ? "red" : result.status >= 300 ? "yellow" : "green",
13634
14194
  children: [
@@ -13637,13 +14197,13 @@ function MppPay({
13637
14197
  ]
13638
14198
  }
13639
14199
  ),
13640
- /* @__PURE__ */ jsx8(Text8, { children: result.body })
14200
+ /* @__PURE__ */ jsx10(Text9, { children: result.body })
13641
14201
  ] })
13642
14202
  ] });
13643
14203
  }
13644
14204
 
13645
14205
  // src/commands/demo/spt-flow.tsx
13646
- import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
14206
+ import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
13647
14207
  var SptFlow = ({
13648
14208
  spendRequestRepo: spendRequestRepo2,
13649
14209
  paymentMethodsResource,
@@ -13792,7 +14352,7 @@ var SptFlow = ({
13792
14352
  setStep("mpp-pay-gate");
13793
14353
  await waitForEnter();
13794
14354
  setStep("mpp-pay");
13795
- const payResponse = await runMppPay(
14355
+ const payResponse = await runMppPayWithSpendRequest(
13796
14356
  DEMO_CLIMATE_API_URL,
13797
14357
  result.id,
13798
14358
  "POST",
@@ -13826,26 +14386,26 @@ var SptFlow = ({
13826
14386
  ];
13827
14387
  return order.indexOf(step) > order.indexOf(target);
13828
14388
  };
13829
- const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
14389
+ const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
13830
14390
  "\n",
13831
14391
  ">",
13832
14392
  " ",
13833
14393
  label
13834
14394
  ] });
13835
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", gap: 1, children: [
13836
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: SPT_FLOW.title }),
13837
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13838
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", gap: 1, children: [
13839
- /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "[testmode]" }),
13840
- /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
14395
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, children: [
14396
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "cyan", children: SPT_FLOW.title }),
14397
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14398
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "row", gap: 1, children: [
14399
+ /* @__PURE__ */ jsx11(Text10, { color: "yellow", children: "[testmode]" }),
14400
+ /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
13841
14401
  DEMO_CLIMATE_API_URL,
13842
14402
  " ",
13843
14403
  DEMO_MPP_DEV_URL
13844
14404
  ] })
13845
14405
  ] }),
13846
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.intro.description }),
13847
- /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
13848
- /* @__PURE__ */ jsx9(Text9, { children: SPT_FLOW.intro.preamble }),
14406
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.intro.description }),
14407
+ /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexDirection: "column", children: [
14408
+ /* @__PURE__ */ jsx11(Text10, { children: SPT_FLOW.intro.preamble }),
13849
14409
  SPT_FLOW.intro.steps.map((s, i) => {
13850
14410
  const doneAfter = [
13851
14411
  "pick-pm",
@@ -13864,17 +14424,17 @@ var SptFlow = ({
13864
14424
  const done = pastStep(doneAfter[i]);
13865
14425
  const active = !done && (step === activeFrom[i] || pastStep(activeFrom[i]));
13866
14426
  const label = s.replace(/`/g, "");
13867
- return done ? /* @__PURE__ */ jsxs7(Text9, { dimColor: true, strikethrough: true, children: [
14427
+ return done ? /* @__PURE__ */ jsxs8(Text10, { dimColor: true, strikethrough: true, children: [
13868
14428
  " ",
13869
14429
  i + 1,
13870
14430
  ". ",
13871
14431
  label
13872
- ] }, s) : active ? /* @__PURE__ */ jsxs7(Text9, { bold: true, color: "cyan", children: [
14432
+ ] }, s) : active ? /* @__PURE__ */ jsxs8(Text10, { bold: true, color: "cyan", children: [
13873
14433
  " ",
13874
14434
  i + 1,
13875
14435
  ". ",
13876
14436
  label
13877
- ] }, s) : /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
14437
+ ] }, s) : /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
13878
14438
  " ",
13879
14439
  i + 1,
13880
14440
  ". ",
@@ -13884,47 +14444,47 @@ var SptFlow = ({
13884
14444
  ] }),
13885
14445
  step === "intro" && prompt(SPT_FLOW.intro.prompt)
13886
14446
  ] }),
13887
- step === "fetch-pm" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "Fetching payment methods..." }) }),
13888
- step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13889
- /* @__PURE__ */ jsx9(Text9, { children: "Which payment method should we use for the demo?" }),
13890
- /* @__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: [
14447
+ step === "fetch-pm" && /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: "Fetching payment methods..." }) }),
14448
+ step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14449
+ /* @__PURE__ */ jsx11(Text10, { children: "Which payment method should we use for the demo?" }),
14450
+ /* @__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: [
13891
14451
  ">",
13892
14452
  " ",
13893
14453
  pm.card_details ? `${pm.card_details.brand} ****${pm.card_details.last4}` : pm.type,
13894
14454
  pm.is_default ? " (default)" : ""
13895
- ] }) : /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
14455
+ ] }) : /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
13896
14456
  " ",
13897
14457
  pm.card_details ? `${pm.card_details.brand} ****${pm.card_details.last4}` : pm.type,
13898
14458
  pm.is_default ? " (default)" : ""
13899
14459
  ] }) }, pm.id)) }),
13900
- /* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
14460
+ /* @__PURE__ */ jsx11(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
13901
14461
  ] }),
13902
- (step === "probe" || step === "explain-402") && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13903
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.probe.description }),
13904
- step === "probe" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: SPT_FLOW.probe.loading }) }),
13905
- step === "explain-402" && networkId && /* @__PURE__ */ jsxs7(Fragment2, { children: [
13906
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.probe.detail }),
13907
- /* @__PURE__ */ jsxs7(Text9, { color: "green", children: [
14462
+ (step === "probe" || step === "explain-402") && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14463
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.probe.description }),
14464
+ step === "probe" && /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: SPT_FLOW.probe.loading }) }),
14465
+ step === "explain-402" && networkId && /* @__PURE__ */ jsxs8(Fragment2, { children: [
14466
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.probe.detail }),
14467
+ /* @__PURE__ */ jsxs8(Text10, { color: "green", children: [
13908
14468
  "\u2713 Got HTTP 402 \u2014 network_id: ",
13909
- /* @__PURE__ */ jsx9(Text9, { bold: true, children: networkId })
14469
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: networkId })
13910
14470
  ] }),
13911
14471
  prompt(SPT_FLOW.probe.prompt)
13912
14472
  ] })
13913
14473
  ] }),
13914
- step === "create-spend" && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13915
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.createSpend.description }),
13916
- /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: SPT_FLOW.createSpend.loading }) })
14474
+ step === "create-spend" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14475
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.createSpend.description }),
14476
+ /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: SPT_FLOW.createSpend.loading }) })
13917
14477
  ] }),
13918
- (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13919
- /* @__PURE__ */ jsxs7(Text9, { color: "green", children: [
14478
+ (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14479
+ /* @__PURE__ */ jsxs8(Text10, { color: "green", children: [
13920
14480
  "\u2713 Spend request created (",
13921
14481
  spendRequest.id,
13922
14482
  ")"
13923
14483
  ] }),
13924
- step === "await-approval" && /* @__PURE__ */ jsxs7(Fragment2, { children: [
13925
- /* @__PURE__ */ jsx9(Text9, { children: SPT_FLOW.approval.description }),
13926
- /* @__PURE__ */ jsxs7(
13927
- Box7,
14484
+ step === "await-approval" && /* @__PURE__ */ jsxs8(Fragment2, { children: [
14485
+ /* @__PURE__ */ jsx11(Text10, { children: SPT_FLOW.approval.description }),
14486
+ /* @__PURE__ */ jsxs8(
14487
+ Box8,
13928
14488
  {
13929
14489
  flexDirection: "column",
13930
14490
  borderStyle: "round",
@@ -13933,21 +14493,21 @@ var SptFlow = ({
13933
14493
  paddingY: 1,
13934
14494
  marginTop: 1,
13935
14495
  children: [
13936
- /* @__PURE__ */ jsxs7(Text9, { children: [
14496
+ /* @__PURE__ */ jsxs8(Text10, { children: [
13937
14497
  "Approve at:",
13938
14498
  " ",
13939
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: approvalUrl })
14499
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "cyan", children: approvalUrl })
13940
14500
  ] }),
13941
- /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: SPT_FLOW.approval.browserHint })
14501
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: SPT_FLOW.approval.browserHint })
13942
14502
  ]
13943
14503
  }
13944
14504
  ),
13945
- /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: SPT_FLOW.approval.loading }) })
14505
+ /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: SPT_FLOW.approval.loading }) })
13946
14506
  ] }),
13947
- step === "approval-timeout" && /* @__PURE__ */ jsxs7(Fragment2, { children: [
13948
- /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
13949
- /* @__PURE__ */ jsxs7(
13950
- Box7,
14507
+ step === "approval-timeout" && /* @__PURE__ */ jsxs8(Fragment2, { children: [
14508
+ /* @__PURE__ */ jsx11(Text10, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
14509
+ /* @__PURE__ */ jsxs8(
14510
+ Box8,
13951
14511
  {
13952
14512
  flexDirection: "column",
13953
14513
  borderStyle: "round",
@@ -13956,35 +14516,35 @@ var SptFlow = ({
13956
14516
  paddingY: 1,
13957
14517
  marginTop: 1,
13958
14518
  children: [
13959
- /* @__PURE__ */ jsxs7(Text9, { children: [
14519
+ /* @__PURE__ */ jsxs8(Text10, { children: [
13960
14520
  "Approve at:",
13961
14521
  " ",
13962
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: approvalUrl })
14522
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "cyan", children: approvalUrl })
13963
14523
  ] }),
13964
- /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Press [Enter] to open in browser" })
14524
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "Press [Enter] to open in browser" })
13965
14525
  ]
13966
14526
  }
13967
14527
  ),
13968
- /* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "r Retry polling q Quit demo" }) })
14528
+ /* @__PURE__ */ jsx11(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "r Retry polling q Quit demo" }) })
13969
14529
  ] })
13970
14530
  ] }),
13971
- (step === "mpp-pay-gate" || step === "mpp-pay") && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13972
- /* @__PURE__ */ jsx9(Text9, { color: "green", children: "\u2713 Approved!" }),
13973
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.mppPay.description }),
14531
+ (step === "mpp-pay-gate" || step === "mpp-pay") && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14532
+ /* @__PURE__ */ jsx11(Text10, { color: "green", children: "\u2713 Approved!" }),
14533
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.mppPay.description }),
13974
14534
  step === "mpp-pay-gate" && prompt(SPT_FLOW.mppPay.prompt),
13975
- step === "mpp-pay" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: SPT_FLOW.mppPay.loading }) })
14535
+ step === "mpp-pay" && /* @__PURE__ */ jsx11(Box8, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "cyan", children: SPT_FLOW.mppPay.loading }) })
13976
14536
  ] }),
13977
- step === "done" && payResult && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
13978
- /* @__PURE__ */ jsxs7(Text9, { bold: true, color: "green", children: [
14537
+ step === "done" && payResult && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14538
+ /* @__PURE__ */ jsxs8(Text10, { bold: true, color: "green", children: [
13979
14539
  "\u2713 ",
13980
14540
  SPT_FLOW.done.success,
13981
14541
  " (HTTP ",
13982
14542
  payResult.status,
13983
14543
  ")"
13984
14544
  ] }),
13985
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.done.detail })
14545
+ /* @__PURE__ */ jsx11(MarkdownText, { children: SPT_FLOW.done.detail })
13986
14546
  ] }),
13987
- step === "error" && /* @__PURE__ */ jsxs7(Text9, { color: "red", children: [
14547
+ step === "error" && /* @__PURE__ */ jsxs8(Text10, { color: "red", children: [
13988
14548
  "Error: ",
13989
14549
  error
13990
14550
  ] })
@@ -13992,7 +14552,7 @@ var SptFlow = ({
13992
14552
  };
13993
14553
 
13994
14554
  // src/commands/demo/demo-runner.tsx
13995
- import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
14555
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
13996
14556
  var DemoRunner = ({
13997
14557
  authRepo: authRepo2,
13998
14558
  spendRequestRepo: spendRequestRepo2,
@@ -14034,7 +14594,7 @@ var DemoRunner = ({
14034
14594
  setPhase("spt-flow");
14035
14595
  }
14036
14596
  });
14037
- const onCardComplete = useCallback2(
14597
+ const onCardComplete = useCallback3(
14038
14598
  (result) => {
14039
14599
  setPaymentMethodId(result.paymentMethodId);
14040
14600
  setCardSuccess(result.success);
@@ -14050,7 +14610,7 @@ var DemoRunner = ({
14050
14610
  },
14051
14611
  [runSpt, onComplete, exit]
14052
14612
  );
14053
- const onSptComplete = useCallback2(
14613
+ const onSptComplete = useCallback3(
14054
14614
  (success) => {
14055
14615
  setSptSuccess(success);
14056
14616
  setPhase("summary");
@@ -14061,12 +14621,12 @@ var DemoRunner = ({
14061
14621
  },
14062
14622
  [onComplete, exit]
14063
14623
  );
14064
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, children: [
14065
- /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14066
- /* @__PURE__ */ jsx10(Text10, { bold: true, children: DEMO_MENU.title }),
14067
- /* @__PURE__ */ jsx10(Text10, { children: DEMO_MENU.subtitle })
14624
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, children: [
14625
+ /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14626
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: DEMO_MENU.title }),
14627
+ /* @__PURE__ */ jsx12(Text11, { children: DEMO_MENU.subtitle })
14068
14628
  ] }),
14069
- phase === "auth" && /* @__PURE__ */ jsx10(
14629
+ phase === "auth" && /* @__PURE__ */ jsx12(
14070
14630
  Login,
14071
14631
  {
14072
14632
  authResource: authRepo2,
@@ -14075,25 +14635,25 @@ var DemoRunner = ({
14075
14635
  onComplete: () => setPhase(postAuthPhase)
14076
14636
  }
14077
14637
  ),
14078
- phase === "menu" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14079
- /* @__PURE__ */ jsx10(Text10, { children: DEMO_MENU.question }),
14080
- /* @__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: [
14081
- /* @__PURE__ */ jsxs8(Text10, { color: "cyan", bold: true, children: [
14638
+ phase === "menu" && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14639
+ /* @__PURE__ */ jsx12(Text11, { children: DEMO_MENU.question }),
14640
+ /* @__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: [
14641
+ /* @__PURE__ */ jsxs9(Text11, { color: "cyan", bold: true, children: [
14082
14642
  ">",
14083
14643
  " ",
14084
14644
  opt.label
14085
14645
  ] }),
14086
- /* @__PURE__ */ jsxs8(Text10, { color: "cyan", children: [
14646
+ /* @__PURE__ */ jsxs9(Text11, { color: "cyan", children: [
14087
14647
  " ",
14088
14648
  opt.description
14089
14649
  ] })
14090
- ] }) : /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
14650
+ ] }) : /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
14091
14651
  " ",
14092
14652
  opt.label
14093
14653
  ] }) }, opt.key)) }),
14094
- /* @__PURE__ */ jsx10(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: DEMO_MENU.hint }) })
14654
+ /* @__PURE__ */ jsx12(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: DEMO_MENU.hint }) })
14095
14655
  ] }),
14096
- runCard && phase !== "menu" && /* @__PURE__ */ jsx10(
14656
+ runCard && phase !== "menu" && /* @__PURE__ */ jsx12(
14097
14657
  CardFlow,
14098
14658
  {
14099
14659
  spendRequestRepo: spendRequestRepo2,
@@ -14102,19 +14662,19 @@ var DemoRunner = ({
14102
14662
  onComplete: onCardComplete
14103
14663
  }
14104
14664
  ),
14105
- phase === "card-done" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14106
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\u2500\u2500\u2500" }),
14107
- /* @__PURE__ */ jsx10(MarkdownText, { children: DEMO_MENU.transition }),
14108
- /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
14665
+ phase === "card-done" && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14666
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "\u2500\u2500\u2500" }),
14667
+ /* @__PURE__ */ jsx12(MarkdownText, { children: DEMO_MENU.transition }),
14668
+ /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
14109
14669
  "\n",
14110
14670
  ">",
14111
14671
  " ",
14112
14672
  DEMO_MENU.transitionPrompt
14113
14673
  ] })
14114
14674
  ] }),
14115
- runSpt && (phase === "spt-flow" || phase === "summary") && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14116
- runCard && /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\u2500\u2500\u2500" }),
14117
- /* @__PURE__ */ jsx10(
14675
+ runSpt && (phase === "spt-flow" || phase === "summary") && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14676
+ runCard && /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "\u2500\u2500\u2500" }),
14677
+ /* @__PURE__ */ jsx12(
14118
14678
  SptFlow,
14119
14679
  {
14120
14680
  spendRequestRepo: spendRequestRepo2,
@@ -14124,30 +14684,30 @@ var DemoRunner = ({
14124
14684
  }
14125
14685
  )
14126
14686
  ] }),
14127
- phase === "summary" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
14128
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\u2500\u2500\u2500" }),
14129
- /* @__PURE__ */ jsx10(Text10, { bold: true, children: "Done!" }),
14130
- cardSuccess !== null && /* @__PURE__ */ jsxs8(Text10, { color: cardSuccess ? "green" : "red", children: [
14687
+ phase === "summary" && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14688
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "\u2500\u2500\u2500" }),
14689
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Done!" }),
14690
+ cardSuccess !== null && /* @__PURE__ */ jsxs9(Text11, { color: cardSuccess ? "green" : "red", children: [
14131
14691
  cardSuccess ? "\u2713" : "\u2717",
14132
14692
  " Virtual card flow"
14133
14693
  ] }),
14134
- sptSuccess !== null && /* @__PURE__ */ jsxs8(Text10, { color: sptSuccess ? "green" : "red", children: [
14694
+ sptSuccess !== null && /* @__PURE__ */ jsxs9(Text11, { color: sptSuccess ? "green" : "red", children: [
14135
14695
  sptSuccess ? "\u2713" : "\u2717",
14136
14696
  " Machine payment flow"
14137
14697
  ] }),
14138
- /* @__PURE__ */ jsx10(AppDownloadQrCodes, {})
14698
+ /* @__PURE__ */ jsx12(AppDownloadQrCodes, {})
14139
14699
  ] })
14140
14700
  ] });
14141
14701
  };
14142
14702
 
14143
14703
  // src/commands/demo/index.tsx
14144
- import { jsx as jsx11 } from "react/jsx-runtime";
14145
- var demoOptions = z2.object({
14146
- onlyCard: z2.boolean().default(false).describe("Run only the virtual card flow"),
14147
- onlySpt: z2.boolean().default(false).describe("Run only the machine payment (SPT) flow")
14704
+ import { jsx as jsx13 } from "react/jsx-runtime";
14705
+ var demoOptions = z3.object({
14706
+ onlyCard: z3.boolean().default(false).describe("Run only the virtual card flow"),
14707
+ onlySpt: z3.boolean().default(false).describe("Run only the machine payment (SPT) flow")
14148
14708
  });
14149
14709
  function createDemoCli(authRepo2, spendRequestRepo2, createPaymentMethodsResource, authStorage2) {
14150
- return Cli2.create("demo", {
14710
+ return Cli3.create("demo", {
14151
14711
  description: "Run an interactive demo of both Link payment flows (virtual card + machine payment)",
14152
14712
  options: demoOptions,
14153
14713
  outputPolicy: "agent-only",
@@ -14160,7 +14720,7 @@ function createDemoCli(authRepo2, spendRequestRepo2, createPaymentMethodsResourc
14160
14720
  }
14161
14721
  const paymentMethodsResource = createPaymentMethodsResource();
14162
14722
  return renderInteractive(
14163
- /* @__PURE__ */ jsx11(
14723
+ /* @__PURE__ */ jsx13(
14164
14724
  DemoRunner,
14165
14725
  {
14166
14726
  authRepo: authRepo2,
@@ -14180,91 +14740,77 @@ function createDemoCli(authRepo2, spendRequestRepo2, createPaymentMethodsResourc
14180
14740
  }
14181
14741
 
14182
14742
  // src/commands/mpp/index.tsx
14183
- import { Cli as Cli3, z as z4 } from "incur";
14184
-
14185
- // src/utils/require-auth.ts
14186
- var NOT_AUTHENTICATED_ERROR = {
14187
- code: "NOT_AUTHENTICATED",
14188
- message: 'Not authenticated. Run "link-cli auth login" first.',
14189
- cta: {
14190
- commands: [{ command: "auth login", description: "Log in to Link" }]
14191
- }
14192
- };
14193
- function requireAuth(authStorage2, envAccessToken2) {
14194
- const store = authStorage2 ?? storage;
14195
- return (c, next) => {
14196
- if (!envAccessToken2 && !store.isAuthenticated()) {
14197
- return c.error(NOT_AUTHENTICATED_ERROR);
14198
- }
14199
- return next();
14200
- };
14201
- }
14202
- function requireAuthGuard(c, authStorage2, envAccessToken2) {
14203
- const store = authStorage2 ?? storage;
14204
- if (!envAccessToken2 && !store.isAuthenticated()) {
14205
- c.error(NOT_AUTHENTICATED_ERROR);
14206
- }
14207
- }
14743
+ import { Cli as Cli4, z as z5 } from "incur";
14208
14744
 
14209
14745
  // src/commands/mpp/decode-view.tsx
14210
- import { Box as Box9, Text as Text11 } from "ink";
14211
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
14746
+ import { Box as Box10, Text as Text12 } from "ink";
14747
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
14212
14748
  function DecodeChallengeView({
14213
14749
  decoded
14214
14750
  }) {
14215
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
14216
- /* @__PURE__ */ jsx12(Text11, { color: "green", children: "\u2713 Stripe challenge decoded" }),
14217
- /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
14218
- /* @__PURE__ */ jsxs9(Text11, { children: [
14751
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14752
+ /* @__PURE__ */ jsx14(Text12, { color: "green", children: "\u2713 Stripe challenge decoded" }),
14753
+ /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
14754
+ /* @__PURE__ */ jsxs10(Text12, { children: [
14219
14755
  "ID: ",
14220
- /* @__PURE__ */ jsx12(Text11, { bold: true, children: decoded.id })
14756
+ /* @__PURE__ */ jsx14(Text12, { bold: true, children: decoded.id })
14221
14757
  ] }),
14222
- /* @__PURE__ */ jsxs9(Text11, { children: [
14758
+ /* @__PURE__ */ jsxs10(Text12, { children: [
14223
14759
  "Realm: ",
14224
- /* @__PURE__ */ jsx12(Text11, { bold: true, children: decoded.realm })
14760
+ /* @__PURE__ */ jsx14(Text12, { bold: true, children: decoded.realm })
14225
14761
  ] }),
14226
- /* @__PURE__ */ jsxs9(Text11, { children: [
14762
+ /* @__PURE__ */ jsxs10(Text12, { children: [
14227
14763
  "Network ID: ",
14228
- /* @__PURE__ */ jsx12(Text11, { bold: true, children: decoded.network_id })
14764
+ /* @__PURE__ */ jsx14(Text12, { bold: true, children: decoded.network_id })
14229
14765
  ] }),
14230
- /* @__PURE__ */ jsx12(Text11, { children: "Request JSON:" }),
14231
- /* @__PURE__ */ jsx12(Text11, { children: JSON.stringify(decoded.request_json, null, 2) })
14766
+ /* @__PURE__ */ jsx14(Text12, { children: "Request JSON:" }),
14767
+ /* @__PURE__ */ jsx14(Text12, { children: JSON.stringify(decoded.request_json, null, 2) })
14232
14768
  ] })
14233
14769
  ] });
14234
14770
  }
14235
14771
 
14236
14772
  // src/commands/mpp/schema.ts
14237
- import { z as z3 } from "incur";
14238
- var payOptions = z3.object({
14239
- spendRequestId: z3.string().describe(
14240
- 'Approved spend request ID with credential_type "shared_payment_token"'
14773
+ import { z as z4 } from "incur";
14774
+ var payOptions = z4.object({
14775
+ spendRequestId: z4.string().optional().describe(
14776
+ 'Approved spend request ID with credential_type "shared_payment_token". If omitted, the command handles the full flow: probe URL, parse challenge, create spend request, get approval, and pay.'
14777
+ ),
14778
+ method: z4.string().optional().describe("HTTP method (default: GET, or POST if --data is provided)"),
14779
+ data: z4.string().optional().describe("Request body (implies POST if --method is not set)"),
14780
+ header: z4.array(z4.string()).default([]).describe('Request header in "Name: Value" format (repeatable)'),
14781
+ context: z4.string().min(100).optional().describe(
14782
+ "Min 100 chars \u2014 describe the purchase and rationale; the user reads this when approving. Required when --spend-request-id is not provided."
14783
+ ),
14784
+ amount: z4.coerce.number().int().positive().optional().describe(
14785
+ "Amount in cents (derived from 402 challenge if omitted; required if challenge has no amount)"
14241
14786
  ),
14242
- method: z3.string().optional().describe("HTTP method (default: GET, or POST if --data is provided)"),
14243
- data: z3.string().optional().describe("Request body (implies POST if --method is not set)"),
14244
- header: z3.array(z3.string()).default([]).describe('Request header in "Name: Value" format (repeatable)')
14787
+ paymentMethodId: z4.string().optional().describe("Payment method ID (uses default if omitted)"),
14788
+ test: z4.boolean().default(false).describe(
14789
+ "Use test mode (creates testmode credentials from test card data)"
14790
+ )
14245
14791
  });
14246
- var decodeOptions = z3.object({
14247
- challenge: z3.string().describe(
14792
+ var decodeOptions = z4.object({
14793
+ challenge: z4.string().describe(
14248
14794
  "Raw WWW-Authenticate header value; may include multiple payment challenges"
14249
14795
  )
14250
14796
  });
14251
14797
 
14252
14798
  // src/commands/mpp/index.tsx
14253
- import { jsx as jsx13 } from "react/jsx-runtime";
14254
- function createMppCli(repository, authStorage2, envAccessToken2) {
14255
- const cli2 = Cli3.create("mpp", {
14799
+ import { jsx as jsx15 } from "react/jsx-runtime";
14800
+ function createMppCli(repository, paymentMethodsFactory, authStorage2, envAccessToken2) {
14801
+ const cli2 = Cli4.create("mpp", {
14256
14802
  description: "Machine payment protocol (MPP) commands"
14257
14803
  });
14258
14804
  cli2.command("pay", {
14259
- description: "Complete a machine payment protocol (MPP) payment using an approved spend request",
14260
- args: z4.object({
14261
- url: z4.string().describe("URL to pay")
14805
+ description: "Pay a URL via the Machine Payment Protocol. Handles the full 402 flow: probes the URL, parses the challenge, creates a spend request, gets approval, and pays with the SPT. Pass --spend-request-id to skip creation and use a pre-approved spend request.",
14806
+ args: z5.object({
14807
+ url: z5.string().describe("URL to pay")
14262
14808
  }),
14263
14809
  options: payOptions,
14264
14810
  alias: { method: "X", data: "d", header: "H" },
14265
14811
  outputPolicy: "agent-only",
14266
14812
  middleware: [requireAuth(authStorage2, envAccessToken2)],
14267
- async run(c) {
14813
+ async *run(c) {
14268
14814
  const url = c.args.url;
14269
14815
  const opts = c.options;
14270
14816
  const method = opts.method;
@@ -14273,7 +14819,7 @@ function createMppCli(repository, authStorage2, envAccessToken2) {
14273
14819
  if (!c.agent && !c.formatExplicit) {
14274
14820
  let capturedResult = null;
14275
14821
  return renderInteractive(
14276
- /* @__PURE__ */ jsx13(
14822
+ /* @__PURE__ */ jsx15(
14277
14823
  MppPay,
14278
14824
  {
14279
14825
  url,
@@ -14281,7 +14827,12 @@ function createMppCli(repository, authStorage2, envAccessToken2) {
14281
14827
  method,
14282
14828
  data,
14283
14829
  headers,
14830
+ context: opts.context,
14831
+ amountOverride: opts.amount,
14832
+ paymentMethodId: opts.paymentMethodId,
14833
+ test: opts.test,
14284
14834
  repository,
14835
+ paymentMethodsFactory,
14285
14836
  onComplete: (result) => {
14286
14837
  capturedResult = result;
14287
14838
  }
@@ -14294,14 +14845,90 @@ function createMppCli(repository, authStorage2, envAccessToken2) {
14294
14845
  }
14295
14846
  );
14296
14847
  }
14297
- return runMppPay(
14298
- url,
14299
- opts.spendRequestId,
14300
- method,
14301
- data,
14302
- headers,
14303
- repository
14304
- );
14848
+ if (opts.spendRequestId) {
14849
+ yield await runMppPayWithSpendRequest(
14850
+ url,
14851
+ opts.spendRequestId,
14852
+ method,
14853
+ data,
14854
+ headers,
14855
+ repository
14856
+ );
14857
+ return;
14858
+ }
14859
+ const httpMethod = method ?? (data !== void 0 ? "POST" : "GET");
14860
+ const requestHeaders = buildHeaders(data, headers);
14861
+ const probeResponse = await fetch(url, {
14862
+ method: httpMethod,
14863
+ body: data,
14864
+ headers: requestHeaders
14865
+ });
14866
+ if (probeResponse.status !== 402) {
14867
+ yield await readPayResult(probeResponse);
14868
+ return;
14869
+ }
14870
+ const wwwAuth = probeResponse.headers.get("www-authenticate");
14871
+ if (!wwwAuth) {
14872
+ return c.error({
14873
+ code: "INVALID_RESPONSE",
14874
+ message: "URL returned 402 but no WWW-Authenticate header"
14875
+ });
14876
+ }
14877
+ const decoded = decodeStripeChallenge(wwwAuth);
14878
+ const networkId = decoded.network_id;
14879
+ const challengeAmount = decoded.request_json.amount ? Number(decoded.request_json.amount) : void 0;
14880
+ const challengeCurrency = decoded.request_json.currency ?? "usd";
14881
+ const amount = opts.amount ?? challengeAmount;
14882
+ if (!amount) {
14883
+ return c.error({
14884
+ code: "INVALID_INPUT",
14885
+ message: "Could not determine amount from 402 challenge. Pass --amount explicitly."
14886
+ });
14887
+ }
14888
+ if (!opts.context) {
14889
+ return c.error({
14890
+ code: "INVALID_INPUT",
14891
+ message: "--context is required for the full MPP flow (min 100 chars). Describe the purchase and rationale."
14892
+ });
14893
+ }
14894
+ let pmId = opts.paymentMethodId;
14895
+ if (!pmId) {
14896
+ const pmResource = paymentMethodsFactory();
14897
+ const methods = await pmResource.list();
14898
+ if (!methods.length) {
14899
+ return c.error({
14900
+ code: "NO_PAYMENT_METHOD",
14901
+ message: "No payment methods found. Add one with `link-cli payment-methods add`."
14902
+ });
14903
+ }
14904
+ pmId = methods[0].id;
14905
+ }
14906
+ const spendRequest = await repository.createSpendRequest({
14907
+ payment_details: pmId,
14908
+ credential_type: "shared_payment_token",
14909
+ network_id: networkId,
14910
+ amount,
14911
+ currency: challengeCurrency,
14912
+ context: opts.context,
14913
+ request_approval: true,
14914
+ test: opts.test || void 0
14915
+ });
14916
+ const nextFlags = [`--spend-request-id ${spendRequest.id}`];
14917
+ if (method) nextFlags.push(`-X ${method}`);
14918
+ if (data) nextFlags.push(`-d '${data}'`);
14919
+ if (headers) {
14920
+ for (const h of headers) nextFlags.push(`-H '${h}'`);
14921
+ }
14922
+ const nextCommand = `mpp pay ${url} ${nextFlags.join(" ")}`;
14923
+ yield {
14924
+ ...spendRequest,
14925
+ instruction: `Present the approval_url to the user and ask them to approve in the Link app. Then call \`spend-request retrieve ${spendRequest.id} --interval 2 --max-attempts 300\` to poll until approved. Once approved, run the _next.command to complete payment. Do not wait for the user to reply \u2014 start polling immediately.`,
14926
+ _next: {
14927
+ poll_command: `spend-request retrieve ${spendRequest.id} --interval 2 --max-attempts 300`,
14928
+ pay_command: nextCommand,
14929
+ until: "status changes from pending_approval, then run pay_command"
14930
+ }
14931
+ };
14305
14932
  }
14306
14933
  });
14307
14934
  cli2.command("decode", {
@@ -14312,7 +14939,7 @@ function createMppCli(repository, authStorage2, envAccessToken2) {
14312
14939
  const decoded = decodeStripeChallenge(c.options.challenge);
14313
14940
  if (!c.agent && !c.formatExplicit) {
14314
14941
  return renderInteractive(
14315
- /* @__PURE__ */ jsx13(DecodeChallengeView, { decoded }),
14942
+ /* @__PURE__ */ jsx15(DecodeChallengeView, { decoded }),
14316
14943
  () => decoded
14317
14944
  );
14318
14945
  }
@@ -14323,12 +14950,12 @@ function createMppCli(repository, authStorage2, envAccessToken2) {
14323
14950
  }
14324
14951
 
14325
14952
  // src/commands/onboard/index.tsx
14326
- import { Cli as Cli4 } from "incur";
14953
+ import { Cli as Cli5 } from "incur";
14327
14954
 
14328
14955
  // src/commands/onboard/onboard-runner.tsx
14329
- import { Box as Box10, Text as Text12, useApp as useApp2, useInput as useInput5 } from "ink";
14956
+ import { Box as Box11, Text as Text13, useApp as useApp2, useInput as useInput5 } from "ink";
14330
14957
  import { useEffect as useEffect7, useRef as useRef4, useState as useState8 } from "react";
14331
- import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
14958
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
14332
14959
  var OnboardRunner = ({
14333
14960
  authRepo: authRepo2,
14334
14961
  spendRequestRepo: spendRequestRepo2,
@@ -14394,21 +15021,21 @@ var OnboardRunner = ({
14394
15021
  const order = ["welcome", "auth", "payment-methods", "demo"];
14395
15022
  return order.indexOf(phase) > order.indexOf(target);
14396
15023
  };
14397
- const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs10(Text12, { dimColor: true, children: [
15024
+ const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
14398
15025
  "\n",
14399
15026
  ">",
14400
15027
  " ",
14401
15028
  label
14402
15029
  ] });
14403
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", gap: 1, children: [
14404
- /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14405
- /* @__PURE__ */ jsx14(Text12, { bold: true, children: ONBOARD.title }),
14406
- /* @__PURE__ */ jsx14(Text12, { children: ONBOARD.subtitle })
15030
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", gap: 1, children: [
15031
+ /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
15032
+ /* @__PURE__ */ jsx16(Text13, { bold: true, children: ONBOARD.title }),
15033
+ /* @__PURE__ */ jsx16(Text13, { children: ONBOARD.subtitle })
14407
15034
  ] }),
14408
- /* @__PURE__ */ jsx14(Box10, { flexDirection: "column", children: authSkipped || pastPhase("auth") ? /* @__PURE__ */ jsxs10(Text12, { color: "green", children: [
15035
+ /* @__PURE__ */ jsx16(Box11, { flexDirection: "column", children: authSkipped || pastPhase("auth") ? /* @__PURE__ */ jsxs11(Text13, { color: "green", children: [
14409
15036
  "\u2713 ",
14410
15037
  authSkipped ? ONBOARD.auth.alreadyLoggedIn : ONBOARD.auth.authenticated
14411
- ] }) : phase === "auth" && !storage2.isAuthenticated() ? /* @__PURE__ */ jsx14(
15038
+ ] }) : phase === "auth" && !storage2.isAuthenticated() ? /* @__PURE__ */ jsx16(
14412
15039
  Login,
14413
15040
  {
14414
15041
  authResource: authRepo2,
@@ -14417,24 +15044,24 @@ var OnboardRunner = ({
14417
15044
  onComplete: () => authResolver.current?.()
14418
15045
  }
14419
15046
  ) : null }),
14420
- pastPhase("auth") && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14421
- phase === "payment-methods" && !pmMissing && /* @__PURE__ */ jsx14(Text12, { color: "cyan", children: ONBOARD.paymentMethods.loading }),
14422
- pmMissing && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14423
- /* @__PURE__ */ jsx14(Text12, { color: "yellow", children: ONBOARD.paymentMethods.missing }),
14424
- /* @__PURE__ */ jsx14(Box10, { marginTop: 1, children: /* @__PURE__ */ jsxs10(Text12, { children: [
15047
+ pastPhase("auth") && /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
15048
+ phase === "payment-methods" && !pmMissing && /* @__PURE__ */ jsx16(Text13, { color: "cyan", children: ONBOARD.paymentMethods.loading }),
15049
+ pmMissing && /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
15050
+ /* @__PURE__ */ jsx16(Text13, { color: "yellow", children: ONBOARD.paymentMethods.missing }),
15051
+ /* @__PURE__ */ jsx16(Box11, { marginTop: 1, children: /* @__PURE__ */ jsxs11(Text13, { children: [
14425
15052
  "Visit",
14426
15053
  " ",
14427
- /* @__PURE__ */ jsx14(Text12, { bold: true, color: "cyan", children: "app.link.com/wallet" }),
15054
+ /* @__PURE__ */ jsx16(Text13, { bold: true, color: "cyan", children: "app.link.com/wallet" }),
14428
15055
  " ",
14429
15056
  "to add a payment method, then press [Enter] to continue."
14430
15057
  ] }) }),
14431
15058
  prompt(ONBOARD.paymentMethods.retryPrompt)
14432
15059
  ] }),
14433
- pastPhase("payment-methods") && /* @__PURE__ */ jsx14(Text12, { color: "green", children: "\u2713 Payment method found" })
15060
+ pastPhase("payment-methods") && /* @__PURE__ */ jsx16(Text13, { color: "green", children: "\u2713 Payment method found" })
14434
15061
  ] }),
14435
- phase === "demo" && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
14436
- /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "\u2500\u2500\u2500" }),
14437
- /* @__PURE__ */ jsx14(
15062
+ phase === "demo" && /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
15063
+ /* @__PURE__ */ jsx16(Text13, { dimColor: true, children: "\u2500\u2500\u2500" }),
15064
+ /* @__PURE__ */ jsx16(
14438
15065
  DemoRunner,
14439
15066
  {
14440
15067
  authRepo: authRepo2,
@@ -14445,7 +15072,7 @@ var OnboardRunner = ({
14445
15072
  }
14446
15073
  )
14447
15074
  ] }),
14448
- error && /* @__PURE__ */ jsxs10(Text12, { color: "red", children: [
15075
+ error && /* @__PURE__ */ jsxs11(Text13, { color: "red", children: [
14449
15076
  "Error: ",
14450
15077
  error
14451
15078
  ] })
@@ -14453,9 +15080,9 @@ var OnboardRunner = ({
14453
15080
  };
14454
15081
 
14455
15082
  // src/commands/onboard/index.tsx
14456
- import { jsx as jsx15 } from "react/jsx-runtime";
15083
+ import { jsx as jsx17 } from "react/jsx-runtime";
14457
15084
  function createOnboardCli(authRepo2, spendRequestRepo2, createPaymentMethodsResource, authStorage2) {
14458
- return Cli4.create("onboard", {
15085
+ return Cli5.create("onboard", {
14459
15086
  description: "Guided setup: authenticate, verify payment methods, and demo both payment flows",
14460
15087
  outputPolicy: "agent-only",
14461
15088
  async run(c) {
@@ -14467,7 +15094,7 @@ function createOnboardCli(authRepo2, spendRequestRepo2, createPaymentMethodsReso
14467
15094
  }
14468
15095
  const paymentMethodsResource = createPaymentMethodsResource();
14469
15096
  return renderInteractive(
14470
- /* @__PURE__ */ jsx15(
15097
+ /* @__PURE__ */ jsx17(
14471
15098
  OnboardRunner,
14472
15099
  {
14473
15100
  authRepo: authRepo2,
@@ -14485,11 +15112,11 @@ function createOnboardCli(authRepo2, spendRequestRepo2, createPaymentMethodsReso
14485
15112
  }
14486
15113
 
14487
15114
  // src/commands/payment-methods/index.tsx
14488
- import { Cli as Cli5 } from "incur";
15115
+ import { Cli as Cli6 } from "incur";
14489
15116
 
14490
15117
  // src/commands/payment-methods/add.tsx
14491
- import { Box as Box11, Text as Text13, useApp as useApp3, useInput as useInput6 } from "ink";
14492
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
15118
+ import { Box as Box12, Text as Text14, useApp as useApp3, useInput as useInput6 } from "ink";
15119
+ import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
14493
15120
  var WALLET_URL = "https://app.link.com/wallet";
14494
15121
  var AddPaymentMethod = () => {
14495
15122
  const { exit } = useApp3();
@@ -14499,10 +15126,10 @@ var AddPaymentMethod = () => {
14499
15126
  exit();
14500
15127
  }
14501
15128
  });
14502
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingY: 1, children: [
14503
- /* @__PURE__ */ jsx16(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text13, { bold: true, children: "Add Payment Method" }) }),
14504
- /* @__PURE__ */ jsxs11(
14505
- Box11,
15129
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingY: 1, children: [
15130
+ /* @__PURE__ */ jsx18(Box12, { marginBottom: 1, children: /* @__PURE__ */ jsx18(Text14, { bold: true, children: "Add Payment Method" }) }),
15131
+ /* @__PURE__ */ jsxs12(
15132
+ Box12,
14506
15133
  {
14507
15134
  flexDirection: "column",
14508
15135
  borderStyle: "round",
@@ -14510,12 +15137,12 @@ var AddPaymentMethod = () => {
14510
15137
  paddingX: 2,
14511
15138
  paddingY: 1,
14512
15139
  children: [
14513
- /* @__PURE__ */ jsxs11(Text13, { children: [
15140
+ /* @__PURE__ */ jsxs12(Text14, { children: [
14514
15141
  "Open:",
14515
15142
  " ",
14516
- /* @__PURE__ */ jsx16(Text13, { bold: true, color: "cyan", children: WALLET_URL })
15143
+ /* @__PURE__ */ jsx18(Text14, { bold: true, color: "cyan", children: WALLET_URL })
14517
15144
  ] }),
14518
- /* @__PURE__ */ jsx16(Text13, { dimColor: true, children: "Press Enter to open in browser" })
15145
+ /* @__PURE__ */ jsx18(Text14, { dimColor: true, children: "Press Enter to open in browser" })
14519
15146
  ]
14520
15147
  }
14521
15148
  )
@@ -14523,48 +15150,48 @@ var AddPaymentMethod = () => {
14523
15150
  };
14524
15151
 
14525
15152
  // src/commands/payment-methods/list.tsx
14526
- import { Box as Box12, Text as Text14 } from "ink";
14527
- import Spinner4 from "ink-spinner";
14528
- import { useCallback as useCallback3 } from "react";
14529
- import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
15153
+ import { Box as Box13, Text as Text15 } from "ink";
15154
+ import Spinner5 from "ink-spinner";
15155
+ import { useCallback as useCallback4 } from "react";
15156
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
14530
15157
  var PaymentMethodsList = ({
14531
15158
  resource,
14532
15159
  onComplete
14533
15160
  }) => {
14534
- const action = useCallback3(() => resource.listPaymentMethods(), [resource]);
15161
+ const action = useCallback4(() => resource.listPaymentMethods(), [resource]);
14535
15162
  const { status, data: methods, error } = useAsyncAction(action, onComplete);
14536
15163
  if (status === "loading") {
14537
- return /* @__PURE__ */ jsx17(Box12, { children: /* @__PURE__ */ jsxs12(Text14, { color: "cyan", children: [
14538
- /* @__PURE__ */ jsx17(Spinner4, { type: "dots" }),
15164
+ return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsxs13(Text15, { color: "cyan", children: [
15165
+ /* @__PURE__ */ jsx19(Spinner5, { type: "dots" }),
14539
15166
  " Loading payment methods..."
14540
15167
  ] }) });
14541
15168
  }
14542
15169
  if (status === "error") {
14543
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
14544
- /* @__PURE__ */ jsx17(Text14, { color: "red", children: "\u2717 Failed to load payment methods" }),
14545
- /* @__PURE__ */ jsx17(Text14, { color: "red", children: error })
15170
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
15171
+ /* @__PURE__ */ jsx19(Text15, { color: "red", children: "\u2717 Failed to load payment methods" }),
15172
+ /* @__PURE__ */ jsx19(Text15, { color: "red", children: error })
14546
15173
  ] });
14547
15174
  }
14548
15175
  if (!methods || methods.length === 0) {
14549
- return /* @__PURE__ */ jsx17(Box12, { children: /* @__PURE__ */ jsx17(Text14, { dimColor: true, children: "No payment methods found" }) });
15176
+ return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: "No payment methods found" }) });
14550
15177
  }
14551
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
14552
- /* @__PURE__ */ jsx17(Text14, { bold: true, children: "Payment Methods" }),
14553
- /* @__PURE__ */ jsx17(Box12, { flexDirection: "column", marginTop: 1, children: methods.map((pm) => {
15178
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
15179
+ /* @__PURE__ */ jsx19(Text15, { bold: true, children: "Payment Methods" }),
15180
+ /* @__PURE__ */ jsx19(Box13, { flexDirection: "column", marginTop: 1, children: methods.map((pm) => {
14554
15181
  const label = pm.card_details?.brand ?? pm.bank_account_details?.bank_name ?? "Bank account";
14555
15182
  const last4 = pm.card_details?.last4 ?? pm.bank_account_details?.last4;
14556
15183
  const suffix = pm.nickname ? `(${pm.nickname})` : "";
14557
15184
  const agenticCap = pm.capabilities?.agentic_payments;
14558
15185
  const ineligible = agenticCap && !agenticCap.eligible;
14559
- return /* @__PURE__ */ jsx17(Box12, { paddingX: 2, children: /* @__PURE__ */ jsxs12(Text14, { children: [
14560
- /* @__PURE__ */ jsx17(Text14, { dimColor: true, children: pm.id }),
15186
+ return /* @__PURE__ */ jsx19(Box13, { paddingX: 2, children: /* @__PURE__ */ jsxs13(Text15, { children: [
15187
+ /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: pm.id }),
14561
15188
  " ",
14562
15189
  label,
14563
15190
  " ****",
14564
15191
  last4,
14565
15192
  suffix ? ` ${suffix}` : "",
14566
- pm.is_default ? /* @__PURE__ */ jsx17(Text14, { color: "green", children: " (default)" }) : "",
14567
- ineligible ? /* @__PURE__ */ jsxs12(Text14, { dimColor: true, children: [
15193
+ pm.is_default ? /* @__PURE__ */ jsx19(Text15, { color: "green", children: " (default)" }) : "",
15194
+ ineligible ? /* @__PURE__ */ jsxs13(Text15, { dimColor: true, children: [
14568
15195
  " ",
14569
15196
  "agentic_payments: ineligible",
14570
15197
  agenticCap.ineligibility_reasons?.length > 0 ? ` (${agenticCap.ineligibility_reasons.join(", ")})` : ""
@@ -14575,9 +15202,9 @@ var PaymentMethodsList = ({
14575
15202
  };
14576
15203
 
14577
15204
  // src/commands/payment-methods/index.tsx
14578
- import { jsx as jsx18 } from "react/jsx-runtime";
15205
+ import { jsx as jsx20 } from "react/jsx-runtime";
14579
15206
  function createPaymentMethodsCli(createResource, authStorage2, envAccessToken2) {
14580
- const cli2 = Cli5.create("payment-methods", {
15207
+ const cli2 = Cli6.create("payment-methods", {
14581
15208
  description: "Payment methods management commands"
14582
15209
  });
14583
15210
  cli2.command("list", {
@@ -14588,7 +15215,7 @@ function createPaymentMethodsCli(createResource, authStorage2, envAccessToken2)
14588
15215
  const resource = createResource();
14589
15216
  if (!c.agent && !c.formatExplicit) {
14590
15217
  return renderInteractive(
14591
- /* @__PURE__ */ jsx18(PaymentMethodsList, { resource, onComplete: () => {
15218
+ /* @__PURE__ */ jsx20(PaymentMethodsList, { resource, onComplete: () => {
14592
15219
  } }),
14593
15220
  () => resource.listPaymentMethods()
14594
15221
  );
@@ -14602,7 +15229,7 @@ function createPaymentMethodsCli(createResource, authStorage2, envAccessToken2)
14602
15229
  middleware: [requireAuth(authStorage2, envAccessToken2)],
14603
15230
  async run(c) {
14604
15231
  if (!c.agent && !c.formatExplicit) {
14605
- return renderInteractive(/* @__PURE__ */ jsx18(AddPaymentMethod, {}), () => ({
15232
+ return renderInteractive(/* @__PURE__ */ jsx20(AddPaymentMethod, {}), () => ({
14606
15233
  url: WALLET_URL
14607
15234
  }));
14608
15235
  }
@@ -14613,22 +15240,22 @@ function createPaymentMethodsCli(createResource, authStorage2, envAccessToken2)
14613
15240
  }
14614
15241
 
14615
15242
  // src/commands/report/index.tsx
14616
- import { Cli as Cli6 } from "incur";
15243
+ import { Cli as Cli7 } from "incur";
14617
15244
 
14618
15245
  // src/commands/report/schema.ts
14619
- import { z as z5 } from "incur";
14620
- var reportOptions = z5.object({
14621
- domain: z5.string().describe("Domain where the outcome occurred"),
14622
- outcome: z5.enum(REPORT_OUTCOMES).describe("What happened: success, blocked, or abandoned"),
14623
- spendRequestId: z5.string().describe("Spend request ID (lsrq_...)"),
14624
- tag: z5.array(z5.enum(REPORT_TAGS)).optional().describe("Outcome tags (repeatable)"),
14625
- step: z5.string().max(500).optional().describe("Where in the flow the agent was"),
14626
- freeformContext: z5.string().max(500).optional().describe("Additional context (max 500 chars)")
15246
+ import { z as z6 } from "incur";
15247
+ var reportOptions = z6.object({
15248
+ domain: z6.string().describe("Domain where the outcome occurred"),
15249
+ outcome: z6.enum(REPORT_OUTCOMES).describe("What happened: success, blocked, or abandoned"),
15250
+ spendRequestId: z6.string().describe("Spend request ID (lsrq_...)"),
15251
+ tag: z6.array(z6.enum(REPORT_TAGS)).optional().describe("Outcome tags (repeatable)"),
15252
+ step: z6.string().max(500).optional().describe("Where in the flow the agent was"),
15253
+ freeformContext: z6.string().max(500).optional().describe("Additional context (max 500 chars)")
14627
15254
  });
14628
15255
 
14629
15256
  // src/commands/report/index.tsx
14630
15257
  function createReportCli(createResource, authStorage2, envAccessToken2) {
14631
- const cli2 = Cli6.create("report", {
15258
+ const cli2 = Cli7.create("report", {
14632
15259
  description: "Report the outcome of an agent action on a domain. Call after every purchase attempt.",
14633
15260
  options: reportOptions,
14634
15261
  outputPolicy: "agent-only",
@@ -14653,7 +15280,7 @@ function createReportCli(createResource, authStorage2, envAccessToken2) {
14653
15280
  import {
14654
15281
  createServer
14655
15282
  } from "http";
14656
- import { Cli as Cli7, z as z6 } from "incur";
15283
+ import { Cli as Cli8, z as z7 } from "incur";
14657
15284
  async function nodeRequestToWebRequest(req, port) {
14658
15285
  const body = await new Promise((resolve) => {
14659
15286
  const chunks = [];
@@ -14678,17 +15305,47 @@ async function sendWebResponse(webRes, res) {
14678
15305
  res.writeHead(webRes.status);
14679
15306
  res.end(Buffer.from(buffer));
14680
15307
  }
15308
+ var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost"]);
15309
+ function isLoopbackHost(host) {
15310
+ return LOOPBACK_HOSTS.has(host.toLowerCase());
15311
+ }
15312
+ function isAllowedOrigin(origin) {
15313
+ if (!origin) return true;
15314
+ try {
15315
+ return isLoopbackHost(new URL(origin).hostname);
15316
+ } catch {
15317
+ return false;
15318
+ }
15319
+ }
15320
+ function isAllowedRoute(method, pathname) {
15321
+ if (pathname === "/mcp") return true;
15322
+ if (pathname.startsWith("/.well-known/skills/") && method === "GET")
15323
+ return true;
15324
+ return false;
15325
+ }
14681
15326
  function createServeCli(rootCli) {
14682
- return Cli7.create("serve", {
15327
+ return Cli8.create("serve", {
14683
15328
  description: "Start an HTTP server exposing link-cli as an MCP endpoint at /mcp",
14684
- options: z6.object({
14685
- port: z6.coerce.number().default(54321).describe("Port to listen on")
15329
+ options: z7.object({
15330
+ port: z7.coerce.number().default(54321).describe("Port to listen on"),
15331
+ host: z7.string().default("127.0.0.1").describe(
15332
+ "Host/interface to bind. Defaults to loopback; set explicitly (e.g. 0.0.0.0) to expose beyond localhost."
15333
+ )
14686
15334
  }),
14687
15335
  async run(c) {
14688
- const { port } = c.options;
15336
+ const { port, host } = c.options;
14689
15337
  const server = createServer(
14690
15338
  async (req, res) => {
14691
- res.setHeader("Access-Control-Allow-Origin", "*");
15339
+ const origin = req.headers.origin;
15340
+ if (!isAllowedOrigin(origin)) {
15341
+ res.writeHead(403, { "Content-Type": "application/json" });
15342
+ res.end(JSON.stringify({ error: "forbidden origin" }));
15343
+ return;
15344
+ }
15345
+ if (origin) {
15346
+ res.setHeader("Access-Control-Allow-Origin", origin);
15347
+ res.setHeader("Vary", "Origin");
15348
+ }
14692
15349
  res.setHeader(
14693
15350
  "Access-Control-Allow-Methods",
14694
15351
  "GET, POST, DELETE, OPTIONS"
@@ -14702,6 +15359,12 @@ function createServeCli(rootCli) {
14702
15359
  res.end();
14703
15360
  return;
14704
15361
  }
15362
+ const pathname = new URL(req.url ?? "/", `http://localhost:${port}`).pathname;
15363
+ if (!isAllowedRoute(req.method ?? "GET", pathname)) {
15364
+ res.writeHead(404, { "Content-Type": "application/json" });
15365
+ res.end(JSON.stringify({ error: "not found" }));
15366
+ return;
15367
+ }
14705
15368
  try {
14706
15369
  const webReq = await nodeRequestToWebRequest(req, port);
14707
15370
  const webRes = await rootCli.fetch(webReq);
@@ -14715,9 +15378,16 @@ function createServeCli(rootCli) {
14715
15378
  );
14716
15379
  await new Promise((resolve, reject) => {
14717
15380
  server.on("error", reject);
14718
- server.listen(port, () => {
15381
+ server.listen(port, host, () => {
15382
+ if (!isLoopbackHost(host)) {
15383
+ process.stderr.write(
15384
+ `WARNING: link-cli serve is bound to ${host}, which may be reachable beyond localhost.
15385
+ Any caller that can reach this port can use the authenticated Link session of this CLI. Only do this on a trusted, isolated network.
15386
+ `
15387
+ );
15388
+ }
14719
15389
  process.stderr.write(
14720
- `link-cli MCP server listening on http://localhost:${port}/mcp
15390
+ `link-cli MCP server listening on http://${host}:${port}/mcp
14721
15391
  `
14722
15392
  );
14723
15393
  });
@@ -14727,13 +15397,13 @@ function createServeCli(rootCli) {
14727
15397
  }
14728
15398
 
14729
15399
  // src/commands/shipping-address/index.tsx
14730
- import { Cli as Cli8 } from "incur";
15400
+ import { Cli as Cli9 } from "incur";
14731
15401
 
14732
15402
  // src/commands/shipping-address/list.tsx
14733
- import { Box as Box13, Text as Text15 } from "ink";
14734
- import Spinner5 from "ink-spinner";
14735
- import { useCallback as useCallback4 } from "react";
14736
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
15403
+ import { Box as Box14, Text as Text16 } from "ink";
15404
+ import Spinner6 from "ink-spinner";
15405
+ import { useCallback as useCallback5 } from "react";
15406
+ import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
14737
15407
  function formatStreetLine(address) {
14738
15408
  const parts = [address.line_1, address.line_2].filter(Boolean);
14739
15409
  return parts.length > 0 ? parts.join(", ") : null;
@@ -14751,100 +15421,311 @@ function formatLocalityLine(address) {
14751
15421
  }
14752
15422
  return localityPostal || address.country_code || null;
14753
15423
  }
14754
- function formatAddressLines(addressRecord) {
14755
- if (!addressRecord.address) {
14756
- return ["Address details unavailable"];
15424
+ function formatAddressLines(addressRecord) {
15425
+ if (!addressRecord.address) {
15426
+ return ["Address details unavailable"];
15427
+ }
15428
+ const address = addressRecord.address;
15429
+ const lines = [formatStreetLine(address), formatLocalityLine(address)].filter(
15430
+ (line) => Boolean(line)
15431
+ );
15432
+ return lines.length > 0 ? lines : ["Address details unavailable"];
15433
+ }
15434
+ var ShippingAddressList = ({
15435
+ resource,
15436
+ onComplete
15437
+ }) => {
15438
+ const action = useCallback5(
15439
+ () => resource.listShippingAddresses(),
15440
+ [resource]
15441
+ );
15442
+ const {
15443
+ status,
15444
+ data: shippingAddresses,
15445
+ error
15446
+ } = useAsyncAction(action, onComplete);
15447
+ if (status === "loading") {
15448
+ return /* @__PURE__ */ jsx21(Box14, { children: /* @__PURE__ */ jsxs14(Text16, { color: "cyan", children: [
15449
+ /* @__PURE__ */ jsx21(Spinner6, { type: "dots" }),
15450
+ " Loading shipping addresses..."
15451
+ ] }) });
15452
+ }
15453
+ if (status === "error") {
15454
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
15455
+ /* @__PURE__ */ jsx21(Text16, { color: "red", children: "\u2717 Failed to load shipping addresses" }),
15456
+ /* @__PURE__ */ jsx21(Text16, { color: "red", children: error })
15457
+ ] });
15458
+ }
15459
+ if (!shippingAddresses || shippingAddresses.length === 0) {
15460
+ return /* @__PURE__ */ jsx21(Box14, { children: /* @__PURE__ */ jsx21(Text16, { dimColor: true, children: "No shipping addresses found" }) });
15461
+ }
15462
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
15463
+ /* @__PURE__ */ jsx21(Text16, { bold: true, children: "Shipping Addresses" }),
15464
+ /* @__PURE__ */ jsx21(Box14, { flexDirection: "column", marginTop: 1, children: shippingAddresses.map((shippingAddress) => {
15465
+ const addressName = shippingAddress.address?.name;
15466
+ const nickname = shippingAddress.nickname ? ` (${shippingAddress.nickname})` : "";
15467
+ return /* @__PURE__ */ jsxs14(
15468
+ Box14,
15469
+ {
15470
+ flexDirection: "column",
15471
+ paddingX: 2,
15472
+ marginBottom: 1,
15473
+ children: [
15474
+ /* @__PURE__ */ jsxs14(Text16, { children: [
15475
+ /* @__PURE__ */ jsx21(Text16, { dimColor: true, children: shippingAddress.id }),
15476
+ nickname,
15477
+ shippingAddress.is_default ? /* @__PURE__ */ jsx21(Text16, { color: "green", children: " (default)" }) : null
15478
+ ] }),
15479
+ /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginTop: 1, children: [
15480
+ addressName ? /* @__PURE__ */ jsx21(Text16, { bold: true, children: addressName }) : null,
15481
+ formatAddressLines(shippingAddress).map((line) => /* @__PURE__ */ jsx21(Text16, { children: line }, `${shippingAddress.id}:${line}`))
15482
+ ] })
15483
+ ]
15484
+ },
15485
+ shippingAddress.id
15486
+ );
15487
+ }) })
15488
+ ] });
15489
+ };
15490
+
15491
+ // src/commands/shipping-address/index.tsx
15492
+ import { jsx as jsx22 } from "react/jsx-runtime";
15493
+ function createShippingAddressCli(createResource, authStorage2, envAccessToken2) {
15494
+ const cli2 = Cli9.create("shipping-address", {
15495
+ description: "Shipping address management commands"
15496
+ });
15497
+ cli2.command("list", {
15498
+ description: "List all shipping addresses on your account",
15499
+ outputPolicy: "agent-only",
15500
+ middleware: [requireAuth(authStorage2, envAccessToken2)],
15501
+ async run(c) {
15502
+ const resource = createResource();
15503
+ if (!c.agent && !c.formatExplicit) {
15504
+ return renderInteractive(
15505
+ /* @__PURE__ */ jsx22(ShippingAddressList, { resource, onComplete: () => {
15506
+ } }),
15507
+ () => resource.listShippingAddresses()
15508
+ );
15509
+ }
15510
+ return resource.listShippingAddresses();
15511
+ }
15512
+ });
15513
+ return cli2;
15514
+ }
15515
+
15516
+ // src/commands/sources/index.tsx
15517
+ import { Cli as Cli10 } from "incur";
15518
+
15519
+ // src/commands/sources/list.tsx
15520
+ import { Box as Box15, Text as Text17 } from "ink";
15521
+ import Spinner7 from "ink-spinner";
15522
+ import { useCallback as useCallback6 } from "react";
15523
+ import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
15524
+ var COLUMN_GAP2 = " ";
15525
+ var HORIZONTAL_PADDING = 4;
15526
+ function truncateCell2(value, width) {
15527
+ if (value.length <= width) {
15528
+ return value;
15529
+ }
15530
+ if (width <= 3) {
15531
+ return value.slice(0, width);
15532
+ }
15533
+ return `${value.slice(0, width - 3)}...`;
15534
+ }
15535
+ function formatCell2(value, width) {
15536
+ return truncateCell2(value, width).padEnd(width);
15537
+ }
15538
+ function sourceId(source, index) {
15539
+ return typeof source.id === "string" && source.id.length > 0 ? source.id : `source-${index + 1}`;
15540
+ }
15541
+ function statusFromValue(value) {
15542
+ if (value && typeof value === "object" && !Array.isArray(value)) {
15543
+ const status = value.status;
15544
+ return typeof status === "string" ? status : null;
15545
+ }
15546
+ return null;
15547
+ }
15548
+ function formatCapabilities(source) {
15549
+ const capabilities = source.capabilities;
15550
+ if (!capabilities || typeof capabilities !== "object") {
15551
+ return "-";
15552
+ }
15553
+ const entries = Object.entries(capabilities).map(([capability, value]) => {
15554
+ const status = statusFromValue(value);
15555
+ return status ? `${capability}:${status}` : capability;
15556
+ }).sort();
15557
+ return entries.length > 0 ? entries.join(", ") : "-";
15558
+ }
15559
+ function formatExternalConnection(source) {
15560
+ const status = statusFromValue(source.external_connection);
15561
+ return status ?? "-";
15562
+ }
15563
+ function sourceRow(source, index) {
15564
+ const capabilities = formatCapabilities(source);
15565
+ const external = formatExternalConnection(source);
15566
+ return {
15567
+ key: sourceId(source, index),
15568
+ name: source.name ?? "Source",
15569
+ type: source.type ?? "-",
15570
+ id: sourceId(source, index),
15571
+ capabilities,
15572
+ external
15573
+ };
15574
+ }
15575
+ function tableColumns() {
15576
+ return [
15577
+ { label: "Name", value: (row) => row.name, minWidth: 14, maxWidth: 24 },
15578
+ { label: "Type", value: (row) => row.type, minWidth: 10, maxWidth: 14 },
15579
+ { label: "ID", value: (row) => row.id, minWidth: 16, maxWidth: 48 },
15580
+ {
15581
+ label: "Capabilities",
15582
+ value: (row) => row.capabilities,
15583
+ minWidth: 8,
15584
+ maxWidth: 48
15585
+ },
15586
+ {
15587
+ label: "External connection status",
15588
+ value: (row) => row.external,
15589
+ minWidth: 8,
15590
+ maxWidth: 36
15591
+ }
15592
+ ];
15593
+ }
15594
+ function distributeWidths(columns, availableWidth) {
15595
+ const gapWidth = COLUMN_GAP2.length * Math.max(0, columns.length - 1);
15596
+ const contentWidth2 = Math.max(columns.length, availableWidth - gapWidth);
15597
+ const widths = columns.map((column) => column.minWidth);
15598
+ let remaining = contentWidth2 - widths.reduce((total, width) => total + width, 0);
15599
+ while (remaining > 0) {
15600
+ let changed = false;
15601
+ for (let index = 0; index < columns.length && remaining > 0; index += 1) {
15602
+ if (widths[index] >= columns[index].maxWidth) {
15603
+ continue;
15604
+ }
15605
+ widths[index] += 1;
15606
+ remaining -= 1;
15607
+ changed = true;
15608
+ }
15609
+ if (!changed) {
15610
+ break;
15611
+ }
14757
15612
  }
14758
- const address = addressRecord.address;
14759
- const lines = [formatStreetLine(address), formatLocalityLine(address)].filter(
14760
- (line) => Boolean(line)
15613
+ return widths;
15614
+ }
15615
+ function renderTableRows(rows, terminalWidth) {
15616
+ const columns = tableColumns();
15617
+ const availableWidth = contentWidth(terminalWidth);
15618
+ const widths = distributeWidths(columns, availableWidth);
15619
+ const headerRow = columns.map((column, index) => formatCell2(column.label, widths[index])).join(COLUMN_GAP2).slice(0, availableWidth);
15620
+ const separatorRow = "-".repeat(headerRow.length).slice(0, availableWidth);
15621
+ const bodyRows = rows.map(
15622
+ (row) => columns.map((column, index) => formatCell2(column.value(row), widths[index])).join(COLUMN_GAP2).slice(0, availableWidth)
14761
15623
  );
14762
- return lines.length > 0 ? lines : ["Address details unavailable"];
15624
+ return { headerRow, separatorRow, bodyRows };
14763
15625
  }
14764
- var ShippingAddressList = ({
15626
+ function contentWidth(terminalWidth) {
15627
+ return Math.max(1, terminalWidth - HORIZONTAL_PADDING);
15628
+ }
15629
+ var SourcesList = ({
14765
15630
  resource,
15631
+ params,
14766
15632
  onComplete
14767
15633
  }) => {
14768
- const action = useCallback4(
14769
- () => resource.listShippingAddresses(),
14770
- [resource]
15634
+ const action = useCallback6(
15635
+ () => resource.listSources(params),
15636
+ [resource, params]
15637
+ );
15638
+ const { status, data: page, error } = useAsyncAction(action, onComplete);
15639
+ const sources = page?.data ?? [];
15640
+ const nextCursor = page?.has_more && sources.length > 0 ? sources[sources.length - 1].id : null;
15641
+ const rows = sources.map(sourceRow);
15642
+ const terminalWidth = process.stdout.columns ?? 140;
15643
+ const { headerRow, separatorRow, bodyRows } = renderTableRows(
15644
+ rows,
15645
+ terminalWidth
14771
15646
  );
14772
- const {
14773
- status,
14774
- data: shippingAddresses,
14775
- error
14776
- } = useAsyncAction(action, onComplete);
14777
15647
  if (status === "loading") {
14778
- return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsxs13(Text15, { color: "cyan", children: [
14779
- /* @__PURE__ */ jsx19(Spinner5, { type: "dots" }),
14780
- " Loading shipping addresses..."
15648
+ return /* @__PURE__ */ jsx23(Box15, { children: /* @__PURE__ */ jsxs15(Text17, { color: "cyan", children: [
15649
+ /* @__PURE__ */ jsx23(Spinner7, { type: "dots" }),
15650
+ " Loading sources..."
14781
15651
  ] }) });
14782
15652
  }
14783
15653
  if (status === "error") {
14784
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
14785
- /* @__PURE__ */ jsx19(Text15, { color: "red", children: "\u2717 Failed to load shipping addresses" }),
14786
- /* @__PURE__ */ jsx19(Text15, { color: "red", children: error })
15654
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
15655
+ /* @__PURE__ */ jsx23(Text17, { color: "red", children: "Failed to load sources" }),
15656
+ /* @__PURE__ */ jsx23(Text17, { color: "red", children: error })
14787
15657
  ] });
14788
15658
  }
14789
- if (!shippingAddresses || shippingAddresses.length === 0) {
14790
- return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: "No shipping addresses found" }) });
15659
+ if (sources.length === 0) {
15660
+ return /* @__PURE__ */ jsx23(Box15, { children: /* @__PURE__ */ jsx23(Text17, { dimColor: true, children: "No sources found" }) });
14791
15661
  }
14792
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
14793
- /* @__PURE__ */ jsx19(Text15, { bold: true, children: "Shipping Addresses" }),
14794
- /* @__PURE__ */ jsx19(Box13, { flexDirection: "column", marginTop: 1, children: shippingAddresses.map((shippingAddress) => {
14795
- const addressName = shippingAddress.address?.name;
14796
- const nickname = shippingAddress.nickname ? ` (${shippingAddress.nickname})` : "";
14797
- return /* @__PURE__ */ jsxs13(
14798
- Box13,
14799
- {
14800
- flexDirection: "column",
14801
- paddingX: 2,
14802
- marginBottom: 1,
14803
- children: [
14804
- /* @__PURE__ */ jsxs13(Text15, { children: [
14805
- /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: shippingAddress.id }),
14806
- nickname,
14807
- shippingAddress.is_default ? /* @__PURE__ */ jsx19(Text15, { color: "green", children: " (default)" }) : null
14808
- ] }),
14809
- /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginTop: 1, children: [
14810
- addressName ? /* @__PURE__ */ jsx19(Text15, { bold: true, children: addressName }) : null,
14811
- formatAddressLines(shippingAddress).map((line) => /* @__PURE__ */ jsx19(Text15, { children: line }, `${shippingAddress.id}:${line}`))
14812
- ] })
14813
- ]
14814
- },
14815
- shippingAddress.id
14816
- );
14817
- }) })
15662
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
15663
+ /* @__PURE__ */ jsx23(Text17, { bold: true, children: "Sources" }),
15664
+ /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15665
+ /* @__PURE__ */ jsx23(Text17, { bold: true, children: headerRow }),
15666
+ /* @__PURE__ */ jsx23(Text17, { dimColor: true, children: separatorRow }),
15667
+ bodyRows.map((row, index) => /* @__PURE__ */ jsx23(Text17, { children: row }, rows[index].key))
15668
+ ] }),
15669
+ page?.has_more !== void 0 ? /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginTop: 1, children: [
15670
+ /* @__PURE__ */ jsxs15(Text17, { dimColor: true, children: [
15671
+ "has_more: ",
15672
+ String(page.has_more)
15673
+ ] }),
15674
+ typeof nextCursor === "string" && nextCursor.length > 0 ? /* @__PURE__ */ jsx23(Text17, { dimColor: true, children: `next page: --starting-after ${nextCursor}` }) : null
15675
+ ] }) : null
14818
15676
  ] });
14819
15677
  };
14820
15678
 
14821
- // src/commands/shipping-address/index.tsx
14822
- import { jsx as jsx20 } from "react/jsx-runtime";
14823
- function createShippingAddressCli(createResource, authStorage2, envAccessToken2) {
14824
- const cli2 = Cli8.create("shipping-address", {
14825
- description: "Shipping address management commands"
15679
+ // src/commands/sources/schema.ts
15680
+ import { z as z8 } from "incur";
15681
+ var listOptions2 = z8.object({
15682
+ limit: z8.coerce.number().int().positive().max(100).optional().describe("Maximum number of sources to return (1-100)."),
15683
+ startingAfter: z8.string().optional().describe("Cursor: return sources after this source ID."),
15684
+ endingBefore: z8.string().optional().describe("Cursor: return sources before this source ID.")
15685
+ });
15686
+
15687
+ // src/commands/sources/index.tsx
15688
+ import { jsx as jsx24 } from "react/jsx-runtime";
15689
+ function createSourcesCli(createResource, authStorage2, envAccessToken2) {
15690
+ const cli2 = Cli10.create("sources", {
15691
+ description: "List sources from your Link wallet"
14826
15692
  });
14827
15693
  cli2.command("list", {
14828
- description: "List all shipping addresses on your account",
15694
+ description: "List sources from your Link wallet",
15695
+ options: listOptions2,
14829
15696
  outputPolicy: "agent-only",
14830
15697
  middleware: [requireAuth(authStorage2, envAccessToken2)],
14831
15698
  async run(c) {
15699
+ const opts = c.options;
14832
15700
  const resource = createResource();
15701
+ const params = {};
15702
+ if (opts.limit !== void 0) params.limit = opts.limit;
15703
+ if (opts.startingAfter !== void 0)
15704
+ params.starting_after = opts.startingAfter;
15705
+ if (opts.endingBefore !== void 0)
15706
+ params.ending_before = opts.endingBefore;
14833
15707
  if (!c.agent && !c.formatExplicit) {
14834
15708
  return renderInteractive(
14835
- /* @__PURE__ */ jsx20(ShippingAddressList, { resource, onComplete: () => {
14836
- } }),
14837
- () => resource.listShippingAddresses()
15709
+ /* @__PURE__ */ jsx24(
15710
+ SourcesList,
15711
+ {
15712
+ resource,
15713
+ params,
15714
+ onComplete: () => {
15715
+ }
15716
+ }
15717
+ ),
15718
+ () => resource.listSources(params)
14838
15719
  );
14839
15720
  }
14840
- return resource.listShippingAddresses();
15721
+ return resource.listSources(params);
14841
15722
  }
14842
15723
  });
14843
15724
  return cli2;
14844
15725
  }
14845
15726
 
14846
15727
  // src/commands/spend-request/index.tsx
14847
- import { Cli as Cli9, z as z9 } from "incur";
15728
+ import { Cli as Cli11, z as z11 } from "incur";
14848
15729
 
14849
15730
  // src/utils/credential-output.ts
14850
15731
  import { constants } from "fs";
@@ -14902,21 +15783,21 @@ async function writeCredentialFile(filePath, data, force) {
14902
15783
  }
14903
15784
 
14904
15785
  // src/utils/line-item-parser.ts
14905
- import { z as z7 } from "zod";
14906
- var LineItemSchema = z7.object({
14907
- name: z7.string(),
14908
- url: z7.string().optional(),
14909
- image_url: z7.string().optional(),
14910
- description: z7.string().optional(),
14911
- sku: z7.string().optional(),
14912
- quantity: z7.coerce.number().optional(),
14913
- unit_amount: z7.coerce.number().optional(),
14914
- product_url: z7.string().optional()
15786
+ import { z as z9 } from "zod";
15787
+ var LineItemSchema = z9.object({
15788
+ name: z9.string(),
15789
+ url: z9.string().optional(),
15790
+ image_url: z9.string().optional(),
15791
+ description: z9.string().optional(),
15792
+ sku: z9.string().optional(),
15793
+ quantity: z9.coerce.number().optional(),
15794
+ unit_amount: z9.coerce.number().optional(),
15795
+ product_url: z9.string().optional()
14915
15796
  }).strict();
14916
- var TotalSchema = z7.object({
14917
- type: z7.string(),
14918
- display_text: z7.string(),
14919
- amount: z7.coerce.number()
15797
+ var TotalSchema = z9.object({
15798
+ type: z9.string(),
15799
+ display_text: z9.string(),
15800
+ amount: z9.coerce.number()
14920
15801
  }).strict();
14921
15802
  function parseKvString(raw) {
14922
15803
  const result = {};
@@ -14946,7 +15827,7 @@ function parseLineItemFlag(raw) {
14946
15827
  try {
14947
15828
  return LineItemSchema.parse(obj);
14948
15829
  } catch (err) {
14949
- if (err instanceof z7.ZodError)
15830
+ if (err instanceof z9.ZodError)
14950
15831
  throw formatZodError(err, "Line item", LineItemSchema);
14951
15832
  throw err;
14952
15833
  }
@@ -14956,65 +15837,65 @@ function parseTotalFlag(raw) {
14956
15837
  try {
14957
15838
  return TotalSchema.parse(obj);
14958
15839
  } catch (err) {
14959
- if (err instanceof z7.ZodError)
15840
+ if (err instanceof z9.ZodError)
14960
15841
  throw formatZodError(err, "Total", TotalSchema);
14961
15842
  throw err;
14962
15843
  }
14963
15844
  }
14964
15845
 
14965
15846
  // src/commands/spend-request/cancel.tsx
14966
- import { Box as Box14, Text as Text16 } from "ink";
14967
- import Spinner6 from "ink-spinner";
14968
- import { useCallback as useCallback5 } from "react";
14969
- import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
15847
+ import { Box as Box16, Text as Text18 } from "ink";
15848
+ import Spinner8 from "ink-spinner";
15849
+ import { useCallback as useCallback7 } from "react";
15850
+ import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
14970
15851
  var CancelSpendRequest = ({
14971
15852
  repository,
14972
15853
  id,
14973
15854
  onComplete
14974
15855
  }) => {
14975
- const action = useCallback5(
15856
+ const action = useCallback7(
14976
15857
  () => repository.cancelSpendRequest(id),
14977
15858
  [repository, id]
14978
15859
  );
14979
15860
  const { status, data: request, error } = useAsyncAction(action, onComplete);
14980
15861
  if (status === "loading") {
14981
- return /* @__PURE__ */ jsx21(Box14, { children: /* @__PURE__ */ jsxs14(Text16, { color: "cyan", children: [
14982
- /* @__PURE__ */ jsx21(Spinner6, { type: "dots" }),
15862
+ return /* @__PURE__ */ jsx25(Box16, { children: /* @__PURE__ */ jsxs16(Text18, { color: "cyan", children: [
15863
+ /* @__PURE__ */ jsx25(Spinner8, { type: "dots" }),
14983
15864
  " Canceling spend request ",
14984
15865
  id,
14985
15866
  "..."
14986
15867
  ] }) });
14987
15868
  }
14988
15869
  if (status === "error") {
14989
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
14990
- /* @__PURE__ */ jsx21(Text16, { color: "red", children: "\u2717 Failed to cancel spend request" }),
14991
- /* @__PURE__ */ jsx21(Text16, { color: "red", children: error })
15870
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
15871
+ /* @__PURE__ */ jsx25(Text18, { color: "red", children: "\u2717 Failed to cancel spend request" }),
15872
+ /* @__PURE__ */ jsx25(Text18, { color: "red", children: error })
14992
15873
  ] });
14993
15874
  }
14994
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
14995
- /* @__PURE__ */ jsx21(Text16, { color: "green", children: "\u2713 Spend request canceled" }),
14996
- /* @__PURE__ */ jsx21(Box14, { flexDirection: "column", marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs14(Text16, { children: [
15875
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
15876
+ /* @__PURE__ */ jsx25(Text18, { color: "green", children: "\u2713 Spend request canceled" }),
15877
+ /* @__PURE__ */ jsx25(Box16, { flexDirection: "column", marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs16(Text18, { children: [
14997
15878
  "ID: ",
14998
- /* @__PURE__ */ jsx21(Text16, { bold: true, children: request?.id })
15879
+ /* @__PURE__ */ jsx25(Text18, { bold: true, children: request?.id })
14999
15880
  ] }) })
15000
15881
  ] });
15001
15882
  };
15002
15883
 
15003
15884
  // src/commands/spend-request/create.tsx
15004
- import { Box as Box16, Text as Text18, useApp as useApp4 } from "ink";
15005
- import Spinner8 from "ink-spinner";
15006
- import { useCallback as useCallback6, useEffect as useEffect9, useState as useState9 } from "react";
15885
+ import { Box as Box18, Text as Text20, useApp as useApp4 } from "ink";
15886
+ import Spinner10 from "ink-spinner";
15887
+ import { useCallback as useCallback8, useEffect as useEffect9, useState as useState9 } from "react";
15007
15888
 
15008
15889
  // src/commands/spend-request/approval-waiting-view.tsx
15009
- import { Box as Box15, Text as Text17 } from "ink";
15010
- import Spinner7 from "ink-spinner";
15011
- import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
15890
+ import { Box as Box17, Text as Text19 } from "ink";
15891
+ import Spinner9 from "ink-spinner";
15892
+ import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
15012
15893
  var ApprovalWaitingView = ({
15013
15894
  status,
15014
15895
  approvalUrl
15015
- }) => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", paddingY: 1, children: [
15016
- /* @__PURE__ */ jsxs15(
15017
- Box15,
15896
+ }) => /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", paddingY: 1, children: [
15897
+ /* @__PURE__ */ jsxs17(
15898
+ Box17,
15018
15899
  {
15019
15900
  flexDirection: "column",
15020
15901
  borderStyle: "round",
@@ -15022,20 +15903,20 @@ var ApprovalWaitingView = ({
15022
15903
  paddingX: 2,
15023
15904
  paddingY: 1,
15024
15905
  children: [
15025
- /* @__PURE__ */ jsxs15(Text17, { children: [
15906
+ /* @__PURE__ */ jsxs17(Text19, { children: [
15026
15907
  "Approve at:",
15027
15908
  " ",
15028
- /* @__PURE__ */ jsx22(Text17, { bold: true, color: "cyan", children: approvalUrl })
15909
+ /* @__PURE__ */ jsx26(Text19, { bold: true, color: "cyan", children: approvalUrl })
15029
15910
  ] }),
15030
- /* @__PURE__ */ jsx22(Text17, { dimColor: true, children: "Press Enter to open in browser" })
15911
+ /* @__PURE__ */ jsx26(Text19, { dimColor: true, children: "Press Enter to open in browser" })
15031
15912
  ]
15032
15913
  }
15033
15914
  ),
15034
- /* @__PURE__ */ jsx22(AppDownloadQrCodes, {}),
15035
- /* @__PURE__ */ jsx22(Box15, { marginTop: 1, children: status === "polling" ? /* @__PURE__ */ jsxs15(Text17, { color: "cyan", children: [
15036
- /* @__PURE__ */ jsx22(Spinner7, { type: "dots" }),
15915
+ /* @__PURE__ */ jsx26(AppDownloadQrCodes, {}),
15916
+ /* @__PURE__ */ jsx26(Box17, { marginTop: 1, children: status === "polling" ? /* @__PURE__ */ jsxs17(Text19, { color: "cyan", children: [
15917
+ /* @__PURE__ */ jsx26(Spinner9, { type: "dots" }),
15037
15918
  " Waiting for approval..."
15038
- ] }) : /* @__PURE__ */ jsx22(Text17, { dimColor: true, children: "Waiting..." }) })
15919
+ ] }) : /* @__PURE__ */ jsx26(Text19, { dimColor: true, children: "Waiting..." }) })
15039
15920
  ] });
15040
15921
 
15041
15922
  // src/commands/spend-request/use-approval-polling.ts
@@ -15104,7 +15985,7 @@ function useApprovalPolling({
15104
15985
  }
15105
15986
 
15106
15987
  // src/commands/spend-request/create.tsx
15107
- import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
15988
+ import { Fragment as Fragment4, jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
15108
15989
  var CreateSpendRequest = ({
15109
15990
  repository,
15110
15991
  params,
@@ -15121,18 +16002,18 @@ var CreateSpendRequest = ({
15121
16002
  const [fileError, setFileError] = useState9("");
15122
16003
  const approvalUrl = request?.approval_url ?? "";
15123
16004
  const { exit } = useApp4();
15124
- const completeAndExit = useCallback6(
16005
+ const completeAndExit = useCallback8(
15125
16006
  (result) => {
15126
16007
  onComplete(result);
15127
16008
  exit();
15128
16009
  },
15129
16010
  [onComplete, exit]
15130
16011
  );
15131
- const onSuccess = useCallback6(
16012
+ const onSuccess = useCallback8(
15132
16013
  (result) => setRequest(result),
15133
16014
  []
15134
16015
  );
15135
- const onError = useCallback6((msg) => setError(msg), []);
16016
+ const onError = useCallback8((msg) => setError(msg), []);
15136
16017
  useApprovalPolling({
15137
16018
  status,
15138
16019
  setStatus,
@@ -15179,105 +16060,105 @@ var CreateSpendRequest = ({
15179
16060
  writeCredentialFile(outputFile, fileData, force ?? false).then((path7) => setOutputFilePath(path7)).catch((err) => setFileError(err.message));
15180
16061
  }, [status, outputFile, force, request]);
15181
16062
  if (status === "creating") {
15182
- return /* @__PURE__ */ jsx23(Box16, { children: /* @__PURE__ */ jsxs16(Text18, { color: "cyan", children: [
15183
- /* @__PURE__ */ jsx23(Spinner8, { type: "dots" }),
16063
+ return /* @__PURE__ */ jsx27(Box18, { children: /* @__PURE__ */ jsxs18(Text20, { color: "cyan", children: [
16064
+ /* @__PURE__ */ jsx27(Spinner10, { type: "dots" }),
15184
16065
  " Creating spend request..."
15185
16066
  ] }) });
15186
16067
  }
15187
16068
  if (status === "error") {
15188
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
15189
- /* @__PURE__ */ jsx23(Text18, { color: "red", children: "\u2717 Failed to create spend request" }),
15190
- /* @__PURE__ */ jsx23(Text18, { color: "red", children: error }),
15191
- verificationUrl && /* @__PURE__ */ jsxs16(Text18, { color: "red", children: [
16069
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
16070
+ /* @__PURE__ */ jsx27(Text20, { color: "red", children: "\u2717 Failed to create spend request" }),
16071
+ /* @__PURE__ */ jsx27(Text20, { color: "red", children: error }),
16072
+ verificationUrl && /* @__PURE__ */ jsxs18(Text20, { color: "red", children: [
15192
16073
  "Complete additional verification at: ",
15193
16074
  verificationUrl
15194
16075
  ] })
15195
16076
  ] });
15196
16077
  }
15197
16078
  if (status === "success") {
15198
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
15199
- /* @__PURE__ */ jsx23(Text18, { color: "green", children: "\u2713 Spend request created" }),
15200
- /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15201
- /* @__PURE__ */ jsxs16(Text18, { children: [
16079
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
16080
+ /* @__PURE__ */ jsx27(Text20, { color: "green", children: "\u2713 Spend request created" }),
16081
+ /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16082
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15202
16083
  "ID: ",
15203
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.id })
16084
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.id })
15204
16085
  ] }),
15205
- /* @__PURE__ */ jsxs16(Text18, { children: [
16086
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15206
16087
  "Status: ",
15207
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.status })
16088
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.status })
15208
16089
  ] }),
15209
- /* @__PURE__ */ jsxs16(Text18, { children: [
16090
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15210
16091
  "Amount:",
15211
16092
  " ",
15212
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.amount != null ? `${request.amount} ${request.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
16093
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.amount != null ? `${request.amount} ${request.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
15213
16094
  ] }),
15214
- /* @__PURE__ */ jsxs16(Text18, { children: [
16095
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15215
16096
  "Merchant: ",
15216
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.merchant_name })
16097
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.merchant_name })
15217
16098
  ] }),
15218
- /* @__PURE__ */ jsxs16(Text18, { children: [
16099
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15219
16100
  "Line Items:",
15220
16101
  " ",
15221
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") || "N/A" })
16102
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") || "N/A" })
15222
16103
  ] }),
15223
- request?.credential_type === "shared_payment_token" && request.shared_payment_token && /* @__PURE__ */ jsxs16(Text18, { children: [
16104
+ request?.credential_type === "shared_payment_token" && request.shared_payment_token && /* @__PURE__ */ jsxs18(Text20, { children: [
15224
16105
  "Token: ",
15225
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.shared_payment_token.id })
16106
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.shared_payment_token.id })
15226
16107
  ] })
15227
16108
  ] }),
15228
- request?.card && !outputFile && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, children: [
15229
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: "Card Details:" }),
15230
- /* @__PURE__ */ jsxs16(Text18, { children: [
16109
+ request?.card && !outputFile && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, children: [
16110
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: "Card Details:" }),
16111
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15231
16112
  " ",
15232
16113
  "Number: ",
15233
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.card.number })
16114
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.card.number })
15234
16115
  ] }),
15235
- /* @__PURE__ */ jsxs16(Text18, { children: [
16116
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15236
16117
  " ",
15237
16118
  "Brand: ",
15238
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.card.brand })
16119
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.card.brand })
15239
16120
  ] }),
15240
- /* @__PURE__ */ jsxs16(Text18, { children: [
16121
+ /* @__PURE__ */ jsxs18(Text20, { children: [
15241
16122
  " ",
15242
16123
  "Expiry:",
15243
16124
  " ",
15244
- /* @__PURE__ */ jsxs16(Text18, { bold: true, children: [
16125
+ /* @__PURE__ */ jsxs18(Text20, { bold: true, children: [
15245
16126
  String(request.card.exp_month).padStart(2, "0"),
15246
16127
  "/",
15247
16128
  request.card.exp_year
15248
16129
  ] })
15249
16130
  ] }),
15250
- request.card.cvc && /* @__PURE__ */ jsxs16(Text18, { children: [
16131
+ request.card.cvc && /* @__PURE__ */ jsxs18(Text20, { children: [
15251
16132
  " ",
15252
16133
  "CVC: ",
15253
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.card.cvc })
16134
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.card.cvc })
15254
16135
  ] }),
15255
- request.card.valid_until && /* @__PURE__ */ jsxs16(Text18, { children: [
16136
+ request.card.valid_until && /* @__PURE__ */ jsxs18(Text20, { children: [
15256
16137
  " ",
15257
16138
  "Valid Until: ",
15258
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request.card.valid_until })
16139
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request.card.valid_until })
15259
16140
  ] })
15260
16141
  ] }),
15261
- request?.card && outputFile && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, children: [
15262
- outputFilePath && /* @__PURE__ */ jsxs16(Text18, { color: "green", children: [
16142
+ request?.card && outputFile && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, children: [
16143
+ outputFilePath && /* @__PURE__ */ jsxs18(Text20, { color: "green", children: [
15263
16144
  "Card credentials written to ",
15264
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: outputFilePath })
16145
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: outputFilePath })
15265
16146
  ] }),
15266
- fileError && /* @__PURE__ */ jsxs16(Text18, { color: "red", children: [
16147
+ fileError && /* @__PURE__ */ jsxs18(Text20, { color: "red", children: [
15267
16148
  "Failed to write card file: ",
15268
16149
  fileError
15269
16150
  ] })
15270
16151
  ] }),
15271
- /* @__PURE__ */ jsx23(AppDownloadQrCodes, {})
16152
+ /* @__PURE__ */ jsx27(AppDownloadQrCodes, {})
15272
16153
  ] });
15273
16154
  }
15274
- return /* @__PURE__ */ jsxs16(Fragment4, { children: [
15275
- /* @__PURE__ */ jsx23(Box16, { children: /* @__PURE__ */ jsxs16(Text18, { color: "green", children: [
16155
+ return /* @__PURE__ */ jsxs18(Fragment4, { children: [
16156
+ /* @__PURE__ */ jsx27(Box18, { children: /* @__PURE__ */ jsxs18(Text20, { color: "green", children: [
15276
16157
  "\u2713 Spend request created (ID: ",
15277
- /* @__PURE__ */ jsx23(Text18, { bold: true, children: request?.id }),
16158
+ /* @__PURE__ */ jsx27(Text20, { bold: true, children: request?.id }),
15278
16159
  ")"
15279
16160
  ] }) }),
15280
- /* @__PURE__ */ jsx23(
16161
+ /* @__PURE__ */ jsx27(
15281
16162
  ApprovalWaitingView,
15282
16163
  {
15283
16164
  status,
@@ -15288,21 +16169,21 @@ var CreateSpendRequest = ({
15288
16169
  };
15289
16170
 
15290
16171
  // src/commands/spend-request/list.tsx
15291
- import { Box as Box17, Text as Text19, useApp as useApp5 } from "ink";
15292
- import Spinner9 from "ink-spinner";
15293
- import { useCallback as useCallback7 } from "react";
15294
- import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
16172
+ import { Box as Box19, Text as Text21, useApp as useApp5 } from "ink";
16173
+ import Spinner11 from "ink-spinner";
16174
+ import { useCallback as useCallback9 } from "react";
16175
+ import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
15295
16176
  var SpendRequestList = ({
15296
16177
  repository,
15297
16178
  includeHistory = false,
15298
16179
  onComplete
15299
16180
  }) => {
15300
16181
  const { exit } = useApp5();
15301
- const action = useCallback7(
16182
+ const action = useCallback9(
15302
16183
  () => repository.listSpendRequests({ includeHistory }),
15303
16184
  [repository, includeHistory]
15304
16185
  );
15305
- const wrappedOnComplete = useCallback7(
16186
+ const wrappedOnComplete = useCallback9(
15306
16187
  (result) => {
15307
16188
  onComplete(result);
15308
16189
  exit();
@@ -15315,29 +16196,29 @@ var SpendRequestList = ({
15315
16196
  error
15316
16197
  } = useAsyncAction(action, wrappedOnComplete);
15317
16198
  if (status === "loading") {
15318
- return /* @__PURE__ */ jsx24(Box17, { children: /* @__PURE__ */ jsxs17(Text19, { color: "cyan", children: [
15319
- /* @__PURE__ */ jsx24(Spinner9, { type: "dots" }),
16199
+ return /* @__PURE__ */ jsx28(Box19, { children: /* @__PURE__ */ jsxs19(Text21, { color: "cyan", children: [
16200
+ /* @__PURE__ */ jsx28(Spinner11, { type: "dots" }),
15320
16201
  " Loading spend requests..."
15321
16202
  ] }) });
15322
16203
  }
15323
16204
  if (status === "error") {
15324
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
15325
- /* @__PURE__ */ jsx24(Text19, { color: "red", children: "\u2717 Failed to load spend requests" }),
15326
- /* @__PURE__ */ jsx24(Text19, { color: "red", children: error })
16205
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
16206
+ /* @__PURE__ */ jsx28(Text21, { color: "red", children: "\u2717 Failed to load spend requests" }),
16207
+ /* @__PURE__ */ jsx28(Text21, { color: "red", children: error })
15327
16208
  ] });
15328
16209
  }
15329
16210
  if (!requests || requests.length === 0) {
15330
- return /* @__PURE__ */ jsx24(Box17, { children: /* @__PURE__ */ jsx24(Text19, { dimColor: true, children: includeHistory ? "No spend requests found" : "No active spend requests found" }) });
16211
+ return /* @__PURE__ */ jsx28(Box19, { children: /* @__PURE__ */ jsx28(Text21, { dimColor: true, children: includeHistory ? "No spend requests found" : "No active spend requests found" }) });
15331
16212
  }
15332
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
15333
- /* @__PURE__ */ jsx24(Text19, { bold: true, children: includeHistory ? "All Spend Requests" : "Active Spend Requests" }),
15334
- /* @__PURE__ */ jsx24(Box17, { flexDirection: "column", marginTop: 1, children: requests.map((sr) => {
16213
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
16214
+ /* @__PURE__ */ jsx28(Text21, { bold: true, children: includeHistory ? "All Spend Requests" : "Active Spend Requests" }),
16215
+ /* @__PURE__ */ jsx28(Box19, { flexDirection: "column", marginTop: 1, children: requests.map((sr) => {
15335
16216
  const statusColor = sr.status === "approved" ? "green" : sr.status === "pending_approval" ? "yellow" : "white";
15336
16217
  const amount = sr.amount != null ? `$${(sr.amount / 100).toFixed(2)} ${(sr.currency ?? "usd").toUpperCase()}` : "";
15337
- return /* @__PURE__ */ jsx24(Box17, { paddingX: 2, children: /* @__PURE__ */ jsxs17(Text19, { children: [
15338
- /* @__PURE__ */ jsx24(Text19, { dimColor: true, children: sr.id }),
16218
+ return /* @__PURE__ */ jsx28(Box19, { paddingX: 2, children: /* @__PURE__ */ jsxs19(Text21, { children: [
16219
+ /* @__PURE__ */ jsx28(Text21, { dimColor: true, children: sr.id }),
15339
16220
  " ",
15340
- /* @__PURE__ */ jsx24(Text19, { color: statusColor, children: sr.status }),
16221
+ /* @__PURE__ */ jsx28(Text21, { color: statusColor, children: sr.status }),
15341
16222
  sr.merchant_name ? ` ${sr.merchant_name}` : "",
15342
16223
  amount ? ` ${amount}` : ""
15343
16224
  ] }) }, sr.id);
@@ -15346,10 +16227,10 @@ var SpendRequestList = ({
15346
16227
  };
15347
16228
 
15348
16229
  // src/commands/spend-request/request-approval.tsx
15349
- import { Box as Box18, Text as Text20, useApp as useApp6 } from "ink";
15350
- import Spinner10 from "ink-spinner";
15351
- import { useCallback as useCallback8, useEffect as useEffect10, useState as useState10 } from "react";
15352
- import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
16230
+ import { Box as Box20, Text as Text22, useApp as useApp6 } from "ink";
16231
+ import Spinner12 from "ink-spinner";
16232
+ import { useCallback as useCallback10, useEffect as useEffect10, useState as useState10 } from "react";
16233
+ import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
15353
16234
  var RequestApproval = ({
15354
16235
  repository,
15355
16236
  id,
@@ -15361,15 +16242,15 @@ var RequestApproval = ({
15361
16242
  const [error, setError] = useState10("");
15362
16243
  const [verificationUrl, setVerificationUrl] = useState10("");
15363
16244
  const { exit } = useApp6();
15364
- const completeAndExit = useCallback8(
16245
+ const completeAndExit = useCallback10(
15365
16246
  (result2) => {
15366
16247
  onComplete(result2);
15367
16248
  exit();
15368
16249
  },
15369
16250
  [onComplete, exit]
15370
16251
  );
15371
- const onSuccess = useCallback8((r) => setResult(r), []);
15372
- const onError = useCallback8((msg) => setError(msg), []);
16252
+ const onSuccess = useCallback10((r) => setResult(r), []);
16253
+ const onError = useCallback10((msg) => setError(msg), []);
15373
16254
  useApprovalPolling({
15374
16255
  status,
15375
16256
  setStatus,
@@ -15402,50 +16283,50 @@ var RequestApproval = ({
15402
16283
  request();
15403
16284
  }, [repository, id, exit, onComplete]);
15404
16285
  if (status === "requesting") {
15405
- return /* @__PURE__ */ jsx25(Box18, { children: /* @__PURE__ */ jsxs18(Text20, { color: "cyan", children: [
15406
- /* @__PURE__ */ jsx25(Spinner10, { type: "dots" }),
16286
+ return /* @__PURE__ */ jsx29(Box20, { children: /* @__PURE__ */ jsxs20(Text22, { color: "cyan", children: [
16287
+ /* @__PURE__ */ jsx29(Spinner12, { type: "dots" }),
15407
16288
  " Requesting approval..."
15408
16289
  ] }) });
15409
16290
  }
15410
16291
  if (status === "error") {
15411
- return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
15412
- /* @__PURE__ */ jsx25(Text20, { color: "red", children: "\u2717 Failed to request approval" }),
15413
- /* @__PURE__ */ jsx25(Text20, { color: "red", children: error }),
15414
- verificationUrl && /* @__PURE__ */ jsxs18(Text20, { color: "red", children: [
16292
+ return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
16293
+ /* @__PURE__ */ jsx29(Text22, { color: "red", children: "\u2717 Failed to request approval" }),
16294
+ /* @__PURE__ */ jsx29(Text22, { color: "red", children: error }),
16295
+ verificationUrl && /* @__PURE__ */ jsxs20(Text22, { color: "red", children: [
15415
16296
  "Complete additional verification at: ",
15416
16297
  verificationUrl
15417
16298
  ] })
15418
16299
  ] });
15419
16300
  }
15420
16301
  if (status === "success") {
15421
- return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
15422
- /* @__PURE__ */ jsx25(Text20, { color: "green", children: "\u2713 Approval completed" }),
15423
- /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15424
- /* @__PURE__ */ jsxs18(Text20, { children: [
16302
+ return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
16303
+ /* @__PURE__ */ jsx29(Text22, { color: "green", children: "\u2713 Approval completed" }),
16304
+ /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16305
+ /* @__PURE__ */ jsxs20(Text22, { children: [
15425
16306
  "ID: ",
15426
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result?.id })
16307
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result?.id })
15427
16308
  ] }),
15428
- /* @__PURE__ */ jsxs18(Text20, { children: [
16309
+ /* @__PURE__ */ jsxs20(Text22, { children: [
15429
16310
  "Status: ",
15430
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result?.status })
16311
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result?.status })
15431
16312
  ] }),
15432
- /* @__PURE__ */ jsxs18(Text20, { children: [
16313
+ /* @__PURE__ */ jsxs20(Text22, { children: [
15433
16314
  "Amount:",
15434
16315
  " ",
15435
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result?.amount != null ? `${result.amount} ${result.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
16316
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result?.amount != null ? `${result.amount} ${result.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
15436
16317
  ] }),
15437
- /* @__PURE__ */ jsxs18(Text20, { children: [
16318
+ /* @__PURE__ */ jsxs20(Text22, { children: [
15438
16319
  "Merchant: ",
15439
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result?.merchant_name })
16320
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result?.merchant_name })
15440
16321
  ] }),
15441
- result?.credential_type === "shared_payment_token" && result.shared_payment_token && /* @__PURE__ */ jsxs18(Text20, { children: [
16322
+ result?.credential_type === "shared_payment_token" && result.shared_payment_token && /* @__PURE__ */ jsxs20(Text22, { children: [
15442
16323
  "Token: ",
15443
- /* @__PURE__ */ jsx25(Text20, { bold: true, children: result.shared_payment_token.id })
16324
+ /* @__PURE__ */ jsx29(Text22, { bold: true, children: result.shared_payment_token.id })
15444
16325
  ] })
15445
16326
  ] })
15446
16327
  ] });
15447
16328
  }
15448
- return /* @__PURE__ */ jsx25(
16329
+ return /* @__PURE__ */ jsx29(
15449
16330
  ApprovalWaitingView,
15450
16331
  {
15451
16332
  status,
@@ -15455,10 +16336,10 @@ var RequestApproval = ({
15455
16336
  };
15456
16337
 
15457
16338
  // src/commands/spend-request/retrieve.tsx
15458
- import { Box as Box19, Text as Text21 } from "ink";
15459
- import Spinner11 from "ink-spinner";
16339
+ import { Box as Box21, Text as Text23 } from "ink";
16340
+ import Spinner13 from "ink-spinner";
15460
16341
  import { useEffect as useEffect11, useRef as useRef5, useState as useState11 } from "react";
15461
- import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
16342
+ import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
15462
16343
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
15463
16344
  "approved",
15464
16345
  "denied",
@@ -15582,121 +16463,121 @@ var RetrieveSpendRequest = ({
15582
16463
  };
15583
16464
  }, [phase, repository, id, include, timeout, onComplete]);
15584
16465
  if (phase === "fetching") {
15585
- return /* @__PURE__ */ jsx26(Box19, { children: /* @__PURE__ */ jsxs19(Text21, { color: "cyan", children: [
15586
- /* @__PURE__ */ jsx26(Spinner11, { type: "dots" }),
16466
+ return /* @__PURE__ */ jsx30(Box21, { children: /* @__PURE__ */ jsxs21(Text23, { color: "cyan", children: [
16467
+ /* @__PURE__ */ jsx30(Spinner13, { type: "dots" }),
15587
16468
  " Retrieving spend request ",
15588
16469
  id,
15589
16470
  "..."
15590
16471
  ] }) });
15591
16472
  }
15592
16473
  if (phase === "error") {
15593
- return /* @__PURE__ */ jsx26(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsxs19(Text21, { color: "red", children: [
16474
+ return /* @__PURE__ */ jsx30(Box21, { flexDirection: "column", children: /* @__PURE__ */ jsxs21(Text23, { color: "red", children: [
15594
16475
  "\u2717 ",
15595
16476
  error
15596
16477
  ] }) });
15597
16478
  }
15598
16479
  if (phase === "timeout") {
15599
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15600
- /* @__PURE__ */ jsxs19(Text21, { color: "yellow", children: [
16480
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16481
+ /* @__PURE__ */ jsxs21(Text23, { color: "yellow", children: [
15601
16482
  "\u2717 Timed out waiting for approval after ",
15602
16483
  timeout,
15603
16484
  "s"
15604
16485
  ] }),
15605
- request && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15606
- /* @__PURE__ */ jsxs19(Text21, { children: [
16486
+ request && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16487
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15607
16488
  "ID: ",
15608
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.id })
16489
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.id })
15609
16490
  ] }),
15610
- /* @__PURE__ */ jsxs19(Text21, { children: [
16491
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15611
16492
  "Status: ",
15612
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.status })
16493
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.status })
15613
16494
  ] })
15614
16495
  ] })
15615
16496
  ] });
15616
16497
  }
15617
16498
  if (phase === "polling") {
15618
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15619
- /* @__PURE__ */ jsx26(Box19, { children: /* @__PURE__ */ jsxs19(Text21, { color: "cyan", children: [
15620
- /* @__PURE__ */ jsx26(Spinner11, { type: "dots" }),
16499
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16500
+ /* @__PURE__ */ jsx30(Box21, { children: /* @__PURE__ */ jsxs21(Text23, { color: "cyan", children: [
16501
+ /* @__PURE__ */ jsx30(Spinner13, { type: "dots" }),
15621
16502
  " Awaiting approval... (",
15622
16503
  elapsed,
15623
16504
  "s elapsed)"
15624
16505
  ] }) }),
15625
- request?.approval_url && /* @__PURE__ */ jsx26(Box19, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs19(Text21, { dimColor: true, children: [
16506
+ request?.approval_url && /* @__PURE__ */ jsx30(Box21, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs21(Text23, { dimColor: true, children: [
15626
16507
  "Approval URL: ",
15627
- /* @__PURE__ */ jsx26(Text21, { color: "cyan", children: request.approval_url })
16508
+ /* @__PURE__ */ jsx30(Text23, { color: "cyan", children: request.approval_url })
15628
16509
  ] }) })
15629
16510
  ] });
15630
16511
  }
15631
16512
  if (phase === "finalized") {
15632
16513
  const psd = request?.payment_status_details;
15633
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15634
- /* @__PURE__ */ jsxs19(Text21, { color: "yellow", children: [
16514
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16515
+ /* @__PURE__ */ jsxs21(Text23, { color: "yellow", children: [
15635
16516
  "Spend request reached terminal status: ",
15636
16517
  request?.status
15637
16518
  ] }),
15638
- /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15639
- /* @__PURE__ */ jsxs19(Text21, { children: [
16519
+ /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16520
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15640
16521
  "ID: ",
15641
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.id })
16522
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.id })
15642
16523
  ] }),
15643
- /* @__PURE__ */ jsxs19(Text21, { children: [
16524
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15644
16525
  "Status: ",
15645
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.status })
16526
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.status })
15646
16527
  ] }),
15647
- psd && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15648
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: "Payment Details:" }),
15649
- /* @__PURE__ */ jsxs19(Text21, { children: [
16528
+ psd && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16529
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: "Payment Details:" }),
16530
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15650
16531
  " ",
15651
16532
  "Outcome:",
15652
16533
  " ",
15653
- /* @__PURE__ */ jsx26(Text21, { bold: true, color: psd.outcome === "success" ? "green" : "red", children: psd.outcome })
16534
+ /* @__PURE__ */ jsx30(Text23, { bold: true, color: psd.outcome === "success" ? "green" : "red", children: psd.outcome })
15654
16535
  ] }),
15655
- psd.code && /* @__PURE__ */ jsxs19(Text21, { children: [
16536
+ psd.code && /* @__PURE__ */ jsxs21(Text23, { children: [
15656
16537
  " ",
15657
16538
  "Code: ",
15658
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: psd.code })
16539
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: psd.code })
15659
16540
  ] }),
15660
- psd.decline_code && /* @__PURE__ */ jsxs19(Text21, { children: [
16541
+ psd.decline_code && /* @__PURE__ */ jsxs21(Text23, { children: [
15661
16542
  " ",
15662
16543
  "Decline Reason: ",
15663
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: psd.decline_code })
16544
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: psd.decline_code })
15664
16545
  ] }),
15665
- /* @__PURE__ */ jsxs19(Text21, { children: [
16546
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15666
16547
  " ",
15667
16548
  "Amount:",
15668
16549
  " ",
15669
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16550
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15670
16551
  psd.amount,
15671
16552
  " ",
15672
16553
  psd.currency
15673
16554
  ] })
15674
16555
  ] }),
15675
- psd.created && /* @__PURE__ */ jsxs19(Text21, { children: [
16556
+ psd.created && /* @__PURE__ */ jsxs21(Text23, { children: [
15676
16557
  " ",
15677
16558
  "Charged At:",
15678
16559
  " ",
15679
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: new Date(psd.created * 1e3).toISOString() })
16560
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: new Date(psd.created * 1e3).toISOString() })
15680
16561
  ] }),
15681
- psd.refund_details && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15682
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16562
+ psd.refund_details && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16563
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15683
16564
  " ",
15684
16565
  "Refund:"
15685
16566
  ] }),
15686
- /* @__PURE__ */ jsxs19(Text21, { children: [
16567
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15687
16568
  " ",
15688
16569
  "Amount:",
15689
16570
  " ",
15690
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16571
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15691
16572
  psd.refund_details.amount,
15692
16573
  " ",
15693
16574
  psd.refund_details.currency
15694
16575
  ] })
15695
16576
  ] }),
15696
- /* @__PURE__ */ jsxs19(Text21, { children: [
16577
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15697
16578
  " ",
15698
16579
  "State: ",
15699
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: psd.refund_details.state })
16580
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: psd.refund_details.state })
15700
16581
  ] })
15701
16582
  ] })
15702
16583
  ] })
@@ -15704,71 +16585,71 @@ var RetrieveSpendRequest = ({
15704
16585
  ] });
15705
16586
  }
15706
16587
  if (phase === "declined") {
15707
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15708
- /* @__PURE__ */ jsx26(Text21, { color: "red", children: "\u2717 Spend request declined" }),
15709
- /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15710
- /* @__PURE__ */ jsxs19(Text21, { children: [
16588
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16589
+ /* @__PURE__ */ jsx30(Text23, { color: "red", children: "\u2717 Spend request declined" }),
16590
+ /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16591
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15711
16592
  "ID: ",
15712
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.id })
16593
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.id })
15713
16594
  ] }),
15714
- /* @__PURE__ */ jsxs19(Text21, { children: [
16595
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15715
16596
  "Status:",
15716
16597
  " ",
15717
- /* @__PURE__ */ jsx26(Text21, { bold: true, color: "red", children: request?.status })
16598
+ /* @__PURE__ */ jsx30(Text23, { bold: true, color: "red", children: request?.status })
15718
16599
  ] }),
15719
- /* @__PURE__ */ jsxs19(Text21, { children: [
16600
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15720
16601
  "Amount:",
15721
16602
  " ",
15722
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
16603
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
15723
16604
  ] }),
15724
- /* @__PURE__ */ jsxs19(Text21, { children: [
16605
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15725
16606
  "Merchant: ",
15726
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.merchant_name })
16607
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.merchant_name })
15727
16608
  ] })
15728
16609
  ] })
15729
16610
  ] });
15730
16611
  }
15731
- return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
15732
- /* @__PURE__ */ jsx26(Text21, { color: "green", children: "\u2713 Spend request approved" }),
15733
- /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15734
- /* @__PURE__ */ jsxs19(Text21, { children: [
16612
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16613
+ /* @__PURE__ */ jsx30(Text23, { color: "green", children: "\u2713 Spend request approved" }),
16614
+ /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16615
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15735
16616
  "ID: ",
15736
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.id })
16617
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.id })
15737
16618
  ] }),
15738
- /* @__PURE__ */ jsxs19(Text21, { children: [
16619
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15739
16620
  "Status:",
15740
16621
  " ",
15741
- /* @__PURE__ */ jsx26(Text21, { bold: true, color: "green", children: request?.status })
16622
+ /* @__PURE__ */ jsx30(Text23, { bold: true, color: "green", children: request?.status })
15742
16623
  ] }),
15743
- /* @__PURE__ */ jsxs19(Text21, { children: [
16624
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15744
16625
  "Amount:",
15745
16626
  " ",
15746
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
16627
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
15747
16628
  ] }),
15748
- /* @__PURE__ */ jsxs19(Text21, { children: [
16629
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15749
16630
  "Merchant: ",
15750
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.merchant_name })
16631
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.merchant_name })
15751
16632
  ] }),
15752
- /* @__PURE__ */ jsxs19(Text21, { children: [
16633
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15753
16634
  "Line Items:",
15754
16635
  " ",
15755
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
16636
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
15756
16637
  ] }),
15757
- request?.link_pay_token && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15758
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: "Link Pay Token:" }),
15759
- /* @__PURE__ */ jsxs19(Text21, { children: [
16638
+ request?.link_pay_token && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16639
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: "Link Pay Token:" }),
16640
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15760
16641
  " ",
15761
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.link_pay_token })
16642
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.link_pay_token })
15762
16643
  ] })
15763
16644
  ] }),
15764
- request?.payment_status_details && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15765
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: "Last Payment Attempt:" }),
15766
- /* @__PURE__ */ jsxs19(Text21, { children: [
16645
+ request?.payment_status_details && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16646
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: "Last Payment Attempt:" }),
16647
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15767
16648
  " ",
15768
16649
  "Outcome:",
15769
16650
  " ",
15770
- /* @__PURE__ */ jsx26(
15771
- Text21,
16651
+ /* @__PURE__ */ jsx30(
16652
+ Text23,
15772
16653
  {
15773
16654
  bold: true,
15774
16655
  color: request.payment_status_details.outcome === "success" ? "green" : "red",
@@ -15776,79 +16657,79 @@ var RetrieveSpendRequest = ({
15776
16657
  }
15777
16658
  )
15778
16659
  ] }),
15779
- request.payment_status_details.code && /* @__PURE__ */ jsxs19(Text21, { children: [
16660
+ request.payment_status_details.code && /* @__PURE__ */ jsxs21(Text23, { children: [
15780
16661
  " ",
15781
16662
  "Code:",
15782
16663
  " ",
15783
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.payment_status_details.code })
16664
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.payment_status_details.code })
15784
16665
  ] }),
15785
- request.payment_status_details.decline_code && /* @__PURE__ */ jsxs19(Text21, { children: [
16666
+ request.payment_status_details.decline_code && /* @__PURE__ */ jsxs21(Text23, { children: [
15786
16667
  " ",
15787
16668
  "Decline Reason:",
15788
16669
  " ",
15789
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.payment_status_details.decline_code })
16670
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.payment_status_details.decline_code })
15790
16671
  ] })
15791
16672
  ] }),
15792
- request?.shared_payment_token && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15793
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16673
+ request?.shared_payment_token && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16674
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15794
16675
  "\x1B]8;;https://docs.stripe.com/agentic-commerce/concepts/shared-payment-tokens\x07",
15795
16676
  "Shared Payment Token",
15796
16677
  "\x1B]8;;\x07",
15797
16678
  ":"
15798
16679
  ] }),
15799
- /* @__PURE__ */ jsxs19(Text21, { children: [
16680
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15800
16681
  " ",
15801
16682
  "Token: ",
15802
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.shared_payment_token.id })
16683
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.shared_payment_token.id })
15803
16684
  ] })
15804
16685
  ] }),
15805
- request?.card && !outputFile && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15806
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: "Card Details:" }),
15807
- /* @__PURE__ */ jsxs19(Text21, { children: [
16686
+ request?.card && !outputFile && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16687
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: "Card Details:" }),
16688
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15808
16689
  " ",
15809
16690
  "Number: ",
15810
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.card.number })
16691
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.card.number })
15811
16692
  ] }),
15812
- /* @__PURE__ */ jsxs19(Text21, { children: [
16693
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15813
16694
  " ",
15814
16695
  "Brand: ",
15815
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request?.card.brand })
16696
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request?.card.brand })
15816
16697
  ] }),
15817
- /* @__PURE__ */ jsxs19(Text21, { children: [
16698
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15818
16699
  " ",
15819
16700
  "Expiry:",
15820
16701
  " ",
15821
- /* @__PURE__ */ jsxs19(Text21, { bold: true, children: [
16702
+ /* @__PURE__ */ jsxs21(Text23, { bold: true, children: [
15822
16703
  String(request?.card.exp_month).padStart(2, "0"),
15823
16704
  "/",
15824
16705
  request?.card.exp_year
15825
16706
  ] })
15826
16707
  ] }),
15827
- request?.card.cvc && /* @__PURE__ */ jsxs19(Text21, { children: [
16708
+ request?.card.cvc && /* @__PURE__ */ jsxs21(Text23, { children: [
15828
16709
  " ",
15829
16710
  "CVC: ",
15830
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.card.cvc })
16711
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.card.cvc })
15831
16712
  ] }),
15832
- request?.card.valid_until && /* @__PURE__ */ jsxs19(Text21, { children: [
16713
+ request?.card.valid_until && /* @__PURE__ */ jsxs21(Text23, { children: [
15833
16714
  " ",
15834
16715
  "Valid Until: ",
15835
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: request.card.valid_until })
16716
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: request.card.valid_until })
15836
16717
  ] }),
15837
- request?.card.billing_address && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15838
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: " Billing Address:" }),
15839
- /* @__PURE__ */ jsxs19(Text21, { children: [
16718
+ request?.card.billing_address && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16719
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: " Billing Address:" }),
16720
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15840
16721
  " ",
15841
16722
  request.card.billing_address.name
15842
16723
  ] }),
15843
- /* @__PURE__ */ jsxs19(Text21, { children: [
16724
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15844
16725
  " ",
15845
16726
  request.card.billing_address.line1
15846
16727
  ] }),
15847
- request.card.billing_address.line2 && /* @__PURE__ */ jsxs19(Text21, { children: [
16728
+ request.card.billing_address.line2 && /* @__PURE__ */ jsxs21(Text23, { children: [
15848
16729
  " ",
15849
16730
  request.card.billing_address.line2
15850
16731
  ] }),
15851
- /* @__PURE__ */ jsxs19(Text21, { children: [
16732
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15852
16733
  " ",
15853
16734
  [
15854
16735
  request.card.billing_address.city,
@@ -15856,18 +16737,18 @@ var RetrieveSpendRequest = ({
15856
16737
  request.card.billing_address.postal_code
15857
16738
  ].filter(Boolean).join(", ")
15858
16739
  ] }),
15859
- /* @__PURE__ */ jsxs19(Text21, { children: [
16740
+ /* @__PURE__ */ jsxs21(Text23, { children: [
15860
16741
  " ",
15861
16742
  request.card.billing_address.country
15862
16743
  ] })
15863
16744
  ] })
15864
16745
  ] }),
15865
- request?.card && outputFile && /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
15866
- outputFilePath && /* @__PURE__ */ jsxs19(Text21, { color: "green", children: [
16746
+ request?.card && outputFile && /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16747
+ outputFilePath && /* @__PURE__ */ jsxs21(Text23, { color: "green", children: [
15867
16748
  "Card credentials written to ",
15868
- /* @__PURE__ */ jsx26(Text21, { bold: true, children: outputFilePath })
16749
+ /* @__PURE__ */ jsx30(Text23, { bold: true, children: outputFilePath })
15869
16750
  ] }),
15870
- fileError && /* @__PURE__ */ jsxs19(Text21, { color: "red", children: [
16751
+ fileError && /* @__PURE__ */ jsxs21(Text23, { color: "red", children: [
15871
16752
  "Failed to write card file: ",
15872
16753
  fileError
15873
16754
  ] })
@@ -15877,140 +16758,143 @@ var RetrieveSpendRequest = ({
15877
16758
  };
15878
16759
 
15879
16760
  // src/commands/spend-request/schema.ts
15880
- import { z as z8 } from "incur";
15881
- var createOptions = z8.object({
15882
- paymentMethodId: z8.string().optional().describe("Payment method ID"),
15883
- credentialType: z8.enum(["shared_payment_token", "card"]).default("card").describe(
16761
+ import { z as z10 } from "incur";
16762
+ var createOptions = z10.object({
16763
+ paymentMethodId: z10.string().optional().describe("Payment method ID"),
16764
+ credentialType: z10.enum(["shared_payment_token", "card"]).default("card").describe(
15884
16765
  '"card" for checkout forms/Stripe Elements; "shared_payment_token" for HTTP 402/machine payment flows'
15885
16766
  ),
15886
- networkId: z8.string().optional().describe(
16767
+ networkId: z10.string().optional().describe(
15887
16768
  "Network ID (required for shared_payment_token) \u2014 use `link-cli mpp decode` to extract"
15888
16769
  ),
15889
- amount: z8.coerce.number().int().positive().max(5e5).describe("Amount in cents, max 500000 ($5,000.00)"),
15890
- currency: z8.string().length(3).default("usd").describe("Currency code"),
15891
- merchantName: z8.string().optional().describe(
16770
+ amount: z10.coerce.number().int().positive().max(5e5).describe("Amount in cents, max 500000 ($5,000.00)"),
16771
+ currency: z10.string().length(3).default("usd").describe("Currency code"),
16772
+ merchantName: z10.string().optional().describe(
15892
16773
  "Merchant name (required for card; forbidden for shared_payment_token)"
15893
16774
  ),
15894
- merchantUrl: z8.string().optional().describe(
16775
+ merchantUrl: z10.string().optional().describe(
15895
16776
  "Merchant URL (required for card; forbidden for shared_payment_token)"
15896
16777
  ),
15897
- context: z8.string().min(100).describe(
16778
+ context: z10.string().min(100).describe(
15898
16779
  "Min 100 chars \u2014 describe the purchase and rationale; the user reads this when approving"
15899
16780
  ),
15900
- lineItem: z8.array(z8.union([z8.string(), z8.record(z8.string(), z8.unknown())])).default([]).describe(
16781
+ lineItem: z10.array(z10.union([z10.string(), z10.record(z10.string(), z10.unknown())])).default([]).describe(
15901
16782
  '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"'
15902
16783
  ),
15903
- total: z8.array(z8.union([z8.string(), z8.record(z8.string(), z8.unknown())])).default([]).describe(
16784
+ total: z10.array(z10.union([z10.string(), z10.record(z10.string(), z10.unknown())])).default([]).describe(
15904
16785
  '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"'
15905
16786
  ),
15906
- requestApproval: z8.boolean().default(true).describe("Request approval and poll until approved/denied/expired"),
15907
- test: z8.boolean().default(false).describe(
16787
+ requestApproval: z10.boolean().default(true).describe("Request approval and poll until approved/denied/expired"),
16788
+ test: z10.boolean().default(false).describe(
15908
16789
  "Use test mode (creates testmode credentials from test card data)"
15909
16790
  ),
15910
- approve: z8.boolean().default(false).describe(""),
15911
- outputFile: z8.string().optional().describe(
16791
+ approve: z10.boolean().default(false).describe(""),
16792
+ outputFile: z10.string().optional().describe(
15912
16793
  "Write full card credentials to this file path; stdout shows redacted card data only"
15913
16794
  ),
15914
- force: z8.boolean().default(false).describe("Overwrite output file if it already exists")
16795
+ force: z10.boolean().default(false).describe("Overwrite output file if it already exists"),
16796
+ approvalDetail: z10.union([z10.string(), z10.record(z10.string(), z10.unknown())]).optional().describe(
16797
+ "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)."
16798
+ )
15915
16799
  });
15916
- var listOptions = z8.object({
15917
- includeHistory: z8.boolean().default(false).describe("Include expired and terminal spend requests")
16800
+ var listOptions3 = z10.object({
16801
+ includeHistory: z10.boolean().default(false).describe("Include expired and terminal spend requests")
15918
16802
  });
15919
- var retrieveOptions = z8.object({
15920
- timeout: z8.coerce.number().default(600).describe(
16803
+ var retrieveOptions = z10.object({
16804
+ timeout: z10.coerce.number().default(600).describe(
15921
16805
  "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."
15922
16806
  ),
15923
- interval: z8.coerce.number().default(0).describe(
16807
+ interval: z10.coerce.number().default(0).describe(
15924
16808
  "Poll interval in seconds. When > 0, polls until status is terminal, timeout is reached, or max attempts are exhausted."
15925
16809
  ),
15926
- maxAttempts: z8.coerce.number().default(0).describe(
16810
+ maxAttempts: z10.coerce.number().default(0).describe(
15927
16811
  "Max poll attempts. 0 = unlimited. Exhaustion during active polling exits non-zero with POLLING_TIMEOUT."
15928
16812
  ),
15929
- include: z8.array(z8.string()).default([]).describe("Include extra data (repeatable, e.g. --include card)"),
15930
- outputFile: z8.string().optional().describe(
16813
+ include: z10.array(z10.string()).default([]).describe("Include extra data (repeatable, e.g. --include card)"),
16814
+ outputFile: z10.string().optional().describe(
15931
16815
  "Write full card credentials to this file path; stdout shows redacted card data only"
15932
16816
  ),
15933
- force: z8.boolean().default(false).describe("Overwrite output file if it already exists")
16817
+ force: z10.boolean().default(false).describe("Overwrite output file if it already exists")
15934
16818
  });
15935
- var updateOptions = z8.object({
15936
- paymentMethodId: z8.string().optional().describe("Payment method ID"),
15937
- amount: z8.coerce.number().optional().describe("Amount in cents"),
15938
- merchantUrl: z8.string().optional().describe("Merchant URL"),
15939
- profileId: z8.string().optional().describe("Profile ID"),
15940
- merchantId: z8.string().optional().describe("Merchant ID"),
15941
- currency: z8.string().optional().describe("Currency code"),
15942
- lineItem: z8.array(z8.union([z8.string(), z8.record(z8.string(), z8.unknown())])).default([]).describe(
16819
+ var updateOptions = z10.object({
16820
+ paymentMethodId: z10.string().optional().describe("Payment method ID"),
16821
+ amount: z10.coerce.number().optional().describe("Amount in cents"),
16822
+ merchantUrl: z10.string().optional().describe("Merchant URL"),
16823
+ profileId: z10.string().optional().describe("Profile ID"),
16824
+ merchantId: z10.string().optional().describe("Merchant ID"),
16825
+ currency: z10.string().optional().describe("Currency code"),
16826
+ lineItem: z10.array(z10.union([z10.string(), z10.record(z10.string(), z10.unknown())])).default([]).describe(
15943
16827
  '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"'
15944
16828
  ),
15945
- total: z8.array(z8.union([z8.string(), z8.record(z8.string(), z8.unknown())])).default([]).describe(
16829
+ total: z10.array(z10.union([z10.string(), z10.record(z10.string(), z10.unknown())])).default([]).describe(
15946
16830
  '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"'
15947
16831
  )
15948
16832
  });
15949
16833
 
15950
16834
  // src/commands/spend-request/update.tsx
15951
- import { Box as Box20, Text as Text22 } from "ink";
15952
- import Spinner12 from "ink-spinner";
15953
- import { useCallback as useCallback9 } from "react";
15954
- import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
16835
+ import { Box as Box22, Text as Text24 } from "ink";
16836
+ import Spinner14 from "ink-spinner";
16837
+ import { useCallback as useCallback11 } from "react";
16838
+ import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
15955
16839
  var UpdateSpendRequest = ({
15956
16840
  repository,
15957
16841
  id,
15958
16842
  params,
15959
16843
  onComplete
15960
16844
  }) => {
15961
- const action = useCallback9(
16845
+ const action = useCallback11(
15962
16846
  () => repository.updateSpendRequest(id, params),
15963
16847
  [repository, id, params]
15964
16848
  );
15965
16849
  const { status, data: request, error } = useAsyncAction(action, onComplete);
15966
16850
  if (status === "loading") {
15967
- return /* @__PURE__ */ jsx27(Box20, { children: /* @__PURE__ */ jsxs20(Text22, { color: "cyan", children: [
15968
- /* @__PURE__ */ jsx27(Spinner12, { type: "dots" }),
16851
+ return /* @__PURE__ */ jsx31(Box22, { children: /* @__PURE__ */ jsxs22(Text24, { color: "cyan", children: [
16852
+ /* @__PURE__ */ jsx31(Spinner14, { type: "dots" }),
15969
16853
  " Updating spend request ",
15970
16854
  id,
15971
16855
  "..."
15972
16856
  ] }) });
15973
16857
  }
15974
16858
  if (status === "error") {
15975
- return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
15976
- /* @__PURE__ */ jsx27(Text22, { color: "red", children: "\u2717 Failed to update spend request" }),
15977
- /* @__PURE__ */ jsx27(Text22, { color: "red", children: error })
16859
+ return /* @__PURE__ */ jsxs22(Box22, { flexDirection: "column", children: [
16860
+ /* @__PURE__ */ jsx31(Text24, { color: "red", children: "\u2717 Failed to update spend request" }),
16861
+ /* @__PURE__ */ jsx31(Text24, { color: "red", children: error })
15978
16862
  ] });
15979
16863
  }
15980
- return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
15981
- /* @__PURE__ */ jsx27(Text22, { color: "green", children: "\u2713 Spend request updated" }),
15982
- /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
15983
- /* @__PURE__ */ jsxs20(Text22, { children: [
16864
+ return /* @__PURE__ */ jsxs22(Box22, { flexDirection: "column", children: [
16865
+ /* @__PURE__ */ jsx31(Text24, { color: "green", children: "\u2713 Spend request updated" }),
16866
+ /* @__PURE__ */ jsxs22(Box22, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16867
+ /* @__PURE__ */ jsxs22(Text24, { children: [
15984
16868
  "ID: ",
15985
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: request?.id })
16869
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: request?.id })
15986
16870
  ] }),
15987
- /* @__PURE__ */ jsxs20(Text22, { children: [
16871
+ /* @__PURE__ */ jsxs22(Text24, { children: [
15988
16872
  "Status: ",
15989
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: request?.status })
16873
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: request?.status })
15990
16874
  ] }),
15991
- /* @__PURE__ */ jsxs20(Text22, { children: [
16875
+ /* @__PURE__ */ jsxs22(Text24, { children: [
15992
16876
  "Amount:",
15993
16877
  " ",
15994
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: (() => {
16878
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: (() => {
15995
16879
  const t = request?.totals.find((t2) => t2.type === "total");
15996
16880
  return t ? String(t.amount) : "N/A";
15997
16881
  })() })
15998
16882
  ] }),
15999
- /* @__PURE__ */ jsxs20(Text22, { children: [
16883
+ /* @__PURE__ */ jsxs22(Text24, { children: [
16000
16884
  "Merchant: ",
16001
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: request?.merchant_name })
16885
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: request?.merchant_name })
16002
16886
  ] }),
16003
- /* @__PURE__ */ jsxs20(Text22, { children: [
16887
+ /* @__PURE__ */ jsxs22(Text24, { children: [
16004
16888
  "Line Items:",
16005
16889
  " ",
16006
- /* @__PURE__ */ jsx27(Text22, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
16890
+ /* @__PURE__ */ jsx31(Text24, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
16007
16891
  ] })
16008
16892
  ] })
16009
16893
  ] });
16010
16894
  };
16011
16895
 
16012
16896
  // src/commands/spend-request/index.tsx
16013
- import { jsx as jsx28 } from "react/jsx-runtime";
16897
+ import { jsx as jsx32 } from "react/jsx-runtime";
16014
16898
  async function applyOutputFile(request, outputFile, force) {
16015
16899
  if (!outputFile || !request.card) return request;
16016
16900
  const fileData = {
@@ -16029,19 +16913,19 @@ async function applyOutputFile(request, outputFile, force) {
16029
16913
  };
16030
16914
  }
16031
16915
  function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16032
- const cli2 = Cli9.create("spend-request", {
16916
+ const cli2 = Cli11.create("spend-request", {
16033
16917
  description: "Spend request management commands"
16034
16918
  });
16035
16919
  cli2.command("list", {
16036
16920
  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.",
16037
16921
  outputPolicy: "agent-only",
16038
- options: listOptions,
16922
+ options: listOptions3,
16039
16923
  middleware: [requireAuth(authStorage2, envAccessToken2)],
16040
16924
  async run(c) {
16041
16925
  const opts = { includeHistory: c.options.includeHistory ?? false };
16042
16926
  if (!c.agent && !c.formatExplicit) {
16043
16927
  return renderInteractive(
16044
- /* @__PURE__ */ jsx28(
16928
+ /* @__PURE__ */ jsx32(
16045
16929
  SpendRequestList,
16046
16930
  {
16047
16931
  repository,
@@ -16105,6 +16989,7 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16105
16989
  const totals = opts.total?.length ? opts.total.map(
16106
16990
  (item) => typeof item === "string" ? parseTotalFlag(item) : item
16107
16991
  ) : void 0;
16992
+ const approvalDetails = opts.approvalDetail !== void 0 ? typeof opts.approvalDetail === "string" ? JSON.parse(opts.approvalDetail) : opts.approvalDetail : void 0;
16108
16993
  const createParams = {
16109
16994
  payment_details: opts.paymentMethodId,
16110
16995
  credential_type: credentialType,
@@ -16118,14 +17003,15 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16118
17003
  totals,
16119
17004
  request_approval: requestApproval || void 0,
16120
17005
  test: opts.test ? true : void 0,
16121
- approve: opts.approve ? true : void 0
17006
+ approve: opts.approve ? true : void 0,
17007
+ approval_details: approvalDetails
16122
17008
  };
16123
17009
  const outputFile = opts.outputFile;
16124
17010
  const forceOverwrite = opts.force;
16125
17011
  if (!c.agent && !c.formatExplicit) {
16126
17012
  let capturedResult = void 0;
16127
17013
  return renderInteractive(
16128
- /* @__PURE__ */ jsx28(
17014
+ /* @__PURE__ */ jsx32(
16129
17015
  CreateSpendRequest,
16130
17016
  {
16131
17017
  repository,
@@ -16185,8 +17071,8 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16185
17071
  });
16186
17072
  cli2.command("update", {
16187
17073
  description: "Update a spend request",
16188
- args: z9.object({
16189
- id: z9.string().describe("Spend request ID")
17074
+ args: z11.object({
17075
+ id: z11.string().describe("Spend request ID")
16190
17076
  }),
16191
17077
  options: updateOptions,
16192
17078
  outputPolicy: "agent-only",
@@ -16214,7 +17100,7 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16214
17100
  if (!c.agent && !c.formatExplicit) {
16215
17101
  let capturedResult = null;
16216
17102
  return renderInteractive(
16217
- /* @__PURE__ */ jsx28(
17103
+ /* @__PURE__ */ jsx32(
16218
17104
  UpdateSpendRequest,
16219
17105
  {
16220
17106
  repository,
@@ -16237,8 +17123,8 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16237
17123
  });
16238
17124
  cli2.command("request-approval", {
16239
17125
  description: "Request approval for a spend request",
16240
- args: z9.object({
16241
- id: z9.string().describe("Spend request ID")
17126
+ args: z11.object({
17127
+ id: z11.string().describe("Spend request ID")
16242
17128
  }),
16243
17129
  outputPolicy: "agent-only",
16244
17130
  async *run(c) {
@@ -16247,7 +17133,7 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16247
17133
  if (!c.agent && !c.formatExplicit) {
16248
17134
  let capturedResult = void 0;
16249
17135
  return renderInteractive(
16250
- /* @__PURE__ */ jsx28(
17136
+ /* @__PURE__ */ jsx32(
16251
17137
  RequestApproval,
16252
17138
  {
16253
17139
  repository,
@@ -16292,8 +17178,8 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16292
17178
  });
16293
17179
  cli2.command("retrieve", {
16294
17180
  description: "Retrieve a spend request",
16295
- args: z9.object({
16296
- id: z9.string().describe("Spend request ID")
17181
+ args: z11.object({
17182
+ id: z11.string().describe("Spend request ID")
16297
17183
  }),
16298
17184
  options: retrieveOptions,
16299
17185
  outputPolicy: "agent-only",
@@ -16311,7 +17197,7 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16311
17197
  if (!c.agent && !c.formatExplicit) {
16312
17198
  let capturedResult = null;
16313
17199
  return renderInteractive(
16314
- /* @__PURE__ */ jsx28(
17200
+ /* @__PURE__ */ jsx32(
16315
17201
  RetrieveSpendRequest,
16316
17202
  {
16317
17203
  repository,
@@ -16383,8 +17269,8 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16383
17269
  });
16384
17270
  cli2.command("cancel", {
16385
17271
  description: "Cancel a spend request",
16386
- args: z9.object({
16387
- id: z9.string().describe("Spend request ID")
17272
+ args: z11.object({
17273
+ id: z11.string().describe("Spend request ID")
16388
17274
  }),
16389
17275
  outputPolicy: "agent-only",
16390
17276
  middleware: [requireAuth(authStorage2, envAccessToken2)],
@@ -16393,7 +17279,7 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16393
17279
  if (!c.agent && !c.formatExplicit) {
16394
17280
  let capturedResult = null;
16395
17281
  return renderInteractive(
16396
- /* @__PURE__ */ jsx28(
17282
+ /* @__PURE__ */ jsx32(
16397
17283
  CancelSpendRequest,
16398
17284
  {
16399
17285
  repository,
@@ -16417,20 +17303,20 @@ function createSpendRequestCli(repository, authStorage2, envAccessToken2) {
16417
17303
  }
16418
17304
 
16419
17305
  // src/commands/transactions/index.tsx
16420
- import { Cli as Cli10 } from "incur";
17306
+ import { Cli as Cli12 } from "incur";
16421
17307
 
16422
17308
  // src/commands/transactions/list.tsx
16423
- import { Box as Box21, Text as Text23 } from "ink";
16424
- import Spinner13 from "ink-spinner";
16425
- import { useCallback as useCallback10 } from "react";
16426
- import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
16427
- var COLUMN_GAP = " ";
17309
+ import { Box as Box23, Text as Text25 } from "ink";
17310
+ import Spinner15 from "ink-spinner";
17311
+ import { useCallback as useCallback12 } from "react";
17312
+ import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
17313
+ var COLUMN_GAP3 = " ";
16428
17314
  var DATE_WIDTH = 10;
16429
17315
  var AMOUNT_WIDTH = 13;
16430
17316
  var STATUS_WIDTH = 10;
16431
17317
  var CATEGORY_WIDTH = 16;
16432
17318
  var MIN_DESCRIPTION_WIDTH = 16;
16433
- var HORIZONTAL_PADDING = 4;
17319
+ var HORIZONTAL_PADDING2 = 4;
16434
17320
  function formatAmount(amount, currency) {
16435
17321
  const currencyCode = currency.toUpperCase();
16436
17322
  try {
@@ -16444,7 +17330,7 @@ function formatAmount(amount, currency) {
16444
17330
  return `${amount} ${currency}`;
16445
17331
  }
16446
17332
  }
16447
- function truncateCell(value, width) {
17333
+ function truncateCell3(value, width) {
16448
17334
  if (value.length <= width) {
16449
17335
  return value;
16450
17336
  }
@@ -16453,8 +17339,8 @@ function truncateCell(value, width) {
16453
17339
  }
16454
17340
  return `${value.slice(0, width - 3)}...`;
16455
17341
  }
16456
- function formatCell(value, width, align = "left") {
16457
- const truncated = truncateCell(value, width);
17342
+ function formatCell3(value, width, align = "left") {
17343
+ const truncated = truncateCell3(value, width);
16458
17344
  return align === "right" ? truncated.padStart(width) : truncated.padEnd(width);
16459
17345
  }
16460
17346
  var TransactionsList = ({
@@ -16462,7 +17348,7 @@ var TransactionsList = ({
16462
17348
  params,
16463
17349
  onComplete
16464
17350
  }) => {
16465
- const action = useCallback10(
17351
+ const action = useCallback12(
16466
17352
  () => resource.listTransactions(params),
16467
17353
  [resource, params]
16468
17354
  );
@@ -16472,80 +17358,80 @@ var TransactionsList = ({
16472
17358
  const terminalWidth = process.stdout.columns ?? 100;
16473
17359
  const descriptionWidth = Math.max(
16474
17360
  MIN_DESCRIPTION_WIDTH,
16475
- terminalWidth - HORIZONTAL_PADDING - DATE_WIDTH - AMOUNT_WIDTH - STATUS_WIDTH - CATEGORY_WIDTH - COLUMN_GAP.length * 4
17361
+ terminalWidth - HORIZONTAL_PADDING2 - DATE_WIDTH - AMOUNT_WIDTH - STATUS_WIDTH - CATEGORY_WIDTH - COLUMN_GAP3.length * 4
16476
17362
  );
16477
17363
  const headerRow = [
16478
- formatCell("Date", DATE_WIDTH),
16479
- formatCell("Amount", AMOUNT_WIDTH, "right"),
16480
- formatCell("Status", STATUS_WIDTH),
16481
- formatCell("Category", CATEGORY_WIDTH),
16482
- formatCell("Description", descriptionWidth)
16483
- ].join(COLUMN_GAP);
17364
+ formatCell3("Date", DATE_WIDTH),
17365
+ formatCell3("Amount", AMOUNT_WIDTH, "right"),
17366
+ formatCell3("Status", STATUS_WIDTH),
17367
+ formatCell3("Category", CATEGORY_WIDTH),
17368
+ formatCell3("Description", descriptionWidth)
17369
+ ].join(COLUMN_GAP3);
16484
17370
  const separatorRow = "-".repeat(headerRow.length);
16485
17371
  const rows = transactions.map(
16486
17372
  (txn) => [
16487
- formatCell(txn.created_date, DATE_WIDTH),
16488
- formatCell(formatAmount(txn.amount, txn.currency), AMOUNT_WIDTH, "right"),
16489
- formatCell(txn.status, STATUS_WIDTH),
16490
- formatCell(txn.category ?? "", CATEGORY_WIDTH),
16491
- formatCell(txn.description, descriptionWidth)
16492
- ].join(COLUMN_GAP)
17373
+ formatCell3(txn.created_date, DATE_WIDTH),
17374
+ formatCell3(formatAmount(txn.amount, txn.currency), AMOUNT_WIDTH, "right"),
17375
+ formatCell3(txn.status, STATUS_WIDTH),
17376
+ formatCell3(txn.category ?? "", CATEGORY_WIDTH),
17377
+ formatCell3(txn.description, descriptionWidth)
17378
+ ].join(COLUMN_GAP3)
16493
17379
  );
16494
17380
  if (status === "loading") {
16495
- return /* @__PURE__ */ jsx29(Box21, { children: /* @__PURE__ */ jsxs21(Text23, { color: "cyan", children: [
16496
- /* @__PURE__ */ jsx29(Spinner13, { type: "dots" }),
17381
+ return /* @__PURE__ */ jsx33(Box23, { children: /* @__PURE__ */ jsxs23(Text25, { color: "cyan", children: [
17382
+ /* @__PURE__ */ jsx33(Spinner15, { type: "dots" }),
16497
17383
  " Loading transactions..."
16498
17384
  ] }) });
16499
17385
  }
16500
17386
  if (status === "error") {
16501
- return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16502
- /* @__PURE__ */ jsx29(Text23, { color: "red", children: "Failed to load transactions" }),
16503
- /* @__PURE__ */ jsx29(Text23, { color: "red", children: error })
17387
+ return /* @__PURE__ */ jsxs23(Box23, { flexDirection: "column", children: [
17388
+ /* @__PURE__ */ jsx33(Text25, { color: "red", children: "Failed to load transactions" }),
17389
+ /* @__PURE__ */ jsx33(Text25, { color: "red", children: error })
16504
17390
  ] });
16505
17391
  }
16506
17392
  if (transactions.length === 0) {
16507
- return /* @__PURE__ */ jsx29(Box21, { children: /* @__PURE__ */ jsx29(Text23, { dimColor: true, children: "No transactions found" }) });
16508
- }
16509
- return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
16510
- /* @__PURE__ */ jsx29(Text23, { bold: true, children: "Transactions" }),
16511
- /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16512
- /* @__PURE__ */ jsx29(Text23, { bold: true, children: headerRow }),
16513
- /* @__PURE__ */ jsx29(Text23, { dimColor: true, children: separatorRow }),
16514
- rows.map((row, index) => /* @__PURE__ */ jsx29(Text23, { children: row }, transactions[index].id))
17393
+ return /* @__PURE__ */ jsx33(Box23, { children: /* @__PURE__ */ jsx33(Text25, { dimColor: true, children: "No transactions found" }) });
17394
+ }
17395
+ return /* @__PURE__ */ jsxs23(Box23, { flexDirection: "column", children: [
17396
+ /* @__PURE__ */ jsx33(Text25, { bold: true, children: "Transactions" }),
17397
+ /* @__PURE__ */ jsxs23(Box23, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
17398
+ /* @__PURE__ */ jsx33(Text25, { bold: true, children: headerRow }),
17399
+ /* @__PURE__ */ jsx33(Text25, { dimColor: true, children: separatorRow }),
17400
+ rows.map((row, index) => /* @__PURE__ */ jsx33(Text25, { children: row }, transactions[index].id))
16515
17401
  ] }),
16516
- page?.has_more !== void 0 ? /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", marginTop: 1, children: [
16517
- /* @__PURE__ */ jsxs21(Text23, { dimColor: true, children: [
17402
+ page?.has_more !== void 0 ? /* @__PURE__ */ jsxs23(Box23, { flexDirection: "column", marginTop: 1, children: [
17403
+ /* @__PURE__ */ jsxs23(Text25, { dimColor: true, children: [
16518
17404
  "has_more: ",
16519
17405
  String(page.has_more)
16520
17406
  ] }),
16521
- nextCursor ? /* @__PURE__ */ jsx29(Text23, { dimColor: true, children: `next page: --starting-after ${nextCursor}` }) : null
17407
+ nextCursor ? /* @__PURE__ */ jsx33(Text25, { dimColor: true, children: `next page: --starting-after ${nextCursor}` }) : null
16522
17408
  ] }) : null
16523
17409
  ] });
16524
17410
  };
16525
17411
 
16526
17412
  // src/commands/transactions/schema.ts
16527
- import { z as z10 } from "incur";
17413
+ import { z as z12 } from "incur";
16528
17414
  var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
16529
- var listOptions2 = z10.object({
16530
- limit: z10.coerce.number().int().positive().max(100).optional().describe("Maximum number of transactions to return (1-100)."),
16531
- startingAfter: z10.string().optional().describe("Cursor: return transactions after this transaction ID."),
16532
- endingBefore: z10.string().optional().describe("Cursor: return transactions before this transaction ID."),
16533
- startDate: z10.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."),
16534
- endDate: z10.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."),
16535
- category: z10.string().optional().describe("Filter by transaction category."),
16536
- origin: z10.enum(["link", "external_connection"]).optional().describe("Filter by transaction origin: link or external_connection."),
16537
- source: z10.array(z10.string()).default([]).describe("Filter by source ID. Repeat to include multiple sources.")
17415
+ var listOptions4 = z12.object({
17416
+ limit: z12.coerce.number().int().positive().max(100).optional().describe("Maximum number of transactions to return (1-100)."),
17417
+ startingAfter: z12.string().optional().describe("Cursor: return transactions after this transaction ID."),
17418
+ endingBefore: z12.string().optional().describe("Cursor: return transactions before this transaction ID."),
17419
+ 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."),
17420
+ 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."),
17421
+ category: z12.string().optional().describe("Filter by transaction category."),
17422
+ origin: z12.enum(["link", "external_connection"]).optional().describe("Filter by transaction origin: link or external_connection."),
17423
+ source: z12.array(z12.string()).default([]).describe("Filter by source ID. Repeat to include multiple sources.")
16538
17424
  });
16539
17425
 
16540
17426
  // src/commands/transactions/index.tsx
16541
- import { jsx as jsx30 } from "react/jsx-runtime";
17427
+ import { jsx as jsx34 } from "react/jsx-runtime";
16542
17428
  function createTransactionsCli(createResource, authStorage2, envAccessToken2) {
16543
- const cli2 = Cli10.create("transactions", {
17429
+ const cli2 = Cli12.create("transactions", {
16544
17430
  description: "List transactions from Link and external accounts"
16545
17431
  });
16546
17432
  cli2.command("list", {
16547
17433
  description: "List transactions from Link and external accounts, including non-Link activity",
16548
- options: listOptions2,
17434
+ options: listOptions4,
16549
17435
  outputPolicy: "agent-only",
16550
17436
  middleware: [requireAuth(authStorage2, envAccessToken2)],
16551
17437
  async run(c) {
@@ -16564,7 +17450,7 @@ function createTransactionsCli(createResource, authStorage2, envAccessToken2) {
16564
17450
  if (opts.source.length > 0) params.sources = opts.source;
16565
17451
  if (!c.agent && !c.formatExplicit) {
16566
17452
  return renderInteractive(
16567
- /* @__PURE__ */ jsx30(
17453
+ /* @__PURE__ */ jsx34(
16568
17454
  TransactionsList,
16569
17455
  {
16570
17456
  resource,
@@ -16583,54 +17469,54 @@ function createTransactionsCli(createResource, authStorage2, envAccessToken2) {
16583
17469
  }
16584
17470
 
16585
17471
  // src/commands/user-info/index.tsx
16586
- import { Cli as Cli11 } from "incur";
17472
+ import { Cli as Cli13 } from "incur";
16587
17473
 
16588
17474
  // src/commands/user-info/retrieve.tsx
16589
- import { Box as Box22, Text as Text24 } from "ink";
16590
- import Spinner14 from "ink-spinner";
16591
- import { useCallback as useCallback11 } from "react";
16592
- import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
17475
+ import { Box as Box24, Text as Text26 } from "ink";
17476
+ import Spinner16 from "ink-spinner";
17477
+ import { useCallback as useCallback13 } from "react";
17478
+ import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
16593
17479
  var UserInfoRetrieve = ({
16594
17480
  resource,
16595
17481
  onComplete
16596
17482
  }) => {
16597
- const action = useCallback11(() => resource.retrieve(), [resource]);
17483
+ const action = useCallback13(() => resource.retrieve(), [resource]);
16598
17484
  const { status, data: userInfo, error } = useAsyncAction(action, onComplete);
16599
17485
  if (status === "loading") {
16600
- return /* @__PURE__ */ jsx31(Box22, { children: /* @__PURE__ */ jsxs22(Text24, { color: "cyan", children: [
16601
- /* @__PURE__ */ jsx31(Spinner14, { type: "dots" }),
17486
+ return /* @__PURE__ */ jsx35(Box24, { children: /* @__PURE__ */ jsxs24(Text26, { color: "cyan", children: [
17487
+ /* @__PURE__ */ jsx35(Spinner16, { type: "dots" }),
16602
17488
  " Loading user info..."
16603
17489
  ] }) });
16604
17490
  }
16605
17491
  if (status === "error") {
16606
- return /* @__PURE__ */ jsxs22(Box22, { flexDirection: "column", children: [
16607
- /* @__PURE__ */ jsx31(Text24, { color: "red", children: "\u2717 Failed to load user info" }),
16608
- /* @__PURE__ */ jsx31(Text24, { color: "red", children: error })
17492
+ return /* @__PURE__ */ jsxs24(Box24, { flexDirection: "column", children: [
17493
+ /* @__PURE__ */ jsx35(Text26, { color: "red", children: "\u2717 Failed to load user info" }),
17494
+ /* @__PURE__ */ jsx35(Text26, { color: "red", children: error })
16609
17495
  ] });
16610
17496
  }
16611
- return /* @__PURE__ */ jsxs22(Box22, { flexDirection: "column", children: [
16612
- /* @__PURE__ */ jsx31(Text24, { bold: true, children: "User Info" }),
16613
- /* @__PURE__ */ jsxs22(Box22, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
16614
- /* @__PURE__ */ jsxs22(Text24, { children: [
16615
- /* @__PURE__ */ jsx31(Text24, { dimColor: true, children: "Email: " }),
16616
- userInfo?.email ?? /* @__PURE__ */ jsx31(Text24, { dimColor: true, children: "Not set" })
17497
+ return /* @__PURE__ */ jsxs24(Box24, { flexDirection: "column", children: [
17498
+ /* @__PURE__ */ jsx35(Text26, { bold: true, children: "User Info" }),
17499
+ /* @__PURE__ */ jsxs24(Box24, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
17500
+ /* @__PURE__ */ jsxs24(Text26, { children: [
17501
+ /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Email: " }),
17502
+ userInfo?.email ?? /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Not set" })
16617
17503
  ] }),
16618
- /* @__PURE__ */ jsxs22(Text24, { children: [
16619
- /* @__PURE__ */ jsx31(Text24, { dimColor: true, children: "Name: " }),
16620
- userInfo?.name ?? /* @__PURE__ */ jsx31(Text24, { dimColor: true, children: "Not set" })
17504
+ /* @__PURE__ */ jsxs24(Text26, { children: [
17505
+ /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Name: " }),
17506
+ userInfo?.name ?? /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Not set" })
16621
17507
  ] }),
16622
- /* @__PURE__ */ jsxs22(Text24, { children: [
16623
- /* @__PURE__ */ jsx31(Text24, { dimColor: true, children: "Phone: " }),
16624
- userInfo?.phone ?? /* @__PURE__ */ jsx31(Text24, { dimColor: true, children: "Not set" })
17508
+ /* @__PURE__ */ jsxs24(Text26, { children: [
17509
+ /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Phone: " }),
17510
+ userInfo?.phone ?? /* @__PURE__ */ jsx35(Text26, { dimColor: true, children: "Not set" })
16625
17511
  ] })
16626
17512
  ] })
16627
17513
  ] });
16628
17514
  };
16629
17515
 
16630
17516
  // src/commands/user-info/index.tsx
16631
- import { jsx as jsx32 } from "react/jsx-runtime";
17517
+ import { jsx as jsx36 } from "react/jsx-runtime";
16632
17518
  function createUserInfoCli(createResource, authStorage2, envAccessToken2) {
16633
- const cli2 = Cli11.create("user-info", {
17519
+ const cli2 = Cli13.create("user-info", {
16634
17520
  description: "User information commands"
16635
17521
  });
16636
17522
  cli2.command("retrieve", {
@@ -16641,7 +17527,7 @@ function createUserInfoCli(createResource, authStorage2, envAccessToken2) {
16641
17527
  const resource = createResource();
16642
17528
  if (!c.agent && !c.formatExplicit) {
16643
17529
  return renderInteractive(
16644
- /* @__PURE__ */ jsx32(UserInfoRetrieve, { resource, onComplete: () => {
17530
+ /* @__PURE__ */ jsx36(UserInfoRetrieve, { resource, onComplete: () => {
16645
17531
  } }),
16646
17532
  () => resource.retrieve()
16647
17533
  );
@@ -16692,11 +17578,55 @@ function requireFetchImplementation2(config) {
16692
17578
 
16693
17579
  // src/auth/auth-resource.ts
16694
17580
  var CLIENT_ID = "lwlpk_U7Qy7ThG69STZk";
16695
- var DEFAULT_SCOPE = "userinfo:read payment_methods.agentic";
16696
17581
  function formatOAuthError(prefix, status, data, rawBody) {
16697
17582
  const err = data;
16698
17583
  return `${prefix} (${status}): ${err?.error_description ?? err?.error ?? (rawBody || "unknown error")}`;
16699
17584
  }
17585
+ function appendAuthorizationDetailValue(params, key, value) {
17586
+ if (Array.isArray(value)) {
17587
+ for (const entry of value) {
17588
+ appendAuthorizationDetailValue(params, `${key}[]`, entry);
17589
+ }
17590
+ return;
17591
+ }
17592
+ if (value !== null && typeof value === "object") {
17593
+ for (const [entryKey, entryValue] of Object.entries(value)) {
17594
+ appendAuthorizationDetailValue(params, `${key}[${entryKey}]`, entryValue);
17595
+ }
17596
+ return;
17597
+ }
17598
+ params.append(key, String(value));
17599
+ }
17600
+ function buildDeviceCodeForm(clientName, options) {
17601
+ const connectionLabel = `${clientName} on ${hostname()}`;
17602
+ const params = new URLSearchParams({
17603
+ client_id: CLIENT_ID,
17604
+ scope: options.scope ?? DEFAULT_SCOPE,
17605
+ connection_label: connectionLabel,
17606
+ client_hint: clientName
17607
+ });
17608
+ const authorizationDetails = buildAuthorizationDetails(
17609
+ options.sourceActions,
17610
+ options.authorizationDetails
17611
+ );
17612
+ for (const detail of authorizationDetails) {
17613
+ appendAuthorizationDetailValue(params, "authorization_details[]", detail);
17614
+ }
17615
+ return params;
17616
+ }
17617
+ function serializeFormBody(params) {
17618
+ return params instanceof URLSearchParams ? params.toString() : new URLSearchParams(params).toString();
17619
+ }
17620
+ function serializeRedactedFormBody(params) {
17621
+ const redacted = new URLSearchParams(params);
17622
+ if (redacted.has("device_code")) {
17623
+ redacted.set("device_code", "<redacted>");
17624
+ }
17625
+ if (redacted.has("refresh_token")) {
17626
+ redacted.set("refresh_token", "<redacted>");
17627
+ }
17628
+ return redacted.toString();
17629
+ }
16700
17630
  var LinkAuthResource = class {
16701
17631
  config;
16702
17632
  fetchImpl;
@@ -16706,12 +17636,9 @@ var LinkAuthResource = class {
16706
17636
  }
16707
17637
  async postForm(url, params) {
16708
17638
  if (this.config.verbose) {
16709
- const redacted = { ...params };
16710
- if (redacted.device_code) redacted.device_code = "<redacted>";
16711
- if (redacted.refresh_token) redacted.refresh_token = "<redacted>";
16712
17639
  this.config.logger.debug(
16713
17640
  `> POST ${url}
16714
- ${JSON.stringify(redacted, null, 2)}`
17641
+ ${serializeRedactedFormBody(params)}`
16715
17642
  );
16716
17643
  }
16717
17644
  let response;
@@ -16722,7 +17649,7 @@ ${JSON.stringify(redacted, null, 2)}`
16722
17649
  ...this.config.defaultHeaders,
16723
17650
  "Content-Type": "application/x-www-form-urlencoded"
16724
17651
  },
16725
- body: new URLSearchParams(params).toString()
17652
+ body: serializeFormBody(params)
16726
17653
  });
16727
17654
  } catch (error) {
16728
17655
  throw new LinkTransportError(`Request failed: POST ${url}`, {
@@ -16744,16 +17671,12 @@ ${JSON.stringify(redacted, null, 2)}`
16744
17671
  }
16745
17672
  return { status: response.status, data, rawBody };
16746
17673
  }
16747
- async initiateDeviceAuth(clientName) {
16748
- const effectiveName = clientName ?? this.config.clientName;
17674
+ async initiateDeviceAuth(options = {}) {
17675
+ const effectiveName = options.clientName ?? this.config.clientName;
17676
+ const params = buildDeviceCodeForm(effectiveName, options);
16749
17677
  const { status, data, rawBody } = await this.postForm(
16750
17678
  `${this.config.authBaseUrl}/device/code`,
16751
- {
16752
- client_id: CLIENT_ID,
16753
- scope: DEFAULT_SCOPE,
16754
- connection_label: `${effectiveName} on ${hostname()}`,
16755
- client_hint: effectiveName
16756
- }
17679
+ params
16757
17680
  );
16758
17681
  if (status < 200 || status >= 300) {
16759
17682
  throw new LinkApiError(
@@ -16933,6 +17856,8 @@ var ResourceFactory = class {
16933
17856
  shippingAddressResource;
16934
17857
  userInfoResource;
16935
17858
  transactionsResource;
17859
+ sourcesResource;
17860
+ balancesResource;
16936
17861
  webBotAuthResource;
16937
17862
  reportResource;
16938
17863
  constructor(options = {}) {
@@ -17061,6 +17986,34 @@ var ResourceFactory = class {
17061
17986
  );
17062
17987
  return this.transactionsResource;
17063
17988
  }
17989
+ createSourcesResource() {
17990
+ if (this.sourcesResource) {
17991
+ return this.sourcesResource;
17992
+ }
17993
+ const getAccessToken = this.createSdkAccessTokenProvider();
17994
+ this.sourcesResource = sanitizeResource(
17995
+ new SourcesResource({
17996
+ verbose: this.verbose,
17997
+ defaultHeaders: this.defaultHeaders,
17998
+ getAccessToken
17999
+ })
18000
+ );
18001
+ return this.sourcesResource;
18002
+ }
18003
+ createBalancesResource() {
18004
+ if (this.balancesResource) {
18005
+ return this.balancesResource;
18006
+ }
18007
+ const getAccessToken = this.createSdkAccessTokenProvider();
18008
+ this.balancesResource = sanitizeResource(
18009
+ new BalancesResource({
18010
+ verbose: this.verbose,
18011
+ defaultHeaders: this.defaultHeaders,
18012
+ getAccessToken
18013
+ })
18014
+ );
18015
+ return this.balancesResource;
18016
+ }
17064
18017
  createWebBotAuthResource() {
17065
18018
  if (this.webBotAuthResource) {
17066
18019
  return this.webBotAuthResource;
@@ -17162,7 +18115,7 @@ function cacheUpdateInfo(value, ttlMs = UPDATE_CACHE_TTL_MS) {
17162
18115
  }
17163
18116
 
17164
18117
  // src/cli.tsx
17165
- var cliVersion = "0.8.3";
18118
+ var cliVersion = "0.10.0";
17166
18119
  var cliName = "@stripe/link-cli";
17167
18120
  var defaultHeaders = {
17168
18121
  "User-Agent": `link-cli/${cliVersion}`
@@ -17192,15 +18145,23 @@ var factory = new ResourceFactory({
17192
18145
  var authRepo = factory.createAuthResource();
17193
18146
  var spendRequestRepo = factory.createSpendRequestResource();
17194
18147
  var requestedCommand = process.argv[2];
17195
- var transactionsCli = requestedCommand === "transactions" ? createTransactionsCli(
18148
+ var hiddenCli = requestedCommand === "transactions" ? createTransactionsCli(
17196
18149
  () => factory.createTransactionsResource(),
17197
18150
  authStorage,
17198
18151
  envAccessToken
18152
+ ) : requestedCommand === "sources" ? createSourcesCli(
18153
+ () => factory.createSourcesResource(),
18154
+ authStorage,
18155
+ envAccessToken
18156
+ ) : requestedCommand === "balances" ? createBalancesCli(
18157
+ () => factory.createBalancesResource(),
18158
+ authStorage,
18159
+ envAccessToken
17199
18160
  ) : null;
17200
- if (transactionsCli) {
18161
+ if (hiddenCli) {
17201
18162
  process.argv.splice(2, 1);
17202
18163
  }
17203
- var cli = transactionsCli ?? Cli12.create("link-cli", {
18164
+ var cli = hiddenCli ?? Cli14.create("link-cli", {
17204
18165
  description: "Create a secure, one-time payment credential from a Link wallet to let agents complete purchases on behalf of users.",
17205
18166
  version: cliVersion
17206
18167
  });
@@ -17217,7 +18178,7 @@ if (!isAgent && process.stdout.isTTY) {
17217
18178
  process.stderr.write(renderInteractiveUpdateNotice(updateInfo));
17218
18179
  }
17219
18180
  }
17220
- if (!transactionsCli) {
18181
+ if (!hiddenCli) {
17221
18182
  cli.command(
17222
18183
  createAuthCli(authRepo, getUpdateInfo, authStorage, envAccessToken)
17223
18184
  );
@@ -17245,7 +18206,14 @@ if (!transactionsCli) {
17245
18206
  envAccessToken
17246
18207
  )
17247
18208
  );
17248
- cli.command(createMppCli(spendRequestRepo, authStorage, envAccessToken));
18209
+ cli.command(
18210
+ createMppCli(
18211
+ spendRequestRepo,
18212
+ () => factory.createPaymentMethodsResource(),
18213
+ authStorage,
18214
+ envAccessToken
18215
+ )
18216
+ );
17249
18217
  cli.command(
17250
18218
  createReportCli(
17251
18219
  () => factory.createReportResource(),