@commercelayer/agent-cli 1.0.0-dev.15 → 1.0.0-dev.17
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 +2 -1
- package/dist/builtins/extensions.js +4 -3
- package/dist/engine.js +29 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -76,9 +76,10 @@ Destructive verbs (deletes, `orders cancel`, `payments void` and `refund`, `sand
|
|
|
76
76
|
|
|
77
77
|
- Without a login, nothing is checked on this machine: the request goes without a token, and the API's answer (`login_required`, or `state_required` for an organization not claimed) comes through as it is. So do `live_unavailable` (a plan without live), `forbidden` (the login is not an active admin of it) and `not_supported` for a verb that comes with a later step of go-live.
|
|
78
78
|
- A verb that never runs live (sandbox, plans, sales calls, `auth login`, `auth switch`, `shop`) stops on this machine with `state_required`.
|
|
79
|
+
- `c11r events writes --live --org <slug>` (`--since 2026-11-12T00:00:00Z`, an ISO time, `--noun`, `--cursor`, `--limit`) is the audit of live writes, and runs only in live: without `--live` it is `missing_value` with the full command, before any call.
|
|
79
80
|
- `c11r status --live --org <slug>` is the organization's live status, with `live_credential` and the warning `live_credential_held` while the API holds one.
|
|
80
81
|
- `c11r auth logout --live --org <slug>` revokes that credential in Commerce Layer (`DELETE /v1/auth/live`): `{ org, revoked, credential }`. The login stays on this machine. `--dry-run` says what it would revoke.
|
|
81
|
-
- A
|
|
82
|
+
- A verb that needs a yes is confirmed by the API in live, with a sentence naming the action, the amount and the mode (`Refunds EUR 1.00 on order N, in LIVE mode, real money.`): the CLI sends it without `confirm=true` and shows that `confirmation_required` as it is, with the API's next command, or asks it with those words in a terminal. `--yes` sends `confirm=true` on every live write, `payments capture` included.
|
|
82
83
|
- A verb that answers a secret (`credentials create`) writes it in live only to the file the human chose with `--out`: without it, `missing_value` with the command and `--out FILE`. Never to c11r's secrets folder, never printed. A live delete leaves the test mode's secret files of the same organization alone.
|
|
83
84
|
- `store.yml`, `.c11r/export.json` and the drift notes are of an organization in a mode: a live write marks a live `store.yml` behind, never a test one, and the other way round.
|
|
84
85
|
- `c11r organizations disconnect <slug>` (confirmed) has the API revoke its credentials and the organization tokens; this machine then forgets the token, its secret files and a `.c11r.json` naming it, as `sandbox destroy` does, and answers `forgotten`.
|
|
@@ -32,9 +32,10 @@ export const organizations = {
|
|
|
32
32
|
const req = resourceRequest('organizations', run.verb, run.parsed.id, run.parsed.values);
|
|
33
33
|
// Ending every other token of the organization is confirmed: by the schema's confirm_if, or
|
|
34
34
|
// here for a schema without it.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
// With confirm_if the engine has it confirmed, by the human here or by the API's 428 with its
|
|
36
|
+
// sentence; only a schema without it is confirmed here, and then sends confirm=true itself.
|
|
37
|
+
if (run.verb.name === 'connect' && run.parsed.values.revoke_others && !run.globals.dryRun && !run.verb.confirmIf.includes('revoke_others')) {
|
|
38
|
+
await confirm(`Connect ${run.parsed.id} and end every other organization token of it`, run.line, { yes: run.globals.yes, prompter: run.prompter ?? terminal });
|
|
38
39
|
req.confirm = true;
|
|
39
40
|
req.body = { ...req.body, confirm: true };
|
|
40
41
|
}
|
package/dist/engine.js
CHANGED
|
@@ -42,6 +42,8 @@ function refusedBeforeEffect(e) {
|
|
|
42
42
|
return status >= 400 && status < 500;
|
|
43
43
|
return e.code === 'unknown_field' || e.code === 'unknown_verb';
|
|
44
44
|
}
|
|
45
|
+
/** Verbs that only run in live mode. */
|
|
46
|
+
const LIVE_ONLY = new Set(['events writes']);
|
|
45
47
|
async function executeOnce(argv, opts) {
|
|
46
48
|
const cmd = parseCommand(argv);
|
|
47
49
|
const builtins = opts.builtins ?? {};
|
|
@@ -87,6 +89,12 @@ async function executeOnce(argv, opts) {
|
|
|
87
89
|
if (live && !verb.live) {
|
|
88
90
|
fail('state_required', `${named} does not run in live mode.`, { required_state: 'claimed', path: 'live', next_step: fixWith(line.replace(/\s--live\b/, '')) });
|
|
89
91
|
}
|
|
92
|
+
// A verb that only reads live data (events writes, the audit of live writes): without --live the
|
|
93
|
+
// API answers the login a bare 401, so the command says what it needs first.
|
|
94
|
+
if (!live && LIVE_ONLY.has(`${schema.noun} ${verb.name}`)) {
|
|
95
|
+
const org = cmd.globals.org ? '' : ' --org ORG_SLUG';
|
|
96
|
+
fail('missing_value', `${named} reads live data only: it needs --live and the organization, named with --org.`, { path: 'live', next_step: fixWith(`${line}${org} --live`) });
|
|
97
|
+
}
|
|
90
98
|
// Live mode acts on an organization named on the command, never the folder's link or the
|
|
91
99
|
// default, which are a sandbox's: --org, or C11R_ORG.
|
|
92
100
|
const liveOrg = live ? (cmd.globals.org ?? (process.env.C11R_ORG || null)) : null;
|
|
@@ -118,10 +126,19 @@ async function executeOnce(argv, opts) {
|
|
|
118
126
|
const loginOrg = org.source && org.source !== 'only_stored' ? org.org : null;
|
|
119
127
|
let confirmed = false;
|
|
120
128
|
const confirmFlags = verb.confirmIf.filter((k) => parsed.values[k] !== undefined && parsed.values[k] !== false);
|
|
121
|
-
|
|
129
|
+
// In live mode the API asks for the verbs it confirms, with a sentence naming the action, the
|
|
130
|
+
// amount and the mode ("Refunds EUR 1.00 on order N, in LIVE mode, real money."): the CLI sends
|
|
131
|
+
// without confirm=true and shows that 428 as it is, or asks it in a terminal. --yes sends
|
|
132
|
+
// confirm=true on every live write, payments capture included.
|
|
133
|
+
// So does a login verb (organizations disconnect), whose sentence names what stops answering.
|
|
134
|
+
const apiAsks = (live || verb.credential === 'login') && (verb.confirm || confirmFlags.length > 0);
|
|
135
|
+
if (apiAsks && cmd.globals.yes && !cmd.globals.dryRun)
|
|
136
|
+
confirmed = true;
|
|
137
|
+
if (live && cmd.globals.yes && verb.method !== 'GET')
|
|
138
|
+
confirmed = true;
|
|
139
|
+
if ((verb.destructive || verb.confirm || confirmFlags.length) && !cmd.globals.dryRun && !apiAsks) {
|
|
122
140
|
const what = `${verb.name} ${schema.noun}${parsed.id ? ` ${parsed.id}` : ''}${confirmFlags.length ? ` with ${confirmFlags.map(toFlag).join(' ')}` : ''}`;
|
|
123
|
-
|
|
124
|
-
const sentence = `${what.charAt(0).toUpperCase() + what.slice(1)}${live ? `, in LIVE mode on ${liveOrg}` : ''}`;
|
|
141
|
+
const sentence = what.charAt(0).toUpperCase() + what.slice(1);
|
|
125
142
|
await confirm(sentence, line, { yes: cmd.globals.yes, prompter: opts.prompter });
|
|
126
143
|
confirmed = true;
|
|
127
144
|
}
|
|
@@ -149,6 +166,15 @@ async function executeOnce(argv, opts) {
|
|
|
149
166
|
return await sendOnce(req);
|
|
150
167
|
}
|
|
151
168
|
catch (e) {
|
|
169
|
+
// The API's own confirmation, in live: as it is with no terminal; asked with its words in one.
|
|
170
|
+
if (apiAsks && !confirmed && e instanceof CliError && e.code === 'confirmation_required') {
|
|
171
|
+
const p = opts.prompter ?? terminal;
|
|
172
|
+
if (!p.interactive)
|
|
173
|
+
throw e;
|
|
174
|
+
await confirm(e.body.message, line, { yes: false, prompter: p, sentence: e.body.message });
|
|
175
|
+
confirmed = true;
|
|
176
|
+
return sendOnce(req);
|
|
177
|
+
}
|
|
152
178
|
// A login token Commerce Layer no longer takes: mint a new one, once.
|
|
153
179
|
if (!(e instanceof CliError && e.code === 'login_required') || !login)
|
|
154
180
|
throw e;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commercelayer/agent-cli",
|
|
3
|
-
"version": "1.0.0-dev.
|
|
3
|
+
"version": "1.0.0-dev.17",
|
|
4
4
|
"description": "c11r: the Commerce Layer CLI for coding agents. One grammar, c11r <noun> <verb>, from a sandbox to a running organization.",
|
|
5
5
|
"homepage": "https://commercelayer.ai",
|
|
6
6
|
"keywords": [
|