makea-cli 0.2.18__py3-none-any.whl → 0.2.20__py3-none-any.whl

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/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.2.18"
1
+ __version__ = "0.2.20"
makea_cli/api_client.py CHANGED
@@ -1136,49 +1136,101 @@ def admin_delete_library_component(
1136
1136
  )
1137
1137
 
1138
1138
 
1139
- # --- admin: one person's AI playbook rules ---------------------------------------
1140
- # Addressed by user_id or email; the backend resolves every scope the person's
1141
- # rules live in (team, own account, factory) and refuses an email that is on
1142
- # more than one account. Every write carries a reason the rule keeps.
1139
+ # --- admin: AI playbook rules -----------------------------------------------------
1140
+ # Addressed by whose they are: a person (user_id or email; the backend resolves
1141
+ # every scope their rules live in and refuses an email on more than one account),
1142
+ # one factory by supplier id, or the platform-wide GLOBAL playbook. Every write
1143
+ # carries a reason the rule keeps.
1143
1144
 
1144
1145
 
1145
- def _user_rules_path(user: str, rule_id: str | None = None) -> str:
1146
- path = f"/admin/playbook/users/{quote(user.strip(), safe='@')}/rules"
1147
- return f"{path}/{quote(rule_id, safe='')}" if rule_id else path
1146
+ def playbook_rules_path(
1147
+ *, user: str | None = None, supplier: str | None = None, is_global: bool = False
1148
+ ) -> str:
1149
+ """Whose rules: a person (user_id or email), one factory, or the GLOBAL playbook."""
1150
+ if is_global:
1151
+ return "/admin/playbook/global/rules"
1152
+ if supplier:
1153
+ return f"/admin/playbook/suppliers/{quote(supplier.strip(), safe='')}/rules"
1154
+ return f"/admin/playbook/users/{quote((user or '').strip(), safe='@')}/rules"
1155
+
1156
+
1157
+ def _rule_path(base: str, rule_id: str) -> str:
1158
+ return f"{base}/{quote(rule_id, safe='')}"
1148
1159
 
1149
1160
 
