@artos-commerce/ucp-cli 0.1.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.
- package/README.md +177 -0
- package/dist/agent.d.ts +35 -0
- package/dist/agent.js +46 -0
- package/dist/agent.js.map +1 -0
- package/dist/args.d.ts +20 -0
- package/dist/args.js +58 -0
- package/dist/args.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.js +250 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/account.d.ts +19 -0
- package/dist/commands/account.js +31 -0
- package/dist/commands/account.js.map +1 -0
- package/dist/commands/cart.d.ts +17 -0
- package/dist/commands/cart.js +51 -0
- package/dist/commands/cart.js.map +1 -0
- package/dist/commands/catalog-search.d.ts +22 -0
- package/dist/commands/catalog-search.js +27 -0
- package/dist/commands/catalog-search.js.map +1 -0
- package/dist/commands/checkout.d.ts +20 -0
- package/dist/commands/checkout.js +52 -0
- package/dist/commands/checkout.js.map +1 -0
- package/dist/commands/discover.d.ts +13 -0
- package/dist/commands/discover.js +27 -0
- package/dist/commands/discover.js.map +1 -0
- package/dist/commands/init.d.ts +16 -0
- package/dist/commands/init.js +222 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/profile-init.d.ts +22 -0
- package/dist/commands/profile-init.js +34 -0
- package/dist/commands/profile-init.js.map +1 -0
- package/dist/commands/purchase.d.ts +22 -0
- package/dist/commands/purchase.js +29 -0
- package/dist/commands/purchase.js.map +1 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.js +22 -0
- package/dist/config.js.map +1 -0
- package/dist/conformance.d.ts +35 -0
- package/dist/conformance.js +240 -0
- package/dist/conformance.js.map +1 -0
- package/dist/doctor.d.ts +23 -0
- package/dist/doctor.js +123 -0
- package/dist/doctor.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +24 -0
- package/dist/io.js +2 -0
- package/dist/io.js.map +1 -0
- package/dist/output.d.ts +38 -0
- package/dist/output.js +131 -0
- package/dist/output.js.map +1 -0
- package/dist/profile.d.ts +38 -0
- package/dist/profile.js +43 -0
- package/dist/profile.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"purchase.js","sourceRoot":"","sources":["../../src/commands/purchase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAqB7C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAkB,EAClB,IAAkB;IAElB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;QAC1C,IAAI,CAAC,EAAE,CAAC,KAAK,CACX,sEAAsE,CACvE,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;QACjC,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,UAAU,EAAE,IAAI,CAAC,EAAE;QACnB,aAAa,EAAE,IAAI,CAAC,GAAG;QACvB,gBAAgB,EAAE,IAAI,CAAC,OAAO;QAC9B,WAAW,EAAE,IAAI,CAAC,WAAW;KAC9B,CAAC,CAAC;IAEH,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3D,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,WAAW;YACd,OAAO,CAAC,CAAC;QACX,KAAK,qBAAqB,CAAC;QAC3B,KAAK,4BAA4B;YAC/B,OAAO,CAAC,CAAC;QACX,KAAK,OAAO;YACV,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the CLI's connection config from flags (highest priority), then the
|
|
3
|
+
* environment, then sensible defaults. Catalog discovery is anonymous-tier, so
|
|
4
|
+
* the platform key and agent profile fall back to placeholders that let
|
|
5
|
+
* read-only commands run; `doctor` flags when they are unset.
|
|
6
|
+
*/
|
|
7
|
+
export interface CliConfig {
|
|
8
|
+
/** Artos API base URL, no trailing slash. */
|
|
9
|
+
artosBaseUrl: string;
|
|
10
|
+
/** Platform (cross-store) UCP API key: `<clientId>.<secret>`. */
|
|
11
|
+
platformApiKey: string;
|
|
12
|
+
/** HTTPS URL of the agent's published UCP profile (sent in `UCP-Agent`). */
|
|
13
|
+
platformProfileUrl: string;
|
|
14
|
+
}
|
|
15
|
+
/** Global flags that can override the environment for any command. */
|
|
16
|
+
export interface GlobalFlags {
|
|
17
|
+
api?: string;
|
|
18
|
+
key?: string;
|
|
19
|
+
profile?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const DEFAULT_API_URL = "https://api.artos.sh";
|
|
22
|
+
export declare const PLACEHOLDER_KEY = "ck_demo.placeholder";
|
|
23
|
+
export declare const PLACEHOLDER_PROFILE = "https://example.com/.well-known/ucp";
|
|
24
|
+
export declare function resolveConfig(env: NodeJS.ProcessEnv, flags?: GlobalFlags): CliConfig;
|
|
25
|
+
/** True when no real platform API key was supplied (running on the placeholder). */
|
|
26
|
+
export declare function usesPlaceholderKey(cfg: CliConfig): boolean;
|
|
27
|
+
/** True when no real agent profile URL was supplied. */
|
|
28
|
+
export declare function usesPlaceholderProfile(cfg: CliConfig): boolean;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const DEFAULT_API_URL = 'https://api.artos.sh';
|
|
2
|
+
export const PLACEHOLDER_KEY = 'ck_demo.placeholder';
|
|
3
|
+
export const PLACEHOLDER_PROFILE = 'https://example.com/.well-known/ucp';
|
|
4
|
+
function stripTrailingSlash(url) {
|
|
5
|
+
return url.trim().replace(/\/+$/, '');
|
|
6
|
+
}
|
|
7
|
+
export function resolveConfig(env, flags = {}) {
|
|
8
|
+
return {
|
|
9
|
+
artosBaseUrl: stripTrailingSlash(flags.api ?? env.ARTOS_BASE_URL ?? DEFAULT_API_URL),
|
|
10
|
+
platformApiKey: flags.key ?? env.UCP_PLATFORM_API_KEY ?? PLACEHOLDER_KEY,
|
|
11
|
+
platformProfileUrl: flags.profile ?? env.PLATFORM_PROFILE_URL ?? PLACEHOLDER_PROFILE,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/** True when no real platform API key was supplied (running on the placeholder). */
|
|
15
|
+
export function usesPlaceholderKey(cfg) {
|
|
16
|
+
return cfg.platformApiKey === PLACEHOLDER_KEY;
|
|
17
|
+
}
|
|
18
|
+
/** True when no real agent profile URL was supplied. */
|
|
19
|
+
export function usesPlaceholderProfile(cfg) {
|
|
20
|
+
return cfg.platformProfileUrl === PLACEHOLDER_PROFILE;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAC;AACtD,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AACrD,MAAM,CAAC,MAAM,mBAAmB,GAAG,qCAAqC,CAAC;AAEzE,SAAS,kBAAkB,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,GAAsB,EACtB,QAAqB,EAAE;IAEvB,OAAO;QACL,YAAY,EAAE,kBAAkB,CAC9B,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,cAAc,IAAI,eAAe,CACnD;QACD,cAAc,EAAE,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,oBAAoB,IAAI,eAAe;QACxE,kBAAkB,EAChB,KAAK,CAAC,OAAO,IAAI,GAAG,CAAC,oBAAoB,IAAI,mBAAmB;KACnE,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,kBAAkB,CAAC,GAAc;IAC/C,OAAO,GAAG,CAAC,cAAc,KAAK,eAAe,CAAC;AAChD,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,sBAAsB,CAAC,GAAc;IACnD,OAAO,GAAG,CAAC,kBAAkB,KAAK,mBAAmB,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type CliConfig } from './config.js';
|
|
2
|
+
import type { DoctorCheck } from './doctor.js';
|
|
3
|
+
export interface ConformanceReport {
|
|
4
|
+
ok: boolean;
|
|
5
|
+
checks: DoctorCheck[];
|
|
6
|
+
}
|
|
7
|
+
export interface ConformanceDeps {
|
|
8
|
+
cfg: CliConfig;
|
|
9
|
+
fetch: typeof fetch;
|
|
10
|
+
/**
|
|
11
|
+
* Runs a minimal cross-store catalog search, resolving on success and
|
|
12
|
+
* rejecting on any transport / UCP error. Injected so the check exercises the
|
|
13
|
+
* real SDK request shape (headers + envelope) without this module importing
|
|
14
|
+
* the client.
|
|
15
|
+
*/
|
|
16
|
+
search: () => Promise<unknown>;
|
|
17
|
+
/** Expected UCP spec version (defaults to the CLI's {@link UCP_VERSION}). */
|
|
18
|
+
expectedVersion?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ConformanceArgs {
|
|
21
|
+
/** When set, also verifies the store publishes signing keys for AP2. */
|
|
22
|
+
store?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Runs a battery of live UCP conformance checks against a deployment: the
|
|
26
|
+
* platform discovery profile and its declared version, the OAuth Authorization
|
|
27
|
+
* Server metadata (endpoints, PKCE, scopes) buyers sign in against, the
|
|
28
|
+
* cross-store catalog search, the buyer-bound 401 + `WWW-Authenticate` relay
|
|
29
|
+
* contract, and (when a store is given) that the store publishes signing keys
|
|
30
|
+
* for AP2 verification. Every probe is reported as pass/warn/fail — network
|
|
31
|
+
* failures become `fail`, never thrown — so the full report always renders.
|
|
32
|
+
*/
|
|
33
|
+
export declare function runConformance(deps: ConformanceDeps, args?: ConformanceArgs): Promise<ConformanceReport>;
|
|
34
|
+
/** Renders a conformance report as plain text for the terminal. */
|
|
35
|
+
export declare function formatConformance(report: ConformanceReport): string;
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { usesPlaceholderKey } from './config.js';
|
|
2
|
+
import { UCP_VERSION } from './profile.js';
|
|
3
|
+
const TIMEOUT_MS = 8000;
|
|
4
|
+
async function fetchJson(fetchFn, url, init) {
|
|
5
|
+
const controller = new AbortController();
|
|
6
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
7
|
+
try {
|
|
8
|
+
const res = await fetchFn(url, {
|
|
9
|
+
...init,
|
|
10
|
+
signal: controller.signal,
|
|
11
|
+
headers: { accept: 'application/json', ...init?.headers },
|
|
12
|
+
});
|
|
13
|
+
let body = {};
|
|
14
|
+
try {
|
|
15
|
+
body = (await res.json());
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
body = {};
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
status: res.status,
|
|
22
|
+
wwwAuthenticate: res.headers?.get('www-authenticate') ?? null,
|
|
23
|
+
body,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function asArray(value) {
|
|
31
|
+
return Array.isArray(value) ? value : [];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Runs a battery of live UCP conformance checks against a deployment: the
|
|
35
|
+
* platform discovery profile and its declared version, the OAuth Authorization
|
|
36
|
+
* Server metadata (endpoints, PKCE, scopes) buyers sign in against, the
|
|
37
|
+
* cross-store catalog search, the buyer-bound 401 + `WWW-Authenticate` relay
|
|
38
|
+
* contract, and (when a store is given) that the store publishes signing keys
|
|
39
|
+
* for AP2 verification. Every probe is reported as pass/warn/fail — network
|
|
40
|
+
* failures become `fail`, never thrown — so the full report always renders.
|
|
41
|
+
*/
|
|
42
|
+
export async function runConformance(deps, args = {}) {
|
|
43
|
+
const { cfg, fetch: fetchFn } = deps;
|
|
44
|
+
const expected = deps.expectedVersion ?? UCP_VERSION;
|
|
45
|
+
const checks = [];
|
|
46
|
+
// 1. Platform discovery profile + declared UCP version.
|
|
47
|
+
const discoveryUrl = `${cfg.artosBaseUrl}/.well-known/ucp`;
|
|
48
|
+
try {
|
|
49
|
+
const { body } = await fetchJson(fetchFn, discoveryUrl);
|
|
50
|
+
const ucp = body.ucp;
|
|
51
|
+
const version = ucp?.version;
|
|
52
|
+
if (!version)
|
|
53
|
+
throw new Error('missing ucp.version');
|
|
54
|
+
checks.push(version === expected
|
|
55
|
+
? {
|
|
56
|
+
name: 'discovery',
|
|
57
|
+
status: 'pass',
|
|
58
|
+
detail: `UCP ${version} (matches client ${expected}).`,
|
|
59
|
+
}
|
|
60
|
+
: {
|
|
61
|
+
name: 'discovery',
|
|
62
|
+
status: 'warn',
|
|
63
|
+
detail: `server UCP ${version} differs from client ${expected} — check for a version mismatch.`,
|
|
64
|
+
});
|
|
65
|
+
const handlers = body.payment_handlers;
|
|
66
|
+
const hasHandlers = typeof handlers === 'object' &&
|
|
67
|
+
handlers !== null &&
|
|
68
|
+
!Array.isArray(handlers);
|
|
69
|
+
const hasCaps = typeof ucp?.capabilities === 'object' && ucp.capabilities !== null;
|
|
70
|
+
checks.push(hasHandlers && hasCaps
|
|
71
|
+
? {
|
|
72
|
+
name: 'platform-profile',
|
|
73
|
+
status: 'pass',
|
|
74
|
+
detail: 'Declares payment_handlers and capabilities.',
|
|
75
|
+
}
|
|
76
|
+
: {
|
|
77
|
+
name: 'platform-profile',
|
|
78
|
+
status: 'warn',
|
|
79
|
+
detail: `Missing ${!hasHandlers ? 'payment_handlers' : 'capabilities'} in the discovery profile.`,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
checks.push({
|
|
84
|
+
name: 'discovery',
|
|
85
|
+
status: 'fail',
|
|
86
|
+
detail: `${discoveryUrl}: ${err.message}`,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// 2. OAuth Authorization Server metadata (endpoints, PKCE, scopes).
|
|
90
|
+
const asUrl = `${cfg.artosBaseUrl}/.well-known/oauth-authorization-server`;
|
|
91
|
+
try {
|
|
92
|
+
const { body } = await fetchJson(fetchFn, asUrl);
|
|
93
|
+
checks.push(body.authorization_endpoint && body.token_endpoint
|
|
94
|
+
? {
|
|
95
|
+
name: 'oauth-endpoints',
|
|
96
|
+
status: 'pass',
|
|
97
|
+
detail: 'authorization_endpoint and token_endpoint present.',
|
|
98
|
+
}
|
|
99
|
+
: {
|
|
100
|
+
name: 'oauth-endpoints',
|
|
101
|
+
status: 'fail',
|
|
102
|
+
detail: `${asUrl}: missing authorization_endpoint or token_endpoint.`,
|
|
103
|
+
});
|
|
104
|
+
const pkce = asArray(body.code_challenge_methods_supported);
|
|
105
|
+
checks.push(pkce.includes('S256')
|
|
106
|
+
? {
|
|
107
|
+
name: 'oauth-pkce',
|
|
108
|
+
status: 'pass',
|
|
109
|
+
detail: 'Advertises PKCE S256.',
|
|
110
|
+
}
|
|
111
|
+
: {
|
|
112
|
+
name: 'oauth-pkce',
|
|
113
|
+
status: 'fail',
|
|
114
|
+
detail: 'code_challenge_methods_supported does not include "S256" — Build-track OAuth requires it.',
|
|
115
|
+
});
|
|
116
|
+
const scopes = asArray(body.scopes_supported);
|
|
117
|
+
const missing = ['offline_access', 'purchase:complete'].filter((s) => !scopes.includes(s));
|
|
118
|
+
checks.push(missing.length === 0
|
|
119
|
+
? {
|
|
120
|
+
name: 'oauth-scopes',
|
|
121
|
+
status: 'pass',
|
|
122
|
+
detail: 'Advertises offline_access and purchase:complete.',
|
|
123
|
+
}
|
|
124
|
+
: {
|
|
125
|
+
name: 'oauth-scopes',
|
|
126
|
+
status: 'warn',
|
|
127
|
+
detail: `scopes_supported missing: ${missing.join(', ')}.`,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
checks.push({
|
|
132
|
+
name: 'oauth-metadata',
|
|
133
|
+
status: 'fail',
|
|
134
|
+
detail: `${asUrl}: ${err.message}`,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
// 3. Cross-store catalog search.
|
|
138
|
+
if (usesPlaceholderKey(cfg)) {
|
|
139
|
+
checks.push({
|
|
140
|
+
name: 'catalog-search',
|
|
141
|
+
status: 'warn',
|
|
142
|
+
detail: 'Skipped — no platform API key configured (set UCP_PLATFORM_API_KEY).',
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
try {
|
|
147
|
+
await deps.search();
|
|
148
|
+
checks.push({
|
|
149
|
+
name: 'catalog-search',
|
|
150
|
+
status: 'pass',
|
|
151
|
+
detail: 'POST /catalog/search returned a success envelope.',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
checks.push({
|
|
156
|
+
name: 'catalog-search',
|
|
157
|
+
status: 'fail',
|
|
158
|
+
detail: `catalog search failed: ${err.message}`,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// 4. Buyer-bound 401 + WWW-Authenticate relay contract.
|
|
163
|
+
const mcpUrl = `${cfg.artosBaseUrl}/account/mcp`;
|
|
164
|
+
try {
|
|
165
|
+
const { status, wwwAuthenticate } = await fetchJson(fetchFn, mcpUrl, {
|
|
166
|
+
method: 'POST',
|
|
167
|
+
headers: { 'content-type': 'application/json' },
|
|
168
|
+
body: JSON.stringify({ jsonrpc: '2.0', id: '1', method: 'tools/list' }),
|
|
169
|
+
});
|
|
170
|
+
if (status === 401 && wwwAuthenticate) {
|
|
171
|
+
checks.push({
|
|
172
|
+
name: 'auth-challenge',
|
|
173
|
+
status: 'pass',
|
|
174
|
+
detail: '401 + WWW-Authenticate on an unauthenticated buyer call.',
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
else if (status === 401) {
|
|
178
|
+
checks.push({
|
|
179
|
+
name: 'auth-challenge',
|
|
180
|
+
status: 'warn',
|
|
181
|
+
detail: '401 without a WWW-Authenticate header — silent refresh may break.',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
checks.push({
|
|
186
|
+
name: 'auth-challenge',
|
|
187
|
+
status: 'warn',
|
|
188
|
+
detail: `expected 401 on an unauthenticated buyer call, got ${status}.`,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
checks.push({
|
|
194
|
+
name: 'auth-challenge',
|
|
195
|
+
status: 'warn',
|
|
196
|
+
detail: `could not probe ${mcpUrl}: ${err.message}`,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
// 5. Store signing keys (AP2) — only when a store is given.
|
|
200
|
+
if (args.store) {
|
|
201
|
+
const storeUrl = `${cfg.artosBaseUrl}/s/${args.store}/.well-known/ucp`;
|
|
202
|
+
try {
|
|
203
|
+
const { body } = await fetchJson(fetchFn, storeUrl);
|
|
204
|
+
const keys = asArray(body.signing_keys);
|
|
205
|
+
checks.push(keys.length > 0
|
|
206
|
+
? {
|
|
207
|
+
name: 'store-signing-keys',
|
|
208
|
+
status: 'pass',
|
|
209
|
+
detail: `${args.store} publishes ${keys.length} signing key(s).`,
|
|
210
|
+
}
|
|
211
|
+
: {
|
|
212
|
+
name: 'store-signing-keys',
|
|
213
|
+
status: 'fail',
|
|
214
|
+
detail: `${args.store} publishes no signing_keys — merchant_authorization cannot be verified.`,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
checks.push({
|
|
219
|
+
name: 'store-signing-keys',
|
|
220
|
+
status: 'fail',
|
|
221
|
+
detail: `${storeUrl}: ${err.message}`,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return { ok: checks.every((c) => c.status !== 'fail'), checks };
|
|
226
|
+
}
|
|
227
|
+
const ICON = {
|
|
228
|
+
pass: 'OK ',
|
|
229
|
+
warn: 'WARN',
|
|
230
|
+
fail: 'FAIL',
|
|
231
|
+
};
|
|
232
|
+
/** Renders a conformance report as plain text for the terminal. */
|
|
233
|
+
export function formatConformance(report) {
|
|
234
|
+
const lines = report.checks.map((c) => `[${ICON[c.status]}] ${c.name} — ${c.detail}`);
|
|
235
|
+
lines.push(report.ok
|
|
236
|
+
? 'conformance: all required checks passed.'
|
|
237
|
+
: 'conformance: one or more checks FAILED.');
|
|
238
|
+
return lines.join('\n');
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../src/conformance.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type CliConfig } from './config.js';
|
|
2
|
+
export interface DoctorCheck {
|
|
3
|
+
name: string;
|
|
4
|
+
status: 'pass' | 'warn' | 'fail';
|
|
5
|
+
detail: string;
|
|
6
|
+
}
|
|
7
|
+
export interface DoctorReport {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
checks: DoctorCheck[];
|
|
10
|
+
}
|
|
11
|
+
export interface DoctorDeps {
|
|
12
|
+
cfg: CliConfig;
|
|
13
|
+
fetch: typeof fetch;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Checks the developer's connection to Artos: the platform key, the API's UCP
|
|
17
|
+
* discovery profile, the OAuth Authorization Server metadata buyers sign in
|
|
18
|
+
* against, and (when configured) the agent's own published profile. Network
|
|
19
|
+
* failures are reported as `fail`, not thrown, so every check is always listed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function runDoctor(deps: DoctorDeps): Promise<DoctorReport>;
|
|
22
|
+
/** Renders a report as plain text for the terminal. */
|
|
23
|
+
export declare function formatReport(report: DoctorReport): string;
|
package/dist/doctor.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { usesPlaceholderKey, usesPlaceholderProfile, } from './config.js';
|
|
2
|
+
const TIMEOUT_MS = 5000;
|
|
3
|
+
async function getJson(fetchFn, url) {
|
|
4
|
+
const controller = new AbortController();
|
|
5
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
6
|
+
try {
|
|
7
|
+
const res = await fetchFn(url, {
|
|
8
|
+
signal: controller.signal,
|
|
9
|
+
headers: { accept: 'application/json' },
|
|
10
|
+
});
|
|
11
|
+
if (!res.ok)
|
|
12
|
+
throw new Error(`HTTP ${res.status}`);
|
|
13
|
+
return (await res.json());
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
clearTimeout(timer);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Checks the developer's connection to Artos: the platform key, the API's UCP
|
|
21
|
+
* discovery profile, the OAuth Authorization Server metadata buyers sign in
|
|
22
|
+
* against, and (when configured) the agent's own published profile. Network
|
|
23
|
+
* failures are reported as `fail`, not thrown, so every check is always listed.
|
|
24
|
+
*/
|
|
25
|
+
export async function runDoctor(deps) {
|
|
26
|
+
const { cfg, fetch: fetchFn } = deps;
|
|
27
|
+
const checks = [];
|
|
28
|
+
checks.push(usesPlaceholderKey(cfg)
|
|
29
|
+
? {
|
|
30
|
+
name: 'platform-key',
|
|
31
|
+
status: 'warn',
|
|
32
|
+
detail: 'No UCP_PLATFORM_API_KEY (or --key) — anonymous catalog only; cart/checkout need a real key.',
|
|
33
|
+
}
|
|
34
|
+
: {
|
|
35
|
+
name: 'platform-key',
|
|
36
|
+
status: 'pass',
|
|
37
|
+
detail: 'Platform API key configured.',
|
|
38
|
+
});
|
|
39
|
+
const apiUrl = `${cfg.artosBaseUrl}/.well-known/ucp`;
|
|
40
|
+
try {
|
|
41
|
+
const body = await getJson(fetchFn, apiUrl);
|
|
42
|
+
const ucp = body.ucp;
|
|
43
|
+
checks.push({
|
|
44
|
+
name: 'api-reachable',
|
|
45
|
+
status: 'pass',
|
|
46
|
+
detail: `${apiUrl} (UCP ${ucp?.version ?? 'unknown'})`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
checks.push({
|
|
51
|
+
name: 'api-reachable',
|
|
52
|
+
status: 'fail',
|
|
53
|
+
detail: `${apiUrl}: ${err.message}`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const asUrl = `${cfg.artosBaseUrl}/.well-known/oauth-authorization-server`;
|
|
57
|
+
try {
|
|
58
|
+
const body = await getJson(fetchFn, asUrl);
|
|
59
|
+
checks.push(body.token_endpoint
|
|
60
|
+
? {
|
|
61
|
+
name: 'oauth-metadata',
|
|
62
|
+
status: 'pass',
|
|
63
|
+
detail: `${asUrl} (token_endpoint present)`,
|
|
64
|
+
}
|
|
65
|
+
: {
|
|
66
|
+
name: 'oauth-metadata',
|
|
67
|
+
status: 'fail',
|
|
68
|
+
detail: `${asUrl}: missing token_endpoint`,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
checks.push({
|
|
73
|
+
name: 'oauth-metadata',
|
|
74
|
+
status: 'fail',
|
|
75
|
+
detail: `${asUrl}: ${err.message}`,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (usesPlaceholderProfile(cfg)) {
|
|
79
|
+
checks.push({
|
|
80
|
+
name: 'agent-profile',
|
|
81
|
+
status: 'warn',
|
|
82
|
+
detail: 'No PLATFORM_PROFILE_URL (or --profile) — run `artos profile init` and host the result.',
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
try {
|
|
87
|
+
const body = await getJson(fetchFn, cfg.platformProfileUrl);
|
|
88
|
+
const ucp = body.ucp;
|
|
89
|
+
const keys = body.signing_keys;
|
|
90
|
+
if (!ucp?.version)
|
|
91
|
+
throw new Error('missing ucp.version');
|
|
92
|
+
checks.push({
|
|
93
|
+
name: 'agent-profile',
|
|
94
|
+
status: keys && keys.length > 0 ? 'pass' : 'warn',
|
|
95
|
+
detail: keys && keys.length > 0
|
|
96
|
+
? `${cfg.platformProfileUrl} (UCP ${ucp.version}, ${keys.length} signing key(s))`
|
|
97
|
+
: `${cfg.platformProfileUrl} has no signing_keys — AP2 verification will fail.`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
checks.push({
|
|
102
|
+
name: 'agent-profile',
|
|
103
|
+
status: 'fail',
|
|
104
|
+
detail: `${cfg.platformProfileUrl}: ${err.message}`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { ok: checks.every((c) => c.status !== 'fail'), checks };
|
|
109
|
+
}
|
|
110
|
+
const ICON = {
|
|
111
|
+
pass: 'OK ',
|
|
112
|
+
warn: 'WARN',
|
|
113
|
+
fail: 'FAIL',
|
|
114
|
+
};
|
|
115
|
+
/** Renders a report as plain text for the terminal. */
|
|
116
|
+
export function formatReport(report) {
|
|
117
|
+
const lines = report.checks.map((c) => `[${ICON[c.status]}] ${c.name} — ${c.detail}`);
|
|
118
|
+
lines.push(report.ok
|
|
119
|
+
? 'doctor: all checks passed.'
|
|
120
|
+
: 'doctor: one or more checks FAILED.');
|
|
121
|
+
return lines.join('\n');
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { run } from './cli.js';
|
|
4
|
+
function withNewline(text) {
|
|
5
|
+
return text.endsWith('\n') ? text : `${text}\n`;
|
|
6
|
+
}
|
|
7
|
+
const io = {
|
|
8
|
+
write: (text) => process.stdout.write(withNewline(text)),
|
|
9
|
+
error: (text) => process.stderr.write(withNewline(text)),
|
|
10
|
+
env: process.env,
|
|
11
|
+
cwd: process.cwd(),
|
|
12
|
+
fetch: globalThis.fetch.bind(globalThis),
|
|
13
|
+
mkdir: (path) => mkdirSync(path, { recursive: true }),
|
|
14
|
+
writeFile: (path, contents) => writeFileSync(path, contents, 'utf8'),
|
|
15
|
+
exists: (path) => existsSync(path),
|
|
16
|
+
};
|
|
17
|
+
run(process.argv.slice(2), io)
|
|
18
|
+
.then((code) => {
|
|
19
|
+
process.exitCode = code;
|
|
20
|
+
})
|
|
21
|
+
.catch((err) => {
|
|
22
|
+
process.stderr.write(`artos: ${err.message}\n`);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAG/B,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC;AAClD,CAAC;AAED,MAAM,EAAE,GAAO;IACb,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACxD,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACxD,GAAG,EAAE,OAAO,CAAC,GAAG;IAChB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;IAClB,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;IACxC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACrD,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC;IACpE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;CACnC,CAAC;AAEF,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;KAC3B,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;IACb,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAW,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;IAC3D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
package/dist/io.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The side-effecting boundary the CLI runs against. Everything that touches the
|
|
3
|
+
* outside world (stdout/stderr, the environment, the filesystem, the network)
|
|
4
|
+
* goes through this seam so commands stay pure and unit-test with fakes. The
|
|
5
|
+
* real implementation is assembled in {@link import('./index.js')}.
|
|
6
|
+
*/
|
|
7
|
+
export interface Io {
|
|
8
|
+
/** Writes to stdout (machine-consumable output). */
|
|
9
|
+
write: (text: string) => void;
|
|
10
|
+
/** Writes to stderr (human/operational messages, errors, diagnostics). */
|
|
11
|
+
error: (text: string) => void;
|
|
12
|
+
/** Process environment (config resolution). */
|
|
13
|
+
env: NodeJS.ProcessEnv;
|
|
14
|
+
/** Current working directory (relative path resolution, e.g. `profile init`). */
|
|
15
|
+
cwd: string;
|
|
16
|
+
/** `fetch` implementation (injected so tests never hit the network). */
|
|
17
|
+
fetch: typeof fetch;
|
|
18
|
+
/** Creates a directory (recursive). */
|
|
19
|
+
mkdir: (path: string) => void;
|
|
20
|
+
/** Writes a UTF-8 file. */
|
|
21
|
+
writeFile: (path: string, contents: string) => void;
|
|
22
|
+
/** True when a path exists (guards `init` against clobbering a project). */
|
|
23
|
+
exists: (path: string) => boolean;
|
|
24
|
+
}
|
package/dist/io.js
ADDED
package/dist/io.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"io.js","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":""}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AccountToolSpec, UcpResponse } from '@artos-commerce/ucp-client/ucp';
|
|
2
|
+
import { type CheckoutOutcome } from '@artos-commerce/ucp-client/checkout';
|
|
3
|
+
/** Formats integer minor units as a human-readable major-unit amount. */
|
|
4
|
+
export declare function formatMinor(minor: number | undefined, currency: string | undefined): string;
|
|
5
|
+
/** A flattened product row pulled from a UCP search response. */
|
|
6
|
+
export interface ProductView {
|
|
7
|
+
title: string;
|
|
8
|
+
storeSlug?: string;
|
|
9
|
+
variantId?: string;
|
|
10
|
+
price?: number;
|
|
11
|
+
currency?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Pulls product rows out of a UCP search envelope (REST or MCP-wrapped). */
|
|
14
|
+
export declare function extractProducts(res: UcpResponse): ProductView[];
|
|
15
|
+
/** Renders catalog search results as text, or raw JSON when `json` is set. */
|
|
16
|
+
export declare function formatSearchResults(res: UcpResponse, opts?: {
|
|
17
|
+
json?: boolean;
|
|
18
|
+
}): string;
|
|
19
|
+
/** Renders a store's UCP profile as text, or raw JSON when `json` is set. */
|
|
20
|
+
export declare function formatStoreProfile(slug: string, raw: Record<string, unknown>, opts?: {
|
|
21
|
+
json?: boolean;
|
|
22
|
+
}): string;
|
|
23
|
+
/** Renders a cart/checkout/order UCP body as text, or raw JSON when `json` is set. */
|
|
24
|
+
export declare function formatEntity(label: string, body: UcpResponse, opts?: {
|
|
25
|
+
json?: boolean;
|
|
26
|
+
}): string;
|
|
27
|
+
/**
|
|
28
|
+
* Renders a `confirmPurchase` outcome, including the call-to-action a buyer needs
|
|
29
|
+
* for the non-terminal states (the hosted-pay / escalation URL, or the list of
|
|
30
|
+
* rails to re-run with `--pay`).
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatOutcome(outcome: CheckoutOutcome, opts?: {
|
|
33
|
+
json?: boolean;
|
|
34
|
+
}): string;
|
|
35
|
+
/** Renders the buyer-account tool list, or raw JSON when `json` is set. */
|
|
36
|
+
export declare function formatAccountTools(tools: AccountToolSpec[], opts?: {
|
|
37
|
+
json?: boolean;
|
|
38
|
+
}): string;
|