@commercelayer/agent-cli 1.0.0-dev.7 → 1.0.0-dev.8

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
@@ -35,7 +35,7 @@ This is the 1.0.0 line, in development on the `clean-slate` branch. It replaces
35
35
  | `c11r auth login [--client-id] [--secret-file] [--keep-file]` | The human's own Commerce Layer login, from their Provisioning API application. See below. |
36
36
  | `c11r auth logout`, `auth switch <slug> [--global]` | Forgetting the login; the organization commands act on. |
37
37
 
38
- A loop runs a skill a Manage noun's schema names in `loop.skill` (`manage-orders`, `manage-payments`, `manage-stock`, ...); create and update refuse any other skill, and any verb that loop does not list, with the allowed values. A loop policy allows verbs: a bare verb is the skill's own noun (`approve`), `<noun>.<verb>` another Manage noun's verb on the same item (`payments.capture`). Verbs that delete or return money are never open to a policy.
38
+ A loop runs a skill a Manage or Report noun's schema names in `loop.skill`, or in `loop.skills` for a noun with several (`manage-orders`, `manage-stock`, `report-sales`, `report-pending`, ...); a report loop allows no verb and only reports. create and update refuse any other skill, and any verb that loop does not list, with the allowed values. A loop policy allows verbs: a bare verb is the skill's own noun (`approve`), `<noun>.<verb>` another Manage noun's verb on the same item (`payments.capture`). Verbs that delete or return money are never open to a policy.
39
39
 
40
40
  ## Login, organization tokens and secrets
41
41
 
@@ -4,8 +4,9 @@
4
4
  // schedules the agent repeats it every `every`.
5
5
  //
6
6
  // A policy allows verbs: a bare verb is the skill's own noun (approve), <noun>.<verb> another
7
- // Manage noun's verb on the same item (payments.capture). The skill must be one a Manage noun's
8
- // schema names in loop.skill, and each verb in that loop.verbs; the API checks again on every pass.
7
+ // Manage noun's verb on the same item (payments.capture). The skill must be one a Manage or Report
8
+ // noun's schema names in loop.skill or loop.skills, and each verb in that loop.verbs; the API checks
9
+ // again on every pass.
9
10
  import fs from 'node:fs';
10
11
  import path from 'node:path';
11
12
  import YAML from 'yaml';
@@ -17,7 +18,7 @@ import { apiNouns, apiSchema } from '../schemas.js';
17
18
  const NAME = /^[a-z0-9][a-z0-9-]{0,62}$/;
18
19
  const EVERY = /^[1-9]\d*(m|h|d)$/;
19
20
  const policyFlags = (required) => [
20
- { name: 'skill', type: 'string', required, description: 'The skill the loop runs, as in manage-orders: one a noun\'s schema names in loop.skill.' },
21
+ { name: 'skill', type: 'string', required, description: 'The skill the loop runs, as in manage-orders or report-sales: one a noun\'s schema names in loop.skill or loop.skills.' },
21
22
  { name: 'every', type: 'string', required, description: 'How often a pass should run, as in 15m, 2h or 1d. The scheduler reads it; the CLI does not wait.' },
22
23
  { name: 'allow', type: 'array', description: 'A verb the policy allows, repeated: approve, payments.capture. Only verbs the noun\'s schema lists in loop.verbs. Without it the loop only reports what is waiting.' },
23
24
  { name: 'max_total', type: 'array', description: 'The largest order total acted on, in major units: 500 for every currency, or EUR=500, repeated per currency. Above it, the item waits for the human.' },
@@ -192,16 +193,23 @@ async function checkPolicy(def) {
192
193
  }
193
194
  return [];
194
195
  }
195
- /** The skills a loop can run, from the schemas of the nouns that have a loop: skill to its noun and verbs. */
196
+ /**
197
+ * The skills a loop can run, from the schemas of the nouns that have a loop (Manage and Report):
198
+ * each skill to its noun and the verbs its policy may allow. loop.skills, when given, lists every
199
+ * skill of the noun's loop (a report loop per report); else loop.skill is the one.
200
+ */
196
201
  async function loopSkills() {
197
- const nouns = (await apiNouns()).filter((n) => n.group === 'manage' && n.served !== false);
202
+ const nouns = (await apiNouns()).filter((n) => (n.group === 'manage' || n.group === 'report') && n.served !== false);
198
203
  const schemas = await Promise.all(nouns.map((n) => apiSchema(n.noun, []).catch(() => null)));
199
204
  const out = new Map();
200
205
  for (const s of schemas) {
201
- if (!s?.loop?.skill)
206
+ if (!s?.loop)
202
207
  continue;
203
- const seen = out.get(s.loop.skill);
204
- out.set(s.loop.skill, { noun: seen?.noun ?? s.noun, verbs: [...new Set([...(seen?.verbs ?? []), ...s.loop.verbs])] });
208
+ const names = Array.isArray(s.loop.skills) && s.loop.skills.length ? s.loop.skills : s.loop.skill ? [s.loop.skill] : [];
209
+ for (const skill of names) {
210
+ const seen = out.get(skill);
211
+ out.set(skill, { noun: seen?.noun ?? s.noun, verbs: [...new Set([...(seen?.verbs ?? []), ...(s.loop.verbs ?? [])])] });
212
+ }
205
213
  }
206
214
  return out;
207
215
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercelayer/agent-cli",
3
- "version": "1.0.0-dev.7",
3
+ "version": "1.0.0-dev.8",
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": [