1150
- def admin_list_user_rules(
1151
- user: str, *, status: str | None = None, include_archived: bool = False
1161
+ def admin_list_rules(
1162
+ base: str, *, status: str | None = None, include_archived: bool = False
1152
1163
  ) -> Any:
1153
- """GET /admin/playbook/users/{user}/rules — every rule that holds for one person."""
1164
+ """GET …/rules — every rule on one target (``playbook_rules_path``)."""
1154
1165
  params: dict[str, Any] = {}
1155
1166
  if status:
1156
1167
  params["status"] = status
1157
1168
  if include_archived:
1158
1169
  params["include_archived"] = "1"
1159
- return get_json(_user_rules_path(user), params=params or None)
1170
+ return get_json(base, params=params or None)
1171
+
1172
+
1173
+ def admin_get_rule(base: str, rule_id: str) -> Any:
1174
+ """GET …/rules/{rule_id} — one rule, evidence included."""
1175
+ return get_json(_rule_path(base, rule_id))
1176
+
1177
+
1178
+ def admin_create_rule(base: str, body: dict[str, Any]) -> Any:
1179
+ """POST …/rules — {text, reason, scope?, applies_to?, when?, mode?, category?,
1180
+ polarity?, status?, force?}."""
1181
+ return post_json(base, body)
1182
+
1183
+
1184
+ def admin_update_rule(base: str, rule_id: str, body: dict[str, Any]) -> Any:
1185
+ """PATCH …/rules/{rule_id} — {text?, status?, applies_to?, when?, mode?, reason}."""
1186
+ return patch_json(_rule_path(base, rule_id), body)
1187
+
1188
+
1189
+ def admin_delete_rule(base: str, rule_id: str, reason: str) -> Any:
1190
+ """DELETE …/rules/{rule_id} — archives it, with the reason."""
1191
+ return delete_json(_rule_path(base, rule_id), body={"reason": reason})
1192
+
1193
+
1194
+ # --- admin: one account's Knowledge > About you -----------------------------------
1195
+ # A person (user_id or email; a supplier account's person is their factory's page)
1196
+ # or one factory by supplier id. Every write but refresh carries a reason.
1197
+
1198
+
1199
+ def about_path(*, user: str | None = None, supplier: str | None = None) -> str:
1200
+ if supplier:
1201
+ return f"/admin/about/suppliers/{quote(supplier.strip(), safe='')}"
1202
+ return f"/admin/about/users/{quote((user or '').strip(), safe='@')}"
1203
+
1204
+
1205
+ def admin_get_about(base: str) -> Any:
1206
+ """GET /admin/about/{target} — the page: facts, removed, unknown, paused."""
1207
+ return get_json(base)
1208
+
1209
+
1210
+ def admin_set_about_line(base: str, key: str, body: dict[str, Any]) -> Any:
1211
+ """PATCH …/{key} — {text, valid_until?, reason}: add or reword one line."""
1212
+ return patch_json(f"{base}/{quote(key, safe='')}", body)
1160
1213
 
1161
1214
 
1162
- def admin_get_user_rule(user: str, rule_id: str) -> Any:
1163
- """GET /admin/playbook/users/{user}/rules/{rule_id} — one rule, evidence included."""
1164
- return get_json(_user_rules_path(user, rule_id))
1215
+ def admin_remove_about_line(base: str, key: str, reason: str) -> Any:
1216
+ """DELETE …/{key} — remove the line; it is not guessed again."""
1217
+ return delete_json(f"{base}/{quote(key, safe='')}", body={"reason": reason})
1165
1218
 
1166
1219
 
1167
- def admin_create_user_rule(user: str, body: dict[str, Any]) -> Any:
1168
- """POST /admin/playbook/users/{user}/rules — {text, reason, scope?, applies_to?,
1169
- when?, mode?, category?, polarity?, status?, force?}."""
1170
- return post_json(_user_rules_path(user), body)
1220
+ def admin_restore_about_line(base: str, key: str, reason: str) -> Any:
1221
+ """POST …/{key}/restore — bring a removed line back."""
1222
+ return post_json(f"{base}/{quote(key, safe='')}/restore", {"reason": reason})
1171
1223
 
1172
1224
 
1173
- def admin_update_user_rule(user: str, rule_id: str, body: dict[str, Any]) -> Any:
1174
- """PATCH /admin/playbook/users/{user}/rules/{rule_id} — {text?, status?,
1175
- applies_to?, when?, mode?, reason}."""
1176
- return patch_json(_user_rules_path(user, rule_id), body)
1225
+ def admin_pause_about(base: str, paused: bool, reason: str) -> Any:
1226
+ """POST …/pause — stop (or resume) Beeboo using the page."""
1227
+ return post_json(f"{base}/pause", {"paused": paused, "reason": reason})
1177
1228
 
1178
1229
 
1179
- def admin_delete_user_rule(user: str, rule_id: str, reason: str) -> Any:
1180
- """DELETE /admin/playbook/users/{user}/rules/{rule_id} — archives it, with the reason."""
1181
- return delete_json(_user_rules_path(user, rule_id), body={"reason": reason})
1230
+ def admin_refresh_about(base: str, *, read: bool = False, force: bool = False) -> Any:
1231
+ """POST …/refresh — recount from records now; ``read`` also reads the
1232
+ conversations since last time (one model call, so a long timeout)."""
1233
+ return post_json(f"{base}/refresh", {"read": read, "force": force}, timeout=300.0)
1182
1234
 
1183
1235
 
1184
1236
  def admin_get_rule_history(rule_id: str) -> Any:
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import typer
4
4
 
5
+ from makea_cli.commands.about.cmd import register as register_about
5
6
  from makea_cli.commands.analytics.cmd import register as register_analytics
6
7
  from makea_cli.commands.auth.cmd import register as register_auth
7
8
  from makea_cli.commands.brand.cmd import register as register_brand
@@ -37,3 +38,4 @@ def register_all(app: typer.Typer) -> None:
37
38
  register_factory(app)
38
39
  register_brand(app)
39
40
  register_playbook(app)
41
+ register_about(app)
File without changes
@@ -0,0 +1,253 @@
1
+ """Admin commands for one account's Knowledge > About you.
2
+
3
+ About you is the short list of plain facts Beeboo starts every turn from
4
+ ("You sell DTC through Shopify", "Vinchy approves fit"), at most 8 lines: what
5
+ the account said, what is counted from its orders, and what is read from its
6
+ conversations. A fact can be wrong but cannot be broken; anything that can be
7
+ broken is a rule (``admin … rule``).
8
+
9
+ Two targets, exactly one of:
10
+
11
+ * ``--user``: a person (user_id or email). A supplier account's person is
12
+ their factory's page; anyone else is their brand's (the team's when there
13
+ is one).
14
+ * ``--supplier``: one factory, by supplier id.
15
+
16
+ A line an admin writes counts as the account's own words: the nightly counting
17
+ and reading leave it alone. A removed line is not guessed again until it is
18
+ restored or said again. Every write but ``generate about`` needs ``--reason``,
19
+ which goes to the audit log.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ from datetime import date
25
+ from typing import Any
26
+
27
+ import typer
28
+ from rich.console import Console
29
+
30
+ from makea_cli import api_client
31
+ from makea_cli.commands._util import print_json_or_exit
32
+ from makea_cli.registry import command
33
+
34
+ console = Console()
35
+
36
+ _ABOUT_EPILOG = """
37
+ Target, exactly one of:
38
+ --user a person: user_id (Cognito sub) or email
39
+ --supplier one factory, by supplier id
40
+ {target} in the API path is users/{user} or suppliers/{supplier}.
41
+
42
+ KEY is a topic: `get about` lists them under keys[] (channels, roles,
43
+ markets, closures, …), with what each means.
44
+
45
+ Examples
46
+ makea-cli admin get about --user brand@example.com
47
+ makea-cli admin update about channels --user brand@example.com \\
48
+ --text "You sell wholesale to about 20 stockists." --reason "Said on the 14 Oct call"
49
+ makea-cli admin delete about price_band --supplier sup_123 --reason "Counted from one order"
50
+ makea-cli admin update about price_band --supplier sup_123 --restore --reason "Removed by mistake"
51
+ makea-cli admin generate about --user brand@example.com --read
52
+ """.strip()
53
+
54
+
55
+ def _user_option() -> Any:
56
+ return typer.Option(None, "--user", "-u", help="Target person: user_id or email.")
57
+
58
+
59
+ def _supplier_option() -> Any:
60
+ return typer.Option(None, "--supplier", help="Target factory: supplier id.")
61
+
62
+
63
+ def _reason_option() -> Any:
64
+ return typer.Option(..., "--reason", "-r", help="Why (required). Kept in the audit log.")
65
+
66
+
67
+ def _target(user: str | None, supplier: str | None) -> str:
68
+ user = (user or "").strip() or None
69
+ supplier = (supplier or "").strip() or None
70
+ if bool(user) == bool(supplier):
71
+ raise typer.BadParameter("pass exactly one of --user, --supplier")
72
+ return api_client.about_path(user=user, supplier=supplier)
73
+
74
+
75
+ def _reason(raw: str) -> str:
76
+ reason = " ".join(raw.split())
77
+ if not reason:
78
+ raise typer.BadParameter("--reason must not be empty")
79
+ return reason
80
+
81
+
82
+ def register(app: typer.Typer) -> None:
83
+ @command(
84
+ app,
85
+ "admin",
86
+ "get",
87
+ "about",
88
+ api="GET /admin/about/{target}",
89
+ help=(
90
+ "GET /admin/about/{target} — one account's About you as its Knowledge tab "
91
+ "shows it: facts[] (key, text, source said/counted/read, valid_until), "
92
+ "removed[], unknown[], paused, and keys[] (every topic). Does not recount."
93
+ ),
94
+ epilog=_ABOUT_EPILOG,
95
+ )
96
+ def get_about(
97
+ user: str | None = _user_option(),
98
+ supplier: str | None = _supplier_option(),
99
+ ) -> None:
100
+ """Show an account's About you."""
101
+ base = _target(user, supplier)
102
+ print_json_or_exit(console, lambda: api_client.admin_get_about(base))
103
+
104
+ @command(
105
+ app,
106
+ "admin",
107
+ "update",
108
+ "about",
109
+ api="PATCH /admin/about/{target}/{key}",
110
+ side_effects=[
111
+ "Beeboo reads the new line from this account's next turn",
112
+ "the line shows on the account's Knowledge > About you tab",
113
+ ],
114
+ approval="ask",
115
+ reversible=True,
116
+ idempotent=True,
117
+ help=(
118
+ "PATCH /admin/about/{target}/{key} — add or reword one About you line (it then "
119
+ "stands as the account's own words); with --restore, POST …/{key}/restore "
120
+ "brings a removed line back. --reason required."
121
+ ),
122
+ epilog=_ABOUT_EPILOG,
123
+ )
124
+ def update_about(
125
+ key: str = typer.Argument(..., help="Topic key, e.g. channels (see get about)."),
126
+ user: str | None = _user_option(),
127
+ supplier: str | None = _supplier_option(),
128
+ reason: str = _reason_option(),
129
+ text: str | None = typer.Option(
130
+ None, "--text", help="The line, written to the account ('You sell…')."
131
+ ),
132
+ valid_until: str | None = typer.Option(
133
+ None,
134
+ "--valid-until",
135
+ help='YYYY-MM-DD the fact stops holding (a closure); "none" removes it.',
136
+ ),
137
+ restore: bool = typer.Option(False, "--restore", help="Bring a removed line back."),
138
+ ) -> None:
139
+ """Add, reword or restore one About you line."""
140
+ base = _target(user, supplier)
141
+ why = _reason(reason)
142
+ if restore:
143
+ if text is not None or valid_until is not None:
144
+ raise typer.BadParameter("--restore takes no --text or --valid-until")
145
+ print_json_or_exit(console, lambda: api_client.admin_restore_about_line(base, key, why))
146
+ return
147
+ body: dict[str, Any] = {"reason": why}
148
+ if text is not None:
149
+ body["text"] = text
150
+ if valid_until is not None:
151
+ if valid_until.strip().lower() == "none":
152
+ body["valid_until"] = None
153
+ else:
154
+ try:
155
+ body["valid_until"] = date.fromisoformat(valid_until.strip()).isoformat()
156
+ except ValueError as e:
157
+ raise typer.BadParameter("--valid-until: expected YYYY-MM-DD") from e
158
+ if len(body) == 1:
159
+ raise typer.BadParameter("nothing to change: pass --text, --valid-until or --restore")
160
+ print_json_or_exit(console, lambda: api_client.admin_set_about_line(base, key, body))
161
+
162
+ @command(
163
+ app,
164
+ "admin",
165
+ "delete",
166
+ "about",
167
+ api="DELETE /admin/about/{target}/{key}",
168
+ side_effects=[
169
+ "the line leaves the account's About you and Beeboo's context",
170
+ "counting and reading will not bring the topic back",
171
+ ],
172
+ approval="ask",
173
+ reversible=True,
174
+ idempotent=False,
175
+ help=(
176
+ "DELETE /admin/about/{target}/{key} — remove one About you line; it is not "
177
+ "guessed again (update about KEY --restore brings it back). --reason required."
178
+ ),
179
+ epilog=_ABOUT_EPILOG,
180
+ )
181
+ def delete_about(
182
+ key: str = typer.Argument(..., help="Topic key (see get about)."),
183
+ user: str | None = _user_option(),
184
+ supplier: str | None = _supplier_option(),
185
+ reason: str = _reason_option(),
186
+ ) -> None:
187
+ """Remove one About you line."""
188
+ base = _target(user, supplier)
189
+ why = _reason(reason)
190
+ print_json_or_exit(console, lambda: api_client.admin_remove_about_line(base, key, why))
191
+
192
+ @command(
193
+ app,
194
+ "admin",
195
+ "update",
196
+ "about-pause",
197
+ api="POST /admin/about/{target}/pause",
198
+ side_effects=["Beeboo stops (or resumes) reading this account's About you"],
199
+ approval="ask",
200
+ reversible=True,
201
+ idempotent=True,
202
+ help=(
203
+ "POST /admin/about/{target}/pause — stop Beeboo using the account's About you "
204
+ "(--resume to start again); the lines are kept. --reason required."
205
+ ),
206
+ epilog=_ABOUT_EPILOG,
207
+ )
208
+ def update_about_pause(
209
+ user: str | None = _user_option(),
210
+ supplier: str | None = _supplier_option(),
211
+ reason: str = _reason_option(),
212
+ resume: bool = typer.Option(False, "--resume", help="Start using it again."),
213
+ ) -> None:
214
+ """Pause or resume an account's About you."""
215
+ base = _target(user, supplier)
216
+ why = _reason(reason)
217
+ print_json_or_exit(console, lambda: api_client.admin_pause_about(base, not resume, why))
218
+
219
+ @command(
220
+ app,
221
+ "admin",
222
+ "generate",
223
+ "about",
224
+ api="POST /admin/about/{target}/refresh",
225
+ side_effects=[
226
+ "recounts the counted lines from the account's records now",
227
+ "with --read, adds lines read from its conversations (one model call)",
228
+ ],
229
+ approval="auto",
230
+ reversible=False,
231
+ idempotent=True,
232
+ help=(
233
+ "POST /admin/about/{target}/refresh — bring an account's About you up to date "
234
+ "now instead of at the nightly pass: recount from records; --read also reads "
235
+ "its conversations since last time; --force re-reads all of them."
236
+ ),
237
+ epilog=_ABOUT_EPILOG,
238
+ )
239
+ def generate_about(
240
+ user: str | None = _user_option(),
241
+ supplier: str | None = _supplier_option(),
242
+ read: bool = typer.Option(False, "--read", help="Also read conversations (model call)."),
243
+ force: bool = typer.Option(
244
+ False, "--force", help="With --read: re-read everything, not just what is new."
245
+ ),
246
+ ) -> None:
247
+ """Recount (and read) an account's About you now."""
248
+ base = _target(user, supplier)
249
+ if force and not read:
250
+ raise typer.BadParameter("--force only applies with --read")
251
+ print_json_or_exit(
252
+ console, lambda: api_client.admin_refresh_about(base, read=read, force=force)
253
+ )
@@ -1,11 +1,16 @@
1
- """Admin commands for one person's AI playbook rules (Knowledge > Rules).
1
+ """Admin commands for AI playbook rules (Knowledge > Rules).
2
2
 
3
3
  A *rule* is one line Beeboo follows for an account ("Always book DHL Express",
4
4
  "Approve PP samples from photos"). Rules live on the brand's team playbook, on
5
- the person's own account, and, for a factory, on its company playbook. These
6
- commands address the person (``--user`` takes a user_id or an email) and the
7
- backend finds every scope; an email on more than one account is refused with
8
- the candidates, so pass the user_id then.
5
+ the person's own account, for a factory on its company playbook, and on the
6
+ platform-wide GLOBAL playbook every account's AI reads. These commands address
7
+ one of three targets:
8
+
9
+ * ``--user``: a person (user_id or email); the backend finds every scope their
10
+ rules live in. An email on more than one account is refused with the
11
+ candidates, so pass the user_id then.
12
+ * ``--supplier``: one factory's company playbook, by supplier id.
13
+ * ``--global``: the GLOBAL playbook (at most 30 live rules).
9
14
 
10
15
  Every write needs ``--reason``. The rule keeps it as an evidence entry
11
16
  (``admin_add`` / ``admin_edit`` / ``admin_delete`` with who, why, when and,
@@ -17,6 +22,7 @@ the row stays as the record, and ``update --status active`` brings it back.
17
22
  from __future__ import annotations
18
23
 
19
24
  import json
25
+ from datetime import date
20
26
  from typing import Any
21
27
 
22
28
  import typer
@@ -34,11 +40,16 @@ _APPLIES_TO_KINDS = ("style", "collection", "supplier", "element")
34
40
  _MODES = ("remind", "act")
35
41
 
36
42
  _RULES_EPILOG = """
37
- --user takes a user_id (Cognito sub) or an email.
43
+ Target, exactly one of:
44
+ --user a person: user_id (Cognito sub) or email
45
+ --supplier one factory, by supplier id
46
+ --global the platform-wide playbook every account's AI reads (max 30 live rules)
47
+ {target} in the API path is users/{user}, suppliers/{supplier} or global.
38
48
 
39
49
  Scopes: ORG#… is the brand's team playbook, USER#… the person's own,
40
- SUPPLIER#… a factory's. A new rule goes to the factory playbook for a supplier,
41
- else the team's (the person's own when there is no team); --scope overrides.
50
+ SUPPLIER#… a factory's, PLAYBOOK#GLOBAL everyone's. A new rule for a --user
51
+ goes to the factory playbook for a supplier, else the team's (the person's own
52
+ when there is no team); --scope overrides.
42
53
 
43
54
  --applies-to narrows a rule to one thing: KIND:ID[:LABEL] with KIND one of
44
55
  style, collection, supplier, element (e.g. supplier:sup_123:Ningbo Knit).
@@ -58,11 +69,33 @@ Examples
58
69
  --status muted --reason "Brand asked to pause it by email"
59
70
  makea-cli admin delete rule rul_0123456789ab --user brand@example.com \\
60
71
  --reason "Learned from another brand's thread"
72
+ makea-cli admin list rule --supplier sup_123
73
+ makea-cli admin create rule --global \\
74
+ --text "Quote prices in the brand's currency" --reason "Agreed in the 20 Oct review"
61
75
  """.strip()
62
76
 
63
77
 
64
78
  def _user_option() -> Any:
65
- return typer.Option(..., "--user", "-u", help="Target person: user_id or email.")
79
+ return typer.Option(None, "--user", "-u", help="Target person: user_id or email.")
80
+
81
+
82
+ def _supplier_option() -> Any:
83
+ return typer.Option(None, "--supplier", help="Target factory: supplier id.")
84
+
85
+
86
+ def _global_option() -> Any:
87
+ return typer.Option(
88
+ False, "--global", help="Target the platform-wide playbook every account reads."
89
+ )
90
+
91
+
92
+ def _target(user: str | None, supplier: str | None, is_global: bool) -> str:
93
+ """The rules path for exactly one of --user, --supplier, --global."""
94
+ user = (user or "").strip() or None
95
+ supplier = (supplier or "").strip() or None
96
+ if sum(bool(t) for t in (user, supplier, is_global)) != 1:
97
+ raise typer.BadParameter("pass exactly one of --user, --supplier, --global")
98
+ return api_client.playbook_rules_path(user=user, supplier=supplier, is_global=is_global)
66
99
 
67
100
 
68
101
  def _reason_option() -> Any:
@@ -107,6 +140,13 @@ def _when(raw: str) -> dict[str, Any]:
107
140
  return data
108
141
 
109
142
 
143
+ def _date(raw: str) -> str:
144
+ try:
145
+ return date.fromisoformat(raw.strip()).isoformat()
146
+ except ValueError as e:
147
+ raise typer.BadParameter("--valid-until: expected YYYY-MM-DD") from e
148
+
149
+
110
150
  def _choice(value: str | None, allowed: tuple[str, ...], flag: str) -> str | None:
111
151
  if value is None:
112
152
  return None
@@ -122,16 +162,19 @@ def register(app: typer.Typer) -> None:
122
162
  "admin",
123
163
  "list",
124
164
  "rule",
125
- api="GET /admin/playbook/users/{user}/rules",
165
+ api="GET /admin/playbook/{target}/rules",
126
166
  help=(
127
- "GET /admin/playbook/users/{user}/rules — every AI playbook rule that holds "
128
- "for one person (team, own account, factory): status, scope, text, "
129
- "applies_to/when, mode/effect, source line, dates. Archived ones only with --all."
167
+ "GET /admin/playbook/{target}/rules — every AI playbook rule that holds "
168
+ "for one person (team, own account, factory), one factory (--supplier) or "
169
+ "everyone (--global): status, scope, text, applies_to/when, mode/effect, "
170
+ "source line, dates. Archived ones only with --all."
130
171
  ),
131
172
  epilog=_RULES_EPILOG,
132
173
  )
133
174
  def list_rules(
134
- user: str = _user_option(),
175
+ user: str | None = _user_option(),
176
+ supplier: str | None = _supplier_option(),
177
+ is_global: bool = _global_option(),
135
178
  status: str | None = typer.Option(
136
179
  None,
137
180
  "--status",
@@ -142,14 +185,15 @@ def register(app: typer.Typer) -> None:
142
185
  False, "--all", help="Also list archived (deleted) rules."
143
186
  ),
144
187
  ) -> None:
145
- """List a person's playbook rules."""
188
+ """List the playbook rules of a person, a factory or the global playbook."""
189
+ base = _target(user, supplier, is_global)
146
190
  if status:
147
191
  for s in status.split(","):
148
192
  _choice(s, _STATUSES, "--status")
149
193
  print_json_or_exit(
150
194
  console,
151
- lambda: api_client.admin_list_user_rules(
152
- user, status=status, include_archived=include_archived
195
+ lambda: api_client.admin_list_rules(
196
+ base, status=status, include_archived=include_archived
153
197
  ),
154
198
  )
155
199
 
@@ -158,19 +202,22 @@ def register(app: typer.Typer) -> None:
158
202
  "admin",
159
203
  "get",
160
204
  "rule",
161
- api="GET /admin/playbook/users/{user}/rules/{rule_id}",
205
+ api="GET /admin/playbook/{target}/rules/{rule_id}",
162
206
  help=(
163
- "GET /admin/playbook/users/{user}/rules/{rule_id} — one rule in full, "
207
+ "GET /admin/playbook/{target}/rules/{rule_id} — one rule in full, "
164
208
  "evidence (where it came from, who changed it and why) included."
165
209
  ),
166
210
  epilog=_RULES_EPILOG,
167
211
  )
168
212
  def get_rule(
169
213
  rule_id: str = typer.Argument(..., help="Rule id (rul_…)."),
170
- user: str = _user_option(),
214
+ user: str | None = _user_option(),
215
+ supplier: str | None = _supplier_option(),
216
+ is_global: bool = _global_option(),
171
217
  ) -> None:
172
218
  """Show one playbook rule with its evidence."""
173
- print_json_or_exit(console, lambda: api_client.admin_get_user_rule(user, rule_id))
219
+ base = _target(user, supplier, is_global)
220
+ print_json_or_exit(console, lambda: api_client.admin_get_rule(base, rule_id))
174
221
 
175
222
  @command(
176
223
  app,
@@ -242,27 +289,33 @@ def register(app: typer.Typer) -> None:
242
289
  "admin",
243
290
  "create",
244
291
  "rule",
245
- api="POST /admin/playbook/users/{user}/rules",
292
+ api="POST /admin/playbook/{target}/rules",
246
293
  side_effects=[
247
- "Beeboo follows the rule in this account's AI answers from now on",
294
+ "Beeboo follows the rule in this account's AI answers from now on "
295
+ "(every account's, with --global)",
248
296
  "shows on the brand's Knowledge > Rules page (brand scopes)",
249
297
  ],
250
298
  approval="ask",
251
299
  reversible=True,
252
300
  idempotent=False,
253
301
  help=(
254
- "POST /admin/playbook/users/{user}/rules — add a rule to a person's playbook "
255
- "(admin-authored, active unless --status). Refuses a repeat or a conflict "
256
- "unless --force. --reason required."
302
+ "POST /admin/playbook/{target}/rules — add a rule to a person's, a factory's "
303
+ "or the global playbook (admin-authored, active unless --status). Refuses a "
304
+ "repeat or a conflict unless --force, and a 31st live global rule. "
305
+ "--reason required."
257
306
  ),
258
307
  epilog=_RULES_EPILOG,
259
308
  )
260
309
  def create_rule(
261
- user: str = _user_option(),
310
+ user: str | None = _user_option(),
311
+ supplier: str | None = _supplier_option(),
312
+ is_global: bool = _global_option(),
262
313
  text: str = typer.Option(..., "--text", help="The rule, one line (max 160 chars)."),
263
314
  reason: str = _reason_option(),
264
315
  scope: str | None = typer.Option(
265
- None, "--scope", help=f"Where it lives: {', '.join(_SCOPES)} (default: see below)."
316
+ None,
317
+ "--scope",
318
+ help=f"Where a --user rule lives: {', '.join(_SCOPES)} (default: see below).",
266
319
  ),
267
320
  applies_to: str | None = typer.Option(
268
321
  None, "--applies-to", help="Narrow to one thing: KIND:ID[:LABEL]."
@@ -290,10 +343,18 @@ def register(app: typer.Typer) -> None:
290
343
  force: bool = typer.Option(
291
344
  False, "--force", help="Add even if it repeats or disagrees with an existing rule."
292
345
  ),
346
+ valid_until: str | None = typer.Option(
347
+ None,
348
+ "--valid-until",
349
+ help="YYYY-MM-DD the rule ends on (a closure, a temporary arrangement).",
350
+ ),
293
351
  ) -> None:
294
- """Add a playbook rule for a person."""
352
+ """Add a playbook rule for a person, a factory or everyone."""
353
+ base = _target(user, supplier, is_global)
295
354
  body: dict[str, Any] = {"text": text, "reason": _reason(reason)}
296
355
  if scope is not None:
356
+ if not user:
357
+ raise typer.BadParameter("--scope only applies with --user")
297
358
  body["scope"] = _choice(scope, _SCOPES, "--scope")
298
359
  if applies_to is not None:
299
360
  body["applies_to"] = _applies_to(applies_to)
@@ -311,14 +372,16 @@ def register(app: typer.Typer) -> None:
311
372
  body["status"] = _choice(status, ("pending", "active", "muted"), "--status")
312
373
  if force:
313
374
  body["force"] = True
314
- print_json_or_exit(console, lambda: api_client.admin_create_user_rule(user, body))
375
+ if valid_until is not None:
376
+ body["valid_until"] = _date(valid_until)
377
+ print_json_or_exit(console, lambda: api_client.admin_create_rule(base, body))
315
378
 
316
379
  @command(
317
380
  app,
318
381
  "admin",
319
382
  "update",
320
383
  "rule",
321
- api="PATCH /admin/playbook/users/{user}/rules/{rule_id}",
384
+ api="PATCH /admin/playbook/{target}/rules/{rule_id}",
322
385
  side_effects=[
323
386
  "changes what Beeboo does for this account",
324
387
  "a learned rule becomes authored and stops expiring",
@@ -327,14 +390,16 @@ def register(app: typer.Typer) -> None:
327
390
  reversible=True,
328
391
  idempotent=True,
329
392
  help=(
330
- "PATCH /admin/playbook/users/{user}/rules/{rule_id} — change a rule's text, "
393
+ "PATCH /admin/playbook/{target}/rules/{rule_id} — change a rule's text, "
331
394
  "status, applies_to, when or mode. --reason required; the rule keeps what it was before."
332
395
  ),
333
396
  epilog=_RULES_EPILOG,
334
397
  )
335
398
  def update_rule(
336
399
  rule_id: str = typer.Argument(..., help="Rule id (rul_…)."),
337
- user: str = _user_option(),
400
+ user: str | None = _user_option(),
401
+ supplier: str | None = _supplier_option(),
402
+ is_global: bool = _global_option(),
338
403
  reason: str = _reason_option(),
339
404
  text: str | None = typer.Option(None, "--text", help="New words."),
340
405
  status: str | None = typer.Option(None, "--status", help=f"One of {', '.join(_STATUSES)}."),
@@ -345,8 +410,14 @@ def register(app: typer.Typer) -> None:
345
410
  None, "--when", help="Which products, JSON ({} for every product)."
346
411
  ),
347
412
  mode: str | None = typer.Option(None, "--mode", help="remind or act."),
413
+ valid_until: str | None = typer.Option(
414
+ None,
415
+ "--valid-until",
416
+ help='YYYY-MM-DD the rule ends on; "none" removes the end date.',
417
+ ),
348
418
  ) -> None:
349
- """Edit a person's playbook rule."""
419
+ """Edit a playbook rule."""
420
+ base = _target(user, supplier, is_global)
350
421
  body: dict[str, Any] = {}
351
422
  if text is not None:
352
423
  body["text"] = text
@@ -358,19 +429,24 @@ def register(app: typer.Typer) -> None:
358
429
  body["when"] = _when(when)
359
430
  if mode is not None:
360
431
  body["mode"] = _choice(mode, _MODES, "--mode")
432
+ if valid_until is not None:
433
+ body["valid_until"] = (
434
+ "" if valid_until.strip().lower() == "none" else _date(valid_until)
435
+ )
361
436
  if not body:
362
437
  raise typer.BadParameter(
363
- "nothing to change: pass --text, --status, --applies-to, --when or --mode"
438
+ "nothing to change: pass --text, --status, --applies-to, --when, --mode "
439
+ "or --valid-until"
364
440
  )
365
441
  body["reason"] = _reason(reason)
366
- print_json_or_exit(console, lambda: api_client.admin_update_user_rule(user, rule_id, body))
442
+ print_json_or_exit(console, lambda: api_client.admin_update_rule(base, rule_id, body))
367
443
 
368
444
  @command(
369
445
  app,
370
446
  "admin",
371
447
  "delete",
372
448
  "rule",
373
- api="DELETE /admin/playbook/users/{user}/rules/{rule_id}",
449
+ api="DELETE /admin/playbook/{target}/rules/{rule_id}",
374
450
  side_effects=[
375
451
  "archives the rule: off the brand's Rules page and out of every AI prompt",
376
452
  "the learner will not propose the same words again",
@@ -379,16 +455,19 @@ def register(app: typer.Typer) -> None:
379
455
  reversible=True,
380
456
  idempotent=False,
381
457
  help=(
382
- "DELETE /admin/playbook/users/{user}/rules/{rule_id} — remove a rule (archived, "
458
+ "DELETE /admin/playbook/{target}/rules/{rule_id} — remove a rule (archived, "
383
459
  "with who and why kept on it; update --status active restores it). --reason required."
384
460
  ),
385
461
  epilog=_RULES_EPILOG,
386
462
  )
387
463
  def delete_rule(
388
464
  rule_id: str = typer.Argument(..., help="Rule id (rul_…)."),
389
- user: str = _user_option(),
465
+ user: str | None = _user_option(),
466
+ supplier: str | None = _supplier_option(),
467
+ is_global: bool = _global_option(),
390
468
  reason: str = _reason_option(),
391
469
  ) -> None:
392
- """Remove (archive) a person's playbook rule."""
470
+ """Remove (archive) a playbook rule."""
471
+ base = _target(user, supplier, is_global)
393
472
  why = _reason(reason)
394
- print_json_or_exit(console, lambda: api_client.admin_delete_user_rule(user, rule_id, why))
473
+ print_json_or_exit(console, lambda: api_client.admin_delete_rule(base, rule_id, why))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: makea-cli
3
- Version: 0.2.18
3
+ Version: 0.2.20
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
@@ -92,21 +92,24 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
92
92
  | `makea-cli admin backfill supplier-id` | write(never) | `POST /admin/supplier/backfill_supplier_id_with_quote_requests` | Migrate supplier_id from a wrong UUID to the Cognito user sub (user_id): profile + Cognito supplierReferenceId, optio… | `backfill-supplier-id` |
93
93
  | `makea-cli admin create library-element` | write(auto) | `POST /admin/designer/{user_id}/library_components` | save a reusable component under a designer. Provide --section and --values (see admin get library-schema). | `library-create` |
94
94
  | `makea-cli admin create quote-request` | write(ask) | `POST /admin/supplier/create_quote_request` | create/send a quote request to a supplier for a product (admin). | `create-quote-request` |
95
- | `makea-cli admin create rule` | write(ask) | `POST /admin/playbook/users/{user}/rules` | add a rule to one person's AI playbook (user_id or email); admin-authored, active unless --status. Refuses a repeat or a conflict unless --force. --reason required. | — |
95
+ | `makea-cli admin create rule` | write(ask) | `POST /admin/playbook/{target}/rules` | add a rule to a person's (`--user`, user_id or email), a factory's (`--supplier`) or the platform-wide (`--global`, max 30 live) AI playbook; admin-authored, active unless --status. Refuses a repeat or a conflict unless --force. --reason required. | — |
96
96
  | `makea-cli admin create shipping-fee` | write(ask) | `POST /admin/shipping_orders/{shipping_order_id}/fees/add` | add a fee (fixed amount or percentage) on top of the freight. | — |
97
97
  | `makea-cli admin create shipping-option` | write(ask) | `POST /admin/shipping_orders/{shipping_order_id}/shipping-options` | add one freight quote (provider, speed, price, currency). | — |
98
98
  | `makea-cli admin create shipping-order` | write(ask) | `POST /admin/shipping_orders/create` | make a shipment for a brand's production and/or sampling orders. The shipment belongs to the orders' owner; you are r… | — |
99
99
  | `makea-cli admin create supplier` | write(ask) | `POST /admin/supplier/add_supplier` | create supplier from JSON file (admin). Run `makea-cli get-supplier-profile-schema` FIRST to get the field taxonomy (… | `add-supplier` |
100
100
  | `makea-cli admin create user` | write(never) | `POST /admin/users/create` | register a user and confirm the Cognito account in one step (no verification email). Allowed --user-type values: "Fas… | `create-user` |
101
+ | `makea-cli admin delete about` | write(ask) | `DELETE /admin/about/{target}/{key}` | remove one About you line (`--user` / `--supplier`); it is not guessed again. --reason required. | — |
101
102
  | `makea-cli admin delete library-element` | write(never) | `DELETE /admin/designer/{user_id}/library_components/{component_id}` | remove a component from the designer's org library. | `library-delete` |
102
- | `makea-cli admin delete rule` | write(ask) | `DELETE /admin/playbook/users/{user}/rules/{rule_id}` | remove a rule: archived, with who and why kept on it (`update rule --status active` restores it). --reason required. | — |
103
+ | `makea-cli admin delete rule` | write(ask) | `DELETE /admin/playbook/{target}/rules/{rule_id}` | remove a rule (`--user` / `--supplier` / `--global`): archived, with who and why kept on it (`update rule --status active` restores it). --reason required. | — |
103
104
  | `makea-cli admin delete shipping-fee` | write(ask) | `DELETE /admin/shipping_orders/{shipping_order_id}/fees/{fee_id}/remove` | remove one fee. | — |
104
105
  | `makea-cli admin delete shipping-option` | write(ask) | `DELETE /admin/shipping_orders/{shipping_order_id}/shipping-options/{shipping_option_id}/remove` | withdraw one freight quote. | — |
105
106
  | `makea-cli admin delete shipping-order` | write(never) | `DELETE /admin/shipping_orders/{shipping_order_id}/delete` | remove a shipment and free its orders. Graded `never`: the backend does not check status, so it removes a paid or in-transit shipment too. | — |
106
107
  | `makea-cli admin delete shipping-order-item` | write(ask) | `POST /admin/production_orders/{id}/unlink_from_shipping_order/{shipping_order_id}` | take one production or sampling order off a shipment. A shipment left empty is deleted. | — |
107
108
  | `makea-cli admin download document` | read | `GET /admin/document/download` | save a document file (document id + designer user_id). | `download-document` |
108
109
  | `makea-cli admin download product-document` | read | `GET /admin/document/download` | Resolve product via admin list product-order payload, then GET /admin/document/download. | `download-product-document` |
110
+ | `makea-cli admin generate about` | write(auto) | `POST /admin/about/{target}/refresh` | recount an account's About you now; `--read` also reads its conversations (one model call). | — |
109
111
  | `makea-cli admin generate pricing-groups` | write(ask) | `POST /admin/production_orders/{id}/details/update` | Lay a production order's variants into pricing groups along one axis (--by style \| colour \| variant \| all) with th… | `production-groups-generate` |
112
+ | `makea-cli admin get about` | read | `GET /admin/about/{target}` | one account's About you (`--user`: a supplier account's person gets their factory's page; `--supplier`): facts, removed, unknown, paused, topic keys. | — |
110
113
  | `makea-cli admin get active-users` | read | `POST /admin/analytics/query` | Distinct active users per day over the last N days (DAU series). | `analytics-active-users` |
111
114
  | `makea-cli admin get analytics-query` | read | `POST /admin/analytics/query` | Run an arbitrary HogQL query (escape hatch). Example: analytics-query "SELECT count() FROM events" | `analytics-query` |
112
115
  | `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` |
@@ -116,7 +119,7 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
116
119
  | `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` |
117
120
  | `makea-cli admin get quote-request` | read | `GET /admin/quote_requests/{quote_request_id}` | one quote request in full. | — |
118
121
  | `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` |
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. | — |
122
+ | `makea-cli admin get rule` | read | `GET /admin/playbook/{target}/rules/{rule_id}` | one rule in full (`--user` / `--supplier` / `--global`), with its evidence: where it came from, who changed it and why. | — |
120
123
  | `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. | — |
121
124
  | `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. | — |
122
125
  | `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` |
@@ -129,7 +132,7 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
129
132
  | `makea-cli admin list production-order` | read | `GET /admin/production_orders?type=PRODUCTION` | 大货 (production) orders only. For restock use admin list restock-order; for shipping use admin list shipping-order. | `list-all-production-orders` |
130
133
  | `makea-cli admin list quote-request` | read | `GET /admin/quote_requests` | quote requests, optionally for one product (--product) or one supplier (--supplier, GET /admin/quote_requests/supplie… | — |
131
134
  | `makea-cli admin list restock-order` | read | `GET /admin/production_orders?type=RESTOCK` | restock orders only. Restock shares the production_orders table; this filters to type=RESTOCK. | `list-all-restock-orders` |
132
- | `makea-cli admin list rule` | read | `GET /admin/playbook/users/{user}/rules` | every AI playbook rule that holds for one person (team, own account, factory): status, scope, text, which products, effect, source. Archived ones only with --all. | — |
135
+ | `makea-cli admin list rule` | read | `GET /admin/playbook/{target}/rules` | every AI playbook rule for one person (team, own account, factory), one factory (`--supplier`) or the platform (`--global`): status, scope, text, which products, effect, source. Archived ones only with --all. | — |
133
136
  | `makea-cli admin list sampling-order` | read | `GET /admin/sampling_orders/get_all` | paginated list of all sampling orders (admin). | `list-all-sampling-orders` |
134
137
  | `makea-cli admin list shipping-order` | read | `GET /admin/shipping_orders` | paginated list of all shipping orders (admin). | `list-all-shipping-orders` |
135
138
  | `makea-cli admin list supplier` | read | `GET /admin/supplier/get_all_suppliers` | list all suppliers (admin). | `list-suppliers` |
@@ -140,10 +143,12 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
140
143
  | `makea-cli admin set production-tiers` | write(ask) | `POST /admin/production_orders/{id}/details/update` | Set the order-wide price tiers / MOQ / incoterm / currency on a production order (the schedule used when it has no pr… | `production-tiers-set` |
141
144
  | `makea-cli admin set production-variants` | write(ask) | `POST /admin/production_orders/{id}/details/update` | Set a production order's available sizes and colours (the grid the buyer's cart and every pricing group's cart keys a… | `production-variants-set` |
142
145
  | `makea-cli admin submit quote` | write(ask) | `POST /admin/quote_requests/{quote_request_id}/submit_quote` | admin submits a new quote (link) to a quote request. Pricing groups cannot be sent here (the submit endpoint ignores … | `submit-supplier-quote` |
146
+ | `makea-cli admin update about` | write(ask) | `PATCH /admin/about/{target}/{key}` | add or reword one About you line (stands as the account's own words); `--restore` brings a removed one back. --reason required. | — |
147
+ | `makea-cli admin update about-pause` | write(ask) | `POST /admin/about/{target}/pause` | stop (or `--resume`) Beeboo using an account's About you. --reason required. | — |
143
148
  | `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` |
144
149
  | `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` |
145
150
  | `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` |
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 or mode. --reason required; the rule keeps what it was before. | — |
151
+ | `makea-cli admin update rule` | write(ask) | `PATCH /admin/playbook/{target}/rules/{rule_id}` | change a rule's text, status, applies_to, when, mode or end date (--valid-until), on `--user` / `--supplier` / `--global`. --reason required; the rule keeps what it was before. | — |
147
152
  | `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… | — |
148
153
  | `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` |
149
154
  | `makea-cli admin update tech-spec` | write(ask) | `POST /admin/products/{id}/technical-specifications` | persist specs from a JSON file. | `save-product-tech-spec` |
@@ -1,6 +1,6 @@
1
- makea_cli/__init__.py,sha256=3RGPra41WobAbWeoPRqR_JXeysqFvK3H3AP1g9gjj3g,23
1
+ makea_cli/__init__.py,sha256=PP1XN3LVw4efHZSwpFDbQRezvRqPg1JqZ--H2vUombw,23
2
2
  makea_cli/__main__.py,sha256=AkQjxWfKE3w9iD1d6I-2Zqvv2t9cct0oYyFF0UiA-Z0,144
3
- makea_cli/api_client.py,sha256=yrHxKDQUov6iuXJZaMq33tyKfuoPhVg6wYLLIwt-88A,71777
3
+ makea_cli/api_client.py,sha256=dQckmLB-wbUuhznW7ej_xe79hVQm_3Xn1OzGykNBVwk,73833
4
4
  makea_cli/auth_pkce.py,sha256=iXSyJ7DM3qVuj-3FwPiqM25CxXz9ebFs9FNthZdw3ws,7315
5
5
  makea_cli/broker.py,sha256=5O650nAdRuF-u9E1MuVM2jVv796iBdxJGIaJasxHij0,3019
6
6
  makea_cli/config.py,sha256=hz8MnJSkhxcIEZkcpHR005JrDceo1Xmi8qwIUq50cMU,3003
@@ -10,8 +10,10 @@ makea_cli/main.py,sha256=nuTQ8_P8OSdRbjMHMB4qcKdex124nS-ApCW-zfbqlI0,7169
10
10
  makea_cli/output.py,sha256=VWvZe2Ad8zxT4ZQyBhFRc6wkFwbyYzQFPddepANGAbY,6361
11
11
  makea_cli/posthog_client.py,sha256=k0cy9Hq7bhdLlPvC1ZW_esJ70xHDdQzPQUlx-GpVskk,1921
12
12
  makea_cli/registry.py,sha256=GYJK_idhwIh1X2ictwFjn8PEMaXT56hFVkoLEVYrVqw,13722
13
- makea_cli/commands/__init__.py,sha256=A6nBCidMsRXfNtIPhJhbvIQklYe1BIphMAubZQc1s0w,1676
13
+ makea_cli/commands/__init__.py,sha256=lTvsdzRvYIRwJuTlDPKcOmp0OWekNlxXsi-63g4q46w,1768
14
14
  makea_cli/commands/_util.py,sha256=zSFwWaWpncARlKxgq4WuJlJvNv7XdZ39HfHrNOELHuw,980
15
+ makea_cli/commands/about/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ makea_cli/commands/about/cmd.py,sha256=smvn0WWfRfyL6h1ZB7vXSmJY67t7qhTHdRqxTk4jqeI,9665
15
17
  makea_cli/commands/analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
18
  makea_cli/commands/analytics/cmd.py,sha256=KVLUtYSeyYZ8_09jIuIAmePjQqcpQS2mb5PBBzGwQYQ,6562
17
19
  makea_cli/commands/auth/__init__.py,sha256=NXoKGfkY2X_hb8GnAyzhoI_qDXfpwKZPqt4HnOrXW3Y,73
@@ -35,7 +37,7 @@ makea_cli/commands/metrics/cmd.py,sha256=ox5OD7Bk3QJcdHQv5u4t6G-OlC6eSbQG5BEH1yB
35
37
  makea_cli/commands/orders/__init__.py,sha256=6WKPqX02e0RRPmItPIBJ0TA4_yDI2PVvBDkAiMQu9rU,75
36
38
  makea_cli/commands/orders/cmd.py,sha256=Nh5lGv5k4SIwsr_hg-ndah8eTorZCYIMpTAz4CCi6oY,13352
37
39
  makea_cli/commands/playbook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- makea_cli/commands/playbook/cmd.py,sha256=lXKY6PQ6oLkHFHwghsPUKXtdT2bDLTtLl7Wgg8vhXtE,15237
40
+ makea_cli/commands/playbook/cmd.py,sha256=Vj2jPtFe6laIhL1ZTqkw4LRJzmSB8ewP0pd-Z2ADg8s,18608
39
41
  makea_cli/commands/product/__init__.py,sha256=mfdonFmpbddDSlJq6JWNWgNpM6aOpKtZr-3FJ6scrwg,76
40
42
  makea_cli/commands/product/cmd.py,sha256=W0oVTZvsK1QWZWv2x6NC26_JQMXrO16O8gYuKYPWC08,7101
41
43
  makea_cli/commands/production/__init__.py,sha256=Whn5ziwVMt4jzcokiFWLhWIpRLYC-ldnjZgAzeQ3We4,79
@@ -45,7 +47,7 @@ makea_cli/commands/shipping/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
45
47
  makea_cli/commands/shipping/cmd.py,sha256=ozt73pj3onlOv0NhEwiJlslyG9WOycE0QN4tmzwFlT0,17280
46
48
  makea_cli/commands/supplier/__init__.py,sha256=qfQDeQdQ-B7I_uwFVfcp1vXFUTL4fAcNLu3ipsZ7dfs,77
47
49
  makea_cli/commands/supplier/cmd.py,sha256=crRCy9WfhkryHMIL3iufoiT90_SG3-mKChAtdhd06uc,58076
48
- makea_cli-0.2.18.dist-info/METADATA,sha256=OagrYvbHIf9KWYTBUIPm0TXVlhJA4-WeBrIhY9WueCw,35416
49
- makea_cli-0.2.18.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
50
- makea_cli-0.2.18.dist-info/entry_points.txt,sha256=4x-lbVa1jBbNlkNq7L-rYyfRh2spZmc3BLIzP-Dl-Qk,50
51
- makea_cli-0.2.18.dist-info/RECORD,,
50
+ makea_cli-0.2.20.dist-info/METADATA,sha256=PQo8Hp4cyZ9xhDd4VcTgTQcGkjIoXrolYPkOktBMz3s,36693
51
+ makea_cli-0.2.20.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
52
+ makea_cli-0.2.20.dist-info/entry_points.txt,sha256=4x-lbVa1jBbNlkNq7L-rYyfRh2spZmc3BLIzP-Dl-Qk,50
53
+ makea_cli-0.2.20.dist-info/RECORD,,