shopstack 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -70,7 +70,7 @@ deliberately has no card-input or payment-approval tool.
70
70
 
71
71
  The canonical agent skill ships as `SKILL.md` in this package. After
72
72
  publication it is available at
73
- `https://unpkg.com/shopstack@0.2.3/SKILL.md` with the release-pinned package.
73
+ `https://unpkg.com/shopstack@0.2.5/SKILL.md` with the release-pinned package.
74
74
 
75
75
  ## Connections
76
76
 
@@ -80,7 +80,10 @@ shopstack connect link
80
80
  ```
81
81
 
82
82
  Link is currently the only persistent payment provider. Connecting it is
83
- optional.
83
+ optional. `shopstack connect link` opens the HTTPS Link setup page, displays the
84
+ confirmation phrase, and checks the connection every five seconds for up to
85
+ five minutes. It prints `Link connected` when the connection is ready. If a
86
+ browser cannot open automatically, use the exact URL printed in the terminal.
84
87
 
85
88
  ## Run a checkout
86
89
 
@@ -125,6 +128,9 @@ Treat the printed URL as opaque and open it exactly as returned, including its
125
128
  `#token=...` fragment. If that fragment is lost while the checkout is active,
126
129
  run `shopstack checkout view CHECKOUT_ID` to receive a replacement URL. The
127
130
  replacement disconnects an older viewer session but does not restart checkout.
131
+ Omit `model_handle` to use the production GLM route. Set it to `qwen` only when
132
+ you explicitly need the fixed Qwen comparison route.
133
+
128
134
  When no provider is selected, the checkout runs normally until the payment
129
135
  form, then asks for card details through a no-echo terminal prompt. Card data is
130
136
  sent only to the protected payment-details endpoint. The CLI separately shows
package/SKILL.md CHANGED
@@ -69,6 +69,11 @@ shopstack connect list
69
69
  shopstack connect link
70
70
  ```
71
71
 
72
+ The Link command opens the HTTPS setup page, displays the confirmation phrase,
73
+ and checks every five seconds for up to five minutes. Continue only after it
74
+ prints `Link connected` and reports `checkout_ready: true`. If the browser does
75
+ not open automatically, open the exact URL printed in the terminal.
76
+
72
77
  Include `payment_provider: "link"` only when the active user's Link connection reports checkout-ready. Otherwise omit `payment_provider`. Shopstack will run until card entry and request one protected checkout-scoped card through the SDK or no-echo CLI prompt.
73
78
 
74
79
  Never put card data in MCP arguments, natural-language messages, model output, logs, or ordinary CLI flags.
@@ -141,7 +146,7 @@ replacement verbatim.
141
146
 
142
147
  - Use `GET/POST /v1/checkout/{id}/messages` only for ordinary missing information.
143
148
  - Use protected SDK/CLI payment input when `required_input.type` is `payment_card`.
144
- - Use only the dedicated payment-approval endpoint from a separately scoped trusted backend.
149
+ - Use only the dedicated payment-approval endpoint with the owning user's credential.
145
150
  - MCP and messages cannot approve payment and expose no approval tool.
146
151
  - Never infer approval from a user's conversational message.
147
152
  - Cancel with the typed cancellation operation if the user withdraws the request.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopstack",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Production Shopstack SDK and CLI for agentic checkout.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -26,8 +26,8 @@
26
26
  "check": "npm run format:check && npm run test:coverage",
27
27
  "format:check": "prettier --check .",
28
28
  "shopstack": "node ./bin/shopstack",
29
- "test": "node --test test",
30
- "test:coverage": "node --test --experimental-test-coverage test",
29
+ "test": "node --test test/*.test.js",
30
+ "test:coverage": "node --test --experimental-test-coverage test/*.test.js",
31
31
  "prepublishOnly": "npm run check"
32
32
  },
33
33
  "engines": {
package/src/cli.js CHANGED
@@ -1,10 +1,15 @@
1
+ import { spawn } from "node:child_process";
1
2
  import { readFile } from "node:fs/promises";
2
3
  import { createInterface } from "node:readline/promises";
3
4
 
4
5
  import { ShopstackClient } from "./client.js";
5
6
  import { ConfigStore } from "./config.js";
6
7
 
7
- const VERSION = "0.2.2";
8
+ const VERSION = JSON.parse(
9
+ await readFile(new URL("../package.json", import.meta.url), "utf8"),
10
+ ).version;
11
+ const LINK_POLL_ATTEMPTS = 60;
12
+ const LINK_POLL_INTERVAL_MS = 5_000;
8
13
 
9
14
  const HELP = `Shopstack CLI ${VERSION}
