makea-cli 0.2.17__tar.gz → 0.2.19__tar.gz
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.
- {makea_cli-0.2.17 → makea_cli-0.2.19}/CHANGELOG.md +21 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/PKG-INFO +4 -2
- {makea_cli-0.2.17 → makea_cli-0.2.19}/README.md +3 -1
- makea_cli-0.2.19/makea_cli/__init__.py +1 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/api_client.py +25 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/playbook/cmd.py +91 -1
- {makea_cli-0.2.17 → makea_cli-0.2.19}/pyproject.toml +1 -1
- {makea_cli-0.2.17 → makea_cli-0.2.19}/tests/golden_manifest.json +136 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/tests/test_persona_commands.py +29 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/uv.lock +1 -1
- makea_cli-0.2.17/makea_cli/__init__.py +0 -1
- {makea_cli-0.2.17 → makea_cli-0.2.19}/.claude/skills/create-supplier-profile/SKILL.md +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/.claude/skills/lark-cli-setup/SKILL.md +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/.claude/skills/link-supplier-user/SKILL.md +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/.claude/skills/makea-cli-setup/SKILL.md +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/.claude/skills/payment-revenue-report/SKILL.md +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/.claude/skills/supplier-user-id-migration/SKILL.md +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/.gitignore +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea-collection-upload/SKILL.md +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea-collection-upload/scripts/create_products.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/__main__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/auth_pkce.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/broker.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/_util.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/analytics/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/analytics/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/auth/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/auth/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/brand/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/brand/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/designer/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/designer/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/directory/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/directory/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/document/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/document/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/email/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/email/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/factory/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/factory/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/library/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/library/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/metrics/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/metrics/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/orders/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/orders/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/playbook/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/product/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/product/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/production/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/production/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/production/pricing_spec.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/shipping/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/shipping/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/supplier/__init__.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/commands/supplier/cmd.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/config.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/errors.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/identity.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/main.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/output.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/posthog_client.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/makea_cli/registry.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/npm/makea-cli/README.md +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/npm/makea-cli/makea-cli.mjs +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/npm/makea-cli/package.json +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/tests/test_broker.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/tests/test_currency_conversion.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/tests/test_output_contract.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/tests/test_pm_reads.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/tests/test_registry.py +0 -0
- {makea_cli-0.2.17 → makea_cli-0.2.19}/tests/test_supplier_scorecard.py +0 -0
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.19
|
|
4
|
+
|
|
5
|
+
- `admin create rule` and `admin update rule` take `--valid-until YYYY-MM-DD`:
|
|
6
|
+
the day the rule ends (a closure, a temporary arrangement). From the day
|
|
7
|
+
after, it is in no prompt and does nothing; `playbook-preview` lists it as
|
|
8
|
+
"Ended". `--valid-until none` on update removes the end date. Needs the
|
|
9
|
+
backend from 3c1dc4e4.
|
|
10
|
+
|
|
11
|
+
## 0.2.18
|
|
12
|
+
|
|
13
|
+
New: see why a playbook rule did not reach Beeboo, and what a rule said
|
|
14
|
+
before. Both need the backend's playbook trace and revisions (ca0469d1).
|
|
15
|
+
|
|
16
|
+
- `admin get playbook-preview -u <user> [--product <id>] [--surface …]`: the
|
|
17
|
+
block one AI surface would get, and in `excluded[]` every rule read that
|
|
18
|
+
stays out with its reason (waiting for the brand, paused, only for other
|
|
19
|
+
product types, narrowed to another factory, over budget…). `--rule <id>`
|
|
20
|
+
answers for one rule only; `--supplier` previews a factory's playbook.
|
|
21
|
+
- `admin get rule-history <rule_id>`: every revision of one rule, with who
|
|
22
|
+
changed it and why, and `superseded_chain` to the rule that replaced it.
|
|
23
|
+
|
|
3
24
|
## 0.2.17
|
|
4
25
|
|
|
5
26
|
New: an admin can make and run shipping orders from the CLI. `create
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: makea-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.19
|
|
4
4
|
Summary: Makea admin CLI (browser login + Makea admin HTTP API)
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Requires-Dist: click<9,>=8.1
|
|
@@ -112,10 +112,12 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
|
|
|
112
112
|
| `makea-cli admin get currency-conversion` | read | `GET /admin/fx/rates` | the platform's own exchange rates and rounding (rate table for several --from; one --from with --amount converts it). | `convert-currency` |
|
|
113
113
|
| `makea-cli admin get feature-usage` | read | `POST /admin/analytics/query` | How many distinct users used a feature recently, plus event volume. Matches $pageview path and feature_time_spent eve… | `analytics-feature-usage` |
|
|
114
114
|
| `makea-cli admin get library-schema` | read | `GET /admin/library_components/schema` | the tech-pack library taxonomy: sections and their library-role field keys (run this before create/update). | `library-schema` |
|
|
115
|
+
| `makea-cli admin get playbook-preview` | read | `GET /admin/playbook/preview` | the playbook block one AI surface would get for a person or factory, and every rule left out with its reason; --product previews a conversation about one product, --rule answers for one rule. | — |
|
|
115
116
|
| `makea-cli admin get production-pricing` | read | `GET /admin/production_orders/{id}/details` | show a production order's price tiers, MOQ, sizes/colours, pricing groups and cart coverage. | `production-pricing-show` |
|
|
116
117
|
| `makea-cli admin get quote-request` | read | `GET /admin/quote_requests/{quote_request_id}` | one quote request in full. | — |
|
|
117
118
|
| `makea-cli admin get revenue-metrics` | read | `GET /admin/business-metrics/cumulative-payment-and-platform-revenue` | platform-wide payment received and platform revenue (service fee + transaction fee) bucketed over a date range. | `get-cumulative-payment-and-platform-revenue` |
|
|
118
119
|
| `makea-cli admin get rule` | read | `GET /admin/playbook/users/{user}/rules/{rule_id}` | one rule in full, with its evidence: where it came from, who changed it and why. | — |
|
|
120
|
+
| `makea-cli admin get rule-history` | read | `GET /admin/playbook/rules/{rule_id}/history` | every revision of one rule: its words, who changed it and why, and the rule that replaced it. | — |
|
|
119
121
|
| `makea-cli admin get shipping-order` | read | `GET /admin/shipping_orders/{shipping_order_id}/details` | one shipment with its production and sampling orders, freight quotes, fees, tracking and address. | — |
|
|
120
122
|
| `makea-cli admin get supplier-profile-schema` | read | `GET /admin/supplier/profile/schema` | supplier profile v2 schema (section/field taxonomy: sections, fields, options, required rules). | `get-supplier-profile-schema` |
|
|
121
123
|
| `makea-cli admin get tech-spec-extraction` | read | `GET /admin/products/{id}/extract-tech-specifications` | AI-generate specs (not saved). | `extract-ai-tech-spec` |
|
|
@@ -141,7 +143,7 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
|
|
|
141
143
|
| `makea-cli admin update library-element` | write(auto) | `PATCH /admin/designer/{user_id}/library_components/{component_id}` | update a component's name and/or values (empty value clears a field). | `library-update` |
|
|
142
144
|
| `makea-cli admin update quote` | write(ask) | `POST /admin/product/edit_supplier_link_override_info` | admin updates an existing quote (supplier link) in place. Only the options you pass are sent, and the backend leaves … | `update-supplier-quote` |
|
|
143
145
|
| `makea-cli admin update quote-request` | write(ask) | `PATCH /admin/quote_requests/{quote_request_id}/update` | set a quote request's stage, status and/or due date. Only what you pass is changed. This is the door that unblocks a … | `update-quote-request` |
|
|
144
|
-
| `makea-cli admin update rule` | write(ask) | `PATCH /admin/playbook/users/{user}/rules/{rule_id}` | change a rule's text, status, applies_to, when or
|
|
146
|
+
| `makea-cli admin update rule` | write(ask) | `PATCH /admin/playbook/users/{user}/rules/{rule_id}` | change a rule's text, status, applies_to, when, mode or end date (--valid-until). --reason required; the rule keeps what it was before. | — |
|
|
145
147
|
| `makea-cli admin update shipping-order` | write(ask) | `PUT /admin/shipping_orders/{shipping_order_id}/status` | Change a shipment: --status (PUT .../status), tracking flags (POST .../tracking), --address (PUT .../shipping-address… | — |
|
|
146
148
|
| `makea-cli admin update supplier` | write(ask) | `PUT /admin/supplier/update_supplier` | update an existing supplier from a JSON file (admin). Run `makea-cli get-supplier-profile-schema` FIRST to get the fi… | `update-supplier` |
|
|
147
149
|
| `makea-cli admin update tech-spec` | write(ask) | `POST /admin/products/{id}/technical-specifications` | persist specs from a JSON file. | `save-product-tech-spec` |
|
|
@@ -100,10 +100,12 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
|
|
|
100
100
|
| `makea-cli admin get currency-conversion` | read | `GET /admin/fx/rates` | the platform's own exchange rates and rounding (rate table for several --from; one --from with --amount converts it). | `convert-currency` |
|
|
101
101
|
| `makea-cli admin get feature-usage` | read | `POST /admin/analytics/query` | How many distinct users used a feature recently, plus event volume. Matches $pageview path and feature_time_spent eve… | `analytics-feature-usage` |
|
|
102
102
|
| `makea-cli admin get library-schema` | read | `GET /admin/library_components/schema` | the tech-pack library taxonomy: sections and their library-role field keys (run this before create/update). | `library-schema` |
|
|
103
|
+
| `makea-cli admin get playbook-preview` | read | `GET /admin/playbook/preview` | the playbook block one AI surface would get for a person or factory, and every rule left out with its reason; --product previews a conversation about one product, --rule answers for one rule. | — |
|
|
103
104
|
| `makea-cli admin get production-pricing` | read | `GET /admin/production_orders/{id}/details` | show a production order's price tiers, MOQ, sizes/colours, pricing groups and cart coverage. | `production-pricing-show` |
|
|
104
105
|
| `makea-cli admin get quote-request` | read | `GET /admin/quote_requests/{quote_request_id}` | one quote request in full. | — |
|
|
105
106
|
| `makea-cli admin get revenue-metrics` | read | `GET /admin/business-metrics/cumulative-payment-and-platform-revenue` | platform-wide payment received and platform revenue (service fee + transaction fee) bucketed over a date range. | `get-cumulative-payment-and-platform-revenue` |
|
|
106
107
|
| `makea-cli admin get rule` | read | `GET /admin/playbook/users/{user}/rules/{rule_id}` | one rule in full, with its evidence: where it came from, who changed it and why. | — |
|
|
108
|
+
| `makea-cli admin get rule-history` | read | `GET /admin/playbook/rules/{rule_id}/history` | every revision of one rule: its words, who changed it and why, and the rule that replaced it. | — |
|
|
107
109
|
| `makea-cli admin get shipping-order` | read | `GET /admin/shipping_orders/{shipping_order_id}/details` | one shipment with its production and sampling orders, freight quotes, fees, tracking and address. | — |
|
|
108
110
|
| `makea-cli admin get supplier-profile-schema` | read | `GET /admin/supplier/profile/schema` | supplier profile v2 schema (section/field taxonomy: sections, fields, options, required rules). | `get-supplier-profile-schema` |
|
|
109
111
|
| `makea-cli admin get tech-spec-extraction` | read | `GET /admin/products/{id}/extract-tech-specifications` | AI-generate specs (not saved). | `extract-ai-tech-spec` |
|
|
@@ -129,7 +131,7 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
|
|
|
129
131
|
| `makea-cli admin update library-element` | write(auto) | `PATCH /admin/designer/{user_id}/library_components/{component_id}` | update a component's name and/or values (empty value clears a field). | `library-update` |
|
|
130
132
|
| `makea-cli admin update quote` | write(ask) | `POST /admin/product/edit_supplier_link_override_info` | admin updates an existing quote (supplier link) in place. Only the options you pass are sent, and the backend leaves … | `update-supplier-quote` |
|
|
131
133
|
| `makea-cli admin update quote-request` | write(ask) | `PATCH /admin/quote_requests/{quote_request_id}/update` | set a quote request's stage, status and/or due date. Only what you pass is changed. This is the door that unblocks a … | `update-quote-request` |
|
|
132
|
-
| `makea-cli admin update rule` | write(ask) | `PATCH /admin/playbook/users/{user}/rules/{rule_id}` | change a rule's text, status, applies_to, when or
|
|
134
|
+
| `makea-cli admin update rule` | write(ask) | `PATCH /admin/playbook/users/{user}/rules/{rule_id}` | change a rule's text, status, applies_to, when, mode or end date (--valid-until). --reason required; the rule keeps what it was before. | — |
|
|
133
135
|
| `makea-cli admin update shipping-order` | write(ask) | `PUT /admin/shipping_orders/{shipping_order_id}/status` | Change a shipment: --status (PUT .../status), tracking flags (POST .../tracking), --address (PUT .../shipping-address… | — |
|
|
134
136
|
| `makea-cli admin update supplier` | write(ask) | `PUT /admin/supplier/update_supplier` | update an existing supplier from a JSON file (admin). Run `makea-cli get-supplier-profile-schema` FIRST to get the fi… | `update-supplier` |
|
|
135
137
|
| `makea-cli admin update tech-spec` | write(ask) | `POST /admin/products/{id}/technical-specifications` | persist specs from a JSON file. | `save-product-tech-spec` |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.19"
|
|
@@ -1181,6 +1181,31 @@ def admin_delete_user_rule(user: str, rule_id: str, reason: str) -> Any:
|
|
|
1181
1181
|
return delete_json(_user_rules_path(user, rule_id), body={"reason": reason})
|
|
1182
1182
|
|
|
1183
1183
|
|
|
1184
|
+
def admin_get_rule_history(rule_id: str) -> Any:
|
|
1185
|
+
"""GET /admin/playbook/rules/{rule_id}/history — every revision of one rule
|
|
1186
|
+
(words, who, why), what replaced it and what it replaced."""
|
|
1187
|
+
return get_json(f"/admin/playbook/rules/{quote(rule_id, safe='')}/history")
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
def admin_playbook_preview(
|
|
1191
|
+
surface: str,
|
|
1192
|
+
*,
|
|
1193
|
+
user_id: str | None = None,
|
|
1194
|
+
supplier_id: str | None = None,
|
|
1195
|
+
product_id: str | None = None,
|
|
1196
|
+
) -> Any:
|
|
1197
|
+
"""GET /admin/playbook/preview — the block a surface would inject, plus every
|
|
1198
|
+
rule left out and why (``excluded``)."""
|
|
1199
|
+
params: dict[str, Any] = {"surface": surface}
|
|
1200
|
+
if user_id:
|
|
1201
|
+
params["user_id"] = user_id
|
|
1202
|
+
if supplier_id:
|
|
1203
|
+
params["supplier_id"] = supplier_id
|
|
1204
|
+
if product_id:
|
|
1205
|
+
params["product_id"] = product_id
|
|
1206
|
+
return get_json("/admin/playbook/preview", params=params)
|
|
1207
|
+
|
|
1208
|
+
|
|
1184
1209
|
# --- supplier persona: a factory acting on its own RFQs, quotes and orders --------
|
|
1185
1210
|
|
|
1186
1211
|
|
|
@@ -17,6 +17,7 @@ the row stays as the record, and ``update --status active`` brings it back.
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import json
|
|
20
|
+
from datetime import date
|
|
20
21
|
from typing import Any
|
|
21
22
|
|
|
22
23
|
import typer
|
|
@@ -107,6 +108,13 @@ def _when(raw: str) -> dict[str, Any]:
|
|
|
107
108
|
return data
|
|
108
109
|
|
|
109
110
|
|
|
111
|
+
def _date(raw: str) -> str:
|
|
112
|
+
try:
|
|
113
|
+
return date.fromisoformat(raw.strip()).isoformat()
|
|
114
|
+
except ValueError as e:
|
|
115
|
+
raise typer.BadParameter("--valid-until: expected YYYY-MM-DD") from e
|
|
116
|
+
|
|
117
|
+
|
|
110
118
|
def _choice(value: str | None, allowed: tuple[str, ...], flag: str) -> str | None:
|
|
111
119
|
if value is None:
|
|
112
120
|
return None
|
|
@@ -172,6 +180,71 @@ def register(app: typer.Typer) -> None:
|
|
|
172
180
|
"""Show one playbook rule with its evidence."""
|
|
173
181
|
print_json_or_exit(console, lambda: api_client.admin_get_user_rule(user, rule_id))
|
|
174
182
|
|
|
183
|
+
@command(
|
|
184
|
+
app,
|
|
185
|
+
"admin",
|
|
186
|
+
"get",
|
|
187
|
+
"rule-history",
|
|
188
|
+
api="GET /admin/playbook/rules/{rule_id}/history",
|
|
189
|
+
help=(
|
|
190
|
+
"GET /admin/playbook/rules/{rule_id}/history — every revision of one rule: "
|
|
191
|
+
"its words, who changed it and why; superseded_chain leads to the rule "
|
|
192
|
+
"that holds now when this one was replaced."
|
|
193
|
+
),
|
|
194
|
+
)
|
|
195
|
+
def get_rule_history(
|
|
196
|
+
rule_id: str = typer.Argument(..., help="Rule id (rul_…)."),
|
|
197
|
+
) -> None:
|
|
198
|
+
"""Show what a playbook rule said at each point, and what replaced it."""
|
|
199
|
+
print_json_or_exit(console, lambda: api_client.admin_get_rule_history(rule_id))
|
|
200
|
+
|
|
201
|
+
@command(
|
|
202
|
+
app,
|
|
203
|
+
"admin",
|
|
204
|
+
"get",
|
|
205
|
+
"playbook-preview",
|
|
206
|
+
api="GET /admin/playbook/preview",
|
|
207
|
+
help=(
|
|
208
|
+
"GET /admin/playbook/preview — the playbook block one AI surface would get "
|
|
209
|
+
"for a person (or a factory), and in excluded[] every rule read that stays "
|
|
210
|
+
"out with its reason (waiting for confirmation, paused, only for knitwear, "
|
|
211
|
+
"over budget…). --product previews a conversation about one product."
|
|
212
|
+
),
|
|
213
|
+
)
|
|
214
|
+
def playbook_preview(
|
|
215
|
+
user: str | None = typer.Option(None, "--user", "-u", help="Brand user_id."),
|
|
216
|
+
supplier: str | None = typer.Option(None, "--supplier", help="Supplier id."),
|
|
217
|
+
surface: str = typer.Option(
|
|
218
|
+
"chat_default", "--surface", help="AI surface, e.g. chat_default."
|
|
219
|
+
),
|
|
220
|
+
product: str | None = typer.Option(None, "--product", "-p", help="Product id."),
|
|
221
|
+
rule: str | None = typer.Option(
|
|
222
|
+
None, "--rule", help="Only say whether this rule is in, and if not why."
|
|
223
|
+
),
|
|
224
|
+
) -> None:
|
|
225
|
+
"""Preview a playbook block and why the other rules stay out."""
|
|
226
|
+
if not user and not supplier:
|
|
227
|
+
raise typer.BadParameter("pass --user or --supplier")
|
|
228
|
+
|
|
229
|
+
def fetch() -> Any:
|
|
230
|
+
out = api_client.admin_playbook_preview(
|
|
231
|
+
surface, user_id=user, supplier_id=supplier, product_id=product
|
|
232
|
+
)
|
|
233
|
+
if not rule:
|
|
234
|
+
return out
|
|
235
|
+
if rule in (out.get("rule_ids") or []):
|
|
236
|
+
return {"rule_id": rule, "in_prompt": True}
|
|
237
|
+
for ex in out.get("excluded") or []:
|
|
238
|
+
if ex.get("rule_id") == rule:
|
|
239
|
+
return {"rule_id": rule, "in_prompt": False, **ex}
|
|
240
|
+
return {
|
|
241
|
+
"rule_id": rule,
|
|
242
|
+
"in_prompt": False,
|
|
243
|
+
"reason": "not read: archived, or not on a scope this surface reads",
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
print_json_or_exit(console, fetch)
|
|
247
|
+
|
|
175
248
|
@command(
|
|
176
249
|
app,
|
|
177
250
|
"admin",
|
|
@@ -225,6 +298,11 @@ def register(app: typer.Typer) -> None:
|
|
|
225
298
|
force: bool = typer.Option(
|
|
226
299
|
False, "--force", help="Add even if it repeats or disagrees with an existing rule."
|
|
227
300
|
),
|
|
301
|
+
valid_until: str | None = typer.Option(
|
|
302
|
+
None,
|
|
303
|
+
"--valid-until",
|
|
304
|
+
help="YYYY-MM-DD the rule ends on (a closure, a temporary arrangement).",
|
|
305
|
+
),
|
|
228
306
|
) -> None:
|
|
229
307
|
"""Add a playbook rule for a person."""
|
|
230
308
|
body: dict[str, Any] = {"text": text, "reason": _reason(reason)}
|
|
@@ -246,6 +324,8 @@ def register(app: typer.Typer) -> None:
|
|
|
246
324
|
body["status"] = _choice(status, ("pending", "active", "muted"), "--status")
|
|
247
325
|
if force:
|
|
248
326
|
body["force"] = True
|
|
327
|
+
if valid_until is not None:
|
|
328
|
+
body["valid_until"] = _date(valid_until)
|
|
249
329
|
print_json_or_exit(console, lambda: api_client.admin_create_user_rule(user, body))
|
|
250
330
|
|
|
251
331
|
@command(
|
|
@@ -280,6 +360,11 @@ def register(app: typer.Typer) -> None:
|
|
|
280
360
|
None, "--when", help="Which products, JSON ({} for every product)."
|
|
281
361
|
),
|
|
282
362
|
mode: str | None = typer.Option(None, "--mode", help="remind or act."),
|
|
363
|
+
valid_until: str | None = typer.Option(
|
|
364
|
+
None,
|
|
365
|
+
"--valid-until",
|
|
366
|
+
help='YYYY-MM-DD the rule ends on; "none" removes the end date.',
|
|
367
|
+
),
|
|
283
368
|
) -> None:
|
|
284
369
|
"""Edit a person's playbook rule."""
|
|
285
370
|
body: dict[str, Any] = {}
|
|
@@ -293,9 +378,14 @@ def register(app: typer.Typer) -> None:
|
|
|
293
378
|
body["when"] = _when(when)
|
|
294
379
|
if mode is not None:
|
|
295
380
|
body["mode"] = _choice(mode, _MODES, "--mode")
|
|
381
|
+
if valid_until is not None:
|
|
382
|
+
body["valid_until"] = (
|
|
383
|
+
"" if valid_until.strip().lower() == "none" else _date(valid_until)
|
|
384
|
+
)
|
|
296
385
|
if not body:
|
|
297
386
|
raise typer.BadParameter(
|
|
298
|
-
"nothing to change: pass --text, --status, --applies-to, --when
|
|
387
|
+
"nothing to change: pass --text, --status, --applies-to, --when, --mode "
|
|
388
|
+
"or --valid-until"
|
|
299
389
|
)
|
|
300
390
|
body["reason"] = _reason(reason)
|
|
301
391
|
print_json_or_exit(console, lambda: api_client.admin_update_user_rule(user, rule_id, body))
|
|
@@ -486,6 +486,18 @@
|
|
|
486
486
|
"multiple": false,
|
|
487
487
|
"default": false,
|
|
488
488
|
"help": "Add even if it repeats or disagrees with an existing rule."
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
"name": "valid_until",
|
|
492
|
+
"kind": "option",
|
|
493
|
+
"opts": [
|
|
494
|
+
"--valid-until"
|
|
495
|
+
],
|
|
496
|
+
"type": "text",
|
|
497
|
+
"required": false,
|
|
498
|
+
"multiple": false,
|
|
499
|
+
"default": null,
|
|
500
|
+
"help": "YYYY-MM-DD the rule ends on (a closure, a temporary arrangement)."
|
|
489
501
|
}
|
|
490
502
|
]
|
|
491
503
|
},
|
|
@@ -1858,6 +1870,87 @@
|
|
|
1858
1870
|
}
|
|
1859
1871
|
]
|
|
1860
1872
|
},
|
|
1873
|
+
{
|
|
1874
|
+
"name": "admin get playbook-preview",
|
|
1875
|
+
"persona": "admin",
|
|
1876
|
+
"verb": "get",
|
|
1877
|
+
"noun": "playbook-preview",
|
|
1878
|
+
"access": "read",
|
|
1879
|
+
"api": "GET /admin/playbook/preview",
|
|
1880
|
+
"external": null,
|
|
1881
|
+
"side_effects": [],
|
|
1882
|
+
"approval": "auto",
|
|
1883
|
+
"reversible": null,
|
|
1884
|
+
"idempotent": null,
|
|
1885
|
+
"limit": null,
|
|
1886
|
+
"legacy": [],
|
|
1887
|
+
"help": "GET /admin/playbook/preview — the playbook block one AI surface would get for a person (or a factory), and in excluded[] every rule read that stays out with its reason (waiting for confirmation, paused, only for knitwear, over budget…). --product previews a conversation about one product.",
|
|
1888
|
+
"function": "makea_cli.commands.playbook.cmd.register.<locals>.playbook_preview",
|
|
1889
|
+
"flags": [
|
|
1890
|
+
{
|
|
1891
|
+
"name": "user",
|
|
1892
|
+
"kind": "option",
|
|
1893
|
+
"opts": [
|
|
1894
|
+
"--user",
|
|
1895
|
+
"-u"
|
|
1896
|
+
],
|
|
1897
|
+
"type": "text",
|
|
1898
|
+
"required": false,
|
|
1899
|
+
"multiple": false,
|
|
1900
|
+
"default": null,
|
|
1901
|
+
"help": "Brand user_id."
|
|
1902
|
+
},
|
|
1903
|
+
{
|
|
1904
|
+
"name": "supplier",
|
|
1905
|
+
"kind": "option",
|
|
1906
|
+
"opts": [
|
|
1907
|
+
"--supplier"
|
|
1908
|
+
],
|
|
1909
|
+
"type": "text",
|
|
1910
|
+
"required": false,
|
|
1911
|
+
"multiple": false,
|
|
1912
|
+
"default": null,
|
|
1913
|
+
"help": "Supplier id."
|
|
1914
|
+
},
|
|
1915
|
+
{
|
|
1916
|
+
"name": "surface",
|
|
1917
|
+
"kind": "option",
|
|
1918
|
+
"opts": [
|
|
1919
|
+
"--surface"
|
|
1920
|
+
],
|
|
1921
|
+
"type": "text",
|
|
1922
|
+
"required": false,
|
|
1923
|
+
"multiple": false,
|
|
1924
|
+
"default": "chat_default",
|
|
1925
|
+
"help": "AI surface, e.g. chat_default."
|
|
1926
|
+
},
|
|
1927
|
+
{
|
|
1928
|
+
"name": "product",
|
|
1929
|
+
"kind": "option",
|
|
1930
|
+
"opts": [
|
|
1931
|
+
"--product",
|
|
1932
|
+
"-p"
|
|
1933
|
+
],
|
|
1934
|
+
"type": "text",
|
|
1935
|
+
"required": false,
|
|
1936
|
+
"multiple": false,
|
|
1937
|
+
"default": null,
|
|
1938
|
+
"help": "Product id."
|
|
1939
|
+
},
|
|
1940
|
+
{
|
|
1941
|
+
"name": "rule",
|
|
1942
|
+
"kind": "option",
|
|
1943
|
+
"opts": [
|
|
1944
|
+
"--rule"
|
|
1945
|
+
],
|
|
1946
|
+
"type": "text",
|
|
1947
|
+
"required": false,
|
|
1948
|
+
"multiple": false,
|
|
1949
|
+
"default": null,
|
|
1950
|
+
"help": "Only say whether this rule is in, and if not why."
|
|
1951
|
+
}
|
|
1952
|
+
]
|
|
1953
|
+
},
|
|
1861
1954
|
{
|
|
1862
1955
|
"name": "admin get production-pricing",
|
|
1863
1956
|
"persona": "admin",
|
|
@@ -2062,6 +2155,37 @@
|
|
|
2062
2155
|
}
|
|
2063
2156
|
]
|
|
2064
2157
|
},
|
|
2158
|
+
{
|
|
2159
|
+
"name": "admin get rule-history",
|
|
2160
|
+
"persona": "admin",
|
|
2161
|
+
"verb": "get",
|
|
2162
|
+
"noun": "rule-history",
|
|
2163
|
+
"access": "read",
|
|
2164
|
+
"api": "GET /admin/playbook/rules/{rule_id}/history",
|
|
2165
|
+
"external": null,
|
|
2166
|
+
"side_effects": [],
|
|
2167
|
+
"approval": "auto",
|
|
2168
|
+
"reversible": null,
|
|
2169
|
+
"idempotent": null,
|
|
2170
|
+
"limit": null,
|
|
2171
|
+
"legacy": [],
|
|
2172
|
+
"help": "GET /admin/playbook/rules/{rule_id}/history — every revision of one rule: its words, who changed it and why; superseded_chain leads to the rule that holds now when this one was replaced.",
|
|
2173
|
+
"function": "makea_cli.commands.playbook.cmd.register.<locals>.get_rule_history",
|
|
2174
|
+
"flags": [
|
|
2175
|
+
{
|
|
2176
|
+
"name": "rule_id",
|
|
2177
|
+
"kind": "argument",
|
|
2178
|
+
"opts": [
|
|
2179
|
+
"rule_id"
|
|
2180
|
+
],
|
|
2181
|
+
"type": "text",
|
|
2182
|
+
"required": true,
|
|
2183
|
+
"multiple": false,
|
|
2184
|
+
"default": null,
|
|
2185
|
+
"help": "Rule id (rul_…)."
|
|
2186
|
+
}
|
|
2187
|
+
]
|
|
2188
|
+
},
|
|
2065
2189
|
{
|
|
2066
2190
|
"name": "admin get shipping-order",
|
|
2067
2191
|
"persona": "admin",
|
|
@@ -4448,6 +4572,18 @@
|
|
|
4448
4572
|
"multiple": false,
|
|
4449
4573
|
"default": null,
|
|
4450
4574
|
"help": "remind or act."
|
|
4575
|
+
},
|
|
4576
|
+
{
|
|
4577
|
+
"name": "valid_until",
|
|
4578
|
+
"kind": "option",
|
|
4579
|
+
"opts": [
|
|
4580
|
+
"--valid-until"
|
|
4581
|
+
],
|
|
4582
|
+
"type": "text",
|
|
4583
|
+
"required": false,
|
|
4584
|
+
"multiple": false,
|
|
4585
|
+
"default": null,
|
|
4586
|
+
"help": "YYYY-MM-DD the rule ends on; \"none\" removes the end date."
|
|
4451
4587
|
}
|
|
4452
4588
|
]
|
|
4453
4589
|
},
|
|
@@ -429,6 +429,35 @@ class PlaybookRuleCommandTests(_PersonaCase):
|
|
|
429
429
|
("GET", "/admin/playbook/users/u1/rules/rul_1"),
|
|
430
430
|
)
|
|
431
431
|
|
|
432
|
+
def test_history_reads_one_rule_by_id(self):
|
|
433
|
+
self.run_cli("admin", "get", "rule-history", "rul_1")
|
|
434
|
+
self.assertEqual(
|
|
435
|
+
(self.rec.last["method"], self.rec.last["path"]),
|
|
436
|
+
("GET", "/admin/playbook/rules/rul_1/history"),
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
def test_preview_passes_the_conversation(self):
|
|
440
|
+
self.run_cli(
|
|
441
|
+
"admin", "get", "playbook-preview", "-u", "u1", "--product", "p1",
|
|
442
|
+
"--surface", "chat_tech_pack_builder",
|
|
443
|
+
) # fmt: skip
|
|
444
|
+
self.assertEqual(self.rec.last["path"], "/admin/playbook/preview")
|
|
445
|
+
self.assertEqual(
|
|
446
|
+
self.rec.last["params"],
|
|
447
|
+
{"surface": "chat_tech_pack_builder", "user_id": "u1", "product_id": "p1"},
|
|
448
|
+
)
|
|
449
|
+
self.run_cli("admin", "get", "playbook-preview", expect=2)
|
|
450
|
+
|
|
451
|
+
def test_preview_answers_for_one_rule(self):
|
|
452
|
+
self.rec.payload = {
|
|
453
|
+
"success": True,
|
|
454
|
+
"rule_ids": ["rul_in"],
|
|
455
|
+
"excluded": [{"rule_id": "rul_out", "reason": "pending", "label": "Waiting"}],
|
|
456
|
+
}
|
|
457
|
+
out = self.run_cli("admin", "get", "playbook-preview", "-u", "u1", "--rule", "rul_out")
|
|
458
|
+
self.assertIn('"in_prompt": false', out.output)
|
|
459
|
+
self.assertIn('"reason": "pending"', out.output)
|
|
460
|
+
|
|
432
461
|
def test_create_builds_the_body(self):
|
|
433
462
|
self.run_cli(
|
|
434
463
|
"admin", "create", "rule", "--user", "u1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.17"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|