10
15
 
@@ -90,6 +95,77 @@ function writeJson(stream, value) {
90
95
  stream.write(`${JSON.stringify(value, null, 2)}\n`);
91
96
  }
92
97
 
98
+ function delay(milliseconds) {
99
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
100
+ }
101
+
102
+ async function openExternal(url) {
103
+ const parsed = new URL(url);
104
+ if (parsed.protocol !== "https:") {
105
+ throw new Error("Only HTTPS connection URLs can be opened.");
106
+ }
107
+ const [command, args] =
108
+ process.platform === "darwin"
109
+ ? ["open", [url]]
110
+ : process.platform === "win32"
111
+ ? ["cmd.exe", ["/d", "/s", "/c", "start", "", url]]
112
+ : ["xdg-open", [url]];
113
+ await new Promise((resolve, reject) => {
114
+ const child = spawn(command, args, { detached: true, stdio: "ignore" });
115
+ child.once("error", reject);
116
+ child.once("spawn", () => {
117
+ child.unref();
118
+ resolve();
119
+ });
120
+ });
121
+ }
122
+
123
+ async function connectLink(client, dependencies) {
124
+ let result = await client.connect("link");
125
+ if (
126
+ result.connection_status !== "action_required" ||
127
+ typeof result.connect_url !== "string"
128
+ ) {
129
+ return result;
130
+ }
131
+
132
+ dependencies.stderr.write(`Open Link: ${result.connect_url}\n`);
133
+ if (typeof result.phrase === "string") {
134
+ dependencies.stderr.write(`Confirmation phrase: ${result.phrase}\n`);
135
+ }
136
+ try {
137
+ await dependencies.openExternal(result.connect_url);
138
+ } catch {
139
+ dependencies.stderr.write(
140
+ "The browser could not open automatically. Open the URL shown above.\n",
141
+ );
142
+ }
143
+ dependencies.stderr.write("Waiting for Link confirmation...\n");
144
+
145
+ for (let attempt = 0; attempt < dependencies.linkPollAttempts; attempt += 1) {
146
+ await dependencies.delay(dependencies.linkPollIntervalMs);
147
+ result = await client.connect("link");
148
+ if (
149
+ result.connection_status === "active" &&
150
+ result.checkout_ready === true
151
+ ) {
152
+ dependencies.stderr.write("✓ Link connected\n");
153
+ return result;
154
+ }
155
+ if (
156
+ result.connection_status !== "action_required" &&
157
+ result.connection_status !== "connecting"
158
+ ) {
159
+ return result;
160
+ }
161
+ }
162
+
163
+ dependencies.stderr.write(
164
+ "Link setup is still pending. Run `shopstack connect link` to resume.\n",
165
+ );
166
+ return result;
167
+ }
168
+
93
169
  async function readJsonFile(path) {
94
170
  return JSON.parse(await readFile(path, "utf8"));
95
171
  }
@@ -264,6 +340,10 @@ export async function runCli(args, supplied = {}) {
264
340
  clientFactory: (options) => new ShopstackClient(options),
265
341
  configStore: new ConfigStore(),
266
342
  confirm: undefined,
343
+ delay,
344
+ linkPollAttempts: LINK_POLL_ATTEMPTS,
345
+ linkPollIntervalMs: LINK_POLL_INTERVAL_MS,
346
+ openExternal,
267
347
  prompt: undefined,
268
348
  readJsonFile,
269
349
  secretPrompt: undefined,
@@ -472,7 +552,7 @@ export async function runCli(args, supplied = {}) {
472
552
  const result =
473
553
  action === "list"
474
554
  ? await client.listConnections()
475
- : await client.connect("link");
555
+ : await connectLink(client, dependencies);
476
556
  writeJson(dependencies.stdout, result);
477
557
  return;
478
558
  }