@purveyors/cli 0.33.1 → 0.33.3
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 +81 -2
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +2 -0
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/manifest.d.ts.map +1 -1
- package/dist/commands/manifest.js +2 -0
- package/dist/commands/manifest.js.map +1 -1
- package/dist/commands/reference-profile.d.ts +4 -0
- package/dist/commands/reference-profile.d.ts.map +1 -0
- package/dist/commands/reference-profile.js +157 -0
- package/dist/commands/reference-profile.js.map +1 -0
- package/dist/lib/cherry.d.ts +2 -16
- package/dist/lib/cherry.d.ts.map +1 -1
- package/dist/lib/cherry.js +19 -5
- package/dist/lib/cherry.js.map +1 -1
- package/dist/lib/interactive/watch.d.ts +2 -3
- package/dist/lib/interactive/watch.d.ts.map +1 -1
- package/dist/lib/interactive/watch.js +4 -26
- package/dist/lib/interactive/watch.js.map +1 -1
- package/dist/lib/manifest.d.ts.map +1 -1
- package/dist/lib/manifest.js +214 -2
- package/dist/lib/manifest.js.map +1 -1
- package/dist/lib/market.d.ts +6 -2
- package/dist/lib/market.d.ts.map +1 -1
- package/dist/lib/reference-profiles.d.ts +102 -0
- package/dist/lib/reference-profiles.d.ts.map +1 -0
- package/dist/lib/reference-profiles.js +145 -0
- package/dist/lib/reference-profiles.js.map +1 -0
- package/dist/lib/roast.d.ts +29 -60
- package/dist/lib/roast.d.ts.map +1 -1
- package/dist/lib/roast.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +13 -0
- package/dist/program.js.map +1 -1
- package/package.json +2 -2
- package/dist/lib/artisan/parser.d.ts +0 -19
- package/dist/lib/artisan/parser.d.ts.map +0 -1
- package/dist/lib/artisan/parser.js +0 -376
- package/dist/lib/artisan/parser.js.map +0 -1
- package/dist/lib/artisan/temperature.d.ts +0 -52
- package/dist/lib/artisan/temperature.d.ts.map +0 -1
- package/dist/lib/artisan/temperature.js +0 -101
- package/dist/lib/artisan/temperature.js.map +0 -1
- package/dist/lib/artisan/types.d.ts +0 -195
- package/dist/lib/artisan/types.d.ts.map +0 -1
- package/dist/lib/artisan/types.js +0 -35
- package/dist/lib/artisan/types.js.map +0 -1
- package/dist/lib/artisan/validator.d.ts +0 -14
- package/dist/lib/artisan/validator.d.ts.map +0 -1
- package/dist/lib/artisan/validator.js +0 -228
- package/dist/lib/artisan/validator.js.map +0 -1
package/README.md
CHANGED
|
@@ -145,11 +145,12 @@ Remote data commands require a valid owner-bound API key with the required scope
|
|
|
145
145
|
- `catalog search` structured process filters require the `member` role
|
|
146
146
|
- `market` has public teaser slices for `signals --summary`, unfiltered retail `stats`, and process/retail/month `metadata`; all filtered or non-public slices require Parchment Intelligence access enforced server-side
|
|
147
147
|
- `price-index`, `procurement`, `inventory`, `roast`, `sales`, and `tasting` require the `member` role
|
|
148
|
+
- `reference-profile` requires a `member` credential plus Studio access, enforced server-side by Parchment
|
|
148
149
|
|
|
149
150
|
`purvey` uses Google OAuth through purveyors.io.
|
|
150
151
|
|
|
151
152
|
Set `PARCHMENT_API_KEY` (or `PURVEYORS_API_KEY`) to authenticate SDK-backed catalog,
|
|
152
|
-
inventory, roast, sales, tasting-read, market, price-index, and procurement operations
|
|
153
|
+
inventory, roast, reference-profile, sales, tasting-read, market, price-index, and procurement operations
|
|
153
154
|
without using the API key created by `purvey auth login`. Environment credentials take precedence.
|
|
154
155
|
|
|
155
156
|
Interactive login:
|
|
@@ -192,6 +193,8 @@ Credentials are stored at `~/.config/purvey/credentials.json`.
|
|
|
192
193
|
| `viewer` | `catalog search`, `catalog get`, `catalog stats`, excluding structured process filters |
|
|
193
194
|
| `member` | All viewer commands, `catalog similar`, structured process filters on `catalog search`, plus `price-index`, `procurement`, `inventory`, `roast`, `sales`, and `tasting` through the scoped key created by `purvey auth login` |
|
|
194
195
|
|
|
196
|
+
The `reference-profile` commands also require Studio access; the API enforces this entitlement.
|
|
197
|
+
|
|
195
198
|
Market Index teaser slices are public. Filtered `market signals`, origin/process/wholesale `market stats`, and non-public `market metadata` slices require Parchment Intelligence access; API-key denial is enforced by the canonical API. The stored login key carries `catalog:read`, which is also the canonical read scope for Market Index, Price Index, and procurement.
|
|
196
199
|
|
|
197
200
|
`auth`, `config`, `context`, and `manifest` remain available without pre-existing credentials.
|
|
@@ -669,6 +672,65 @@ Notes:
|
|
|
669
672
|
- `roast watch --auto-match` uses the `@purveyors/cli/cherry` helper to send roast metadata and the current stocked-inventory candidates to the canonical Parchment `POST /v1/roasts/classify` endpoint via `@purveyors/sdk`; it never calls an AI provider directly.
|
|
670
673
|
- `roast watch --commit-mode` defaults to `batch`.
|
|
671
674
|
|
|
675
|
+
### reference-profile
|
|
676
|
+
|
|
677
|
+
- `purvey reference-profile list [--include-archived]`
|
|
678
|
+
- `purvey reference-profile get <profile-id>`
|
|
679
|
+
- `purvey reference-profile chart <profile-id> <revision-id>`
|
|
680
|
+
- `purvey reference-profile import <file>`
|
|
681
|
+
- `purvey reference-profile preview <profile-id> <revision-id> --request <file>`
|
|
682
|
+
- `purvey reference-profile save <profile-id> <revision-id> --request <file>`
|
|
683
|
+
- `purvey reference-profile export <profile-id> <revision-id> --output <file>`
|
|
684
|
+
|
|
685
|
+
Reference-profile commands use the canonical Parchment API through `@purveyors/sdk`. They
|
|
686
|
+
require a member credential and Studio access, which Parchment enforces server-side.
|
|
687
|
+
|
|
688
|
+
`reference-profile import` uploads an Artisan `.alog` or another file accepted by the
|
|
689
|
+
canonical importer. Parchment owns parsing and private source retention. It creates a
|
|
690
|
+
reference profile, not an executed roast. `get` returns its current revision; pass
|
|
691
|
+
`data.currentRevision.id` to `chart`, `preview`, or `save`.
|
|
692
|
+
|
|
693
|
+
`preview` and `save` take the same JSON request file. The first supported edits are
|
|
694
|
+
explicit bounded bean-temperature or environmental-temperature adjustments over a time
|
|
695
|
+
interval in milliseconds. Each request supports at most 12 adjustments; intervals must
|
|
696
|
+
be ordered and each nonzero `delta` is bounded from -20 to 20. For example:
|
|
697
|
+
|
|
698
|
+
```json
|
|
699
|
+
{
|
|
700
|
+
"title": "Slightly later development",
|
|
701
|
+
"notes": "Small next-batch adjustment",
|
|
702
|
+
"changes": {
|
|
703
|
+
"temperatureAdjustments": [
|
|
704
|
+
{
|
|
705
|
+
"kind": "bean_temperature",
|
|
706
|
+
"startMilliseconds": 300000,
|
|
707
|
+
"endMilliseconds": 420000,
|
|
708
|
+
"delta": 3
|
|
709
|
+
}
|
|
710
|
+
]
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
Example flow:
|
|
716
|
+
|
|
717
|
+
Replace the sample UUIDs below with the profile and revision IDs returned by your commands.
|
|
718
|
+
|
|
719
|
+
```bash
|
|
720
|
+
purvey reference-profile import ~/artisan/ethiopia.alog --title "Ethiopia baseline" --pretty
|
|
721
|
+
purvey reference-profile get 5ea1af6f-234c-43a9-9bf8-5678dd24f854 --pretty
|
|
722
|
+
purvey reference-profile preview 5ea1af6f-234c-43a9-9bf8-5678dd24f854 8d2c41e0-7b9a-4f3e-a6d1-2c9e5f07b3a4 --request changes.json --pretty
|
|
723
|
+
purvey reference-profile save 5ea1af6f-234c-43a9-9bf8-5678dd24f854 8d2c41e0-7b9a-4f3e-a6d1-2c9e5f07b3a4 --request changes.json --pretty
|
|
724
|
+
purvey reference-profile export 0b7e9f52-3c61-4d8a-9e24-6f1a8c3d5b90 c43a1d7e-95b2-4e06-8f7c-1d2b3a4e5f68 --output ~/artisan/next-batch.alog
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
Writes generate a new idempotency key per invocation. Pass `--idempotency-key <key>` on
|
|
728
|
+
`import` or `save` and reuse that key to safely retry the same request. `export` requires a
|
|
729
|
+
saved generated revision, writes the unsigned `.alog` plan locally, and emits a JSON
|
|
730
|
+
receipt; it refuses to overwrite an existing file unless `--force` is passed. A generated
|
|
731
|
+
profile is never executed roast history, and this CLI does not claim verified Artisan 4.2
|
|
732
|
+
playback compatibility.
|
|
733
|
+
|
|
672
734
|
### sales
|
|
673
735
|
|
|
674
736
|
- `purvey sales list`
|
|
@@ -852,6 +914,21 @@ purvey roast watch --resume
|
|
|
852
914
|
|
|
853
915
|
Watch mode runs until Ctrl+C or SIGTERM. On shutdown it waits for active imports, commits queued batch-mode roasts, prints the verification summary, and leaves session state available for `--resume`.
|
|
854
916
|
|
|
917
|
+
### Plan an Artisan reference
|
|
918
|
+
|
|
919
|
+
Replace the sample UUIDs with IDs returned by your own import and save commands.
|
|
920
|
+
|
|
921
|
+
```bash
|
|
922
|
+
purvey reference-profile import ~/artisan/ethiopia.alog --title "Ethiopia baseline"
|
|
923
|
+
purvey reference-profile get 5ea1af6f-234c-43a9-9bf8-5678dd24f854 --pretty
|
|
924
|
+
purvey reference-profile preview 5ea1af6f-234c-43a9-9bf8-5678dd24f854 8d2c41e0-7b9a-4f3e-a6d1-2c9e5f07b3a4 --request changes.json --pretty
|
|
925
|
+
purvey reference-profile save 5ea1af6f-234c-43a9-9bf8-5678dd24f854 8d2c41e0-7b9a-4f3e-a6d1-2c9e5f07b3a4 --request changes.json
|
|
926
|
+
purvey reference-profile export 0b7e9f52-3c61-4d8a-9e24-6f1a8c3d5b90 c43a1d7e-95b2-4e06-8f7c-1d2b3a4e5f68 --output ~/artisan/next-batch.alog
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
Review the preview before saving. The export is an unsigned plan; Artisan 4.2 playback
|
|
930
|
+
compatibility has not yet been established.
|
|
931
|
+
|
|
855
932
|
### Export records for spreadsheets
|
|
856
933
|
|
|
857
934
|
```bash
|
|
@@ -878,13 +955,15 @@ Use the right ID for the right command.
|
|
|
878
955
|
- `roast_id`: `roast_data` rows; used by `roast get/delete`, `sales record --roast-id`, `roast list --roast-id`
|
|
879
956
|
- `sales record` also supports resolving a roast from `inventory id` plus `--batch-name`; because sales retain inventory + batch rather than roast ID, duplicate batch names on one inventory item are rejected
|
|
880
957
|
- `sale id`: `coffee_sales` rows; used by `sales update/delete`
|
|
958
|
+
- `reference_profile_id`: owner-scoped Studio profile UUID; used by `reference-profile get/chart/preview/save/export`
|
|
959
|
+
- `reference_revision_id`: immutable revision UUID; used by `reference-profile chart/preview/save/export`
|
|
881
960
|
|
|
882
961
|
## Environment variables
|
|
883
962
|
|
|
884
963
|
- `PURVEYORS_BASE_URL`: override the Purveyors web base URL
|
|
885
964
|
- `PURVEYORS_API_KEY`: explicit API-key override for canonical Parchment commands
|
|
886
965
|
- `PARCHMENT_API_KEY`: preferred API-key variable for SDK-backed Parchment commands; also accepted for API-backed proof and paid-tier similarity paths
|
|
887
|
-
- `PARCHMENT_API_BASE_URL`: override the SDK-backed Parchment API base URL, including `market`, `price-index`, `procurement`, and roast auto-classification requests
|
|
966
|
+
- `PARCHMENT_API_BASE_URL`: override the SDK-backed Parchment API base URL, including `market`, `price-index`, `procurement`, `reference-profile`, and roast auto-classification requests
|
|
888
967
|
- `PURVEY_DEBUG`: enable verbose error output
|
|
889
968
|
|
|
890
969
|
## For AI agents
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,mBAAmB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,mBAAmB,IAAI,OAAO,CAsD7C"}
|
package/dist/commands/context.js
CHANGED
|
@@ -12,6 +12,7 @@ Default output is the dense human-readable operator reference.
|
|
|
12
12
|
Preferred machine contract: \`purvey manifest\`.
|
|
13
13
|
Use --json or --pretty only when an existing \`purvey context\` caller needs manifest parity.
|
|
14
14
|
Use \`@purveyors/cli/manifest\` for the same contract inside Node.js or agent runtimes.
|
|
15
|
+
Studio reference workflows are listed under \`reference-profile\` in the manifest; they require Studio access.
|
|
15
16
|
|
|
16
17
|
Examples:
|
|
17
18
|
purvey context
|
|
@@ -20,6 +21,7 @@ Examples:
|
|
|
20
21
|
purvey context --pretty
|
|
21
22
|
purvey context --json > cli-manifest.json
|
|
22
23
|
purvey manifest
|
|
24
|
+
purvey reference-profile --help
|
|
23
25
|
`)
|
|
24
26
|
.action(withErrorHandling(async (opts, cmd) => {
|
|
25
27
|
const globalOpts = cmd.optsWithGlobals();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;SAC1B,WAAW,CACV,kGAAkG,CACnG;SACA,MAAM,CAAC,QAAQ,EAAE,6DAA6D,CAAC;SAC/E,MAAM,CAAC,UAAU,EAAE,8DAA8D,CAAC;SAClF,WAAW,CACV,OAAO,EACP
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;SAC1B,WAAW,CACV,kGAAkG,CACnG;SACA,MAAM,CAAC,QAAQ,EAAE,6DAA6D,CAAC;SAC/E,MAAM,CAAC,UAAU,EAAE,8DAA8D,CAAC;SAClF,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;CAeL,CACI;SACA,MAAM,CACL,iBAAiB,CAAC,KAAK,EAAE,IAA6B,EAAE,GAAY,EAAE,EAAE;QACtE,MAAM,UAAU,GAAG,GAAG,CAAC,eAAe,EAAmB,CAAC;QAC1D,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;QAClC,MAAM,SAAS,GACb,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YACpB,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YACxB,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAE7B,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACnB,MAAM,IAAI,UAAU,CAClB,kBAAkB,EAClB,4EAA4E,CAC7E,CAAC;QACJ,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,UAAU,CAAC,QAAQ,EAAE;gBACnB,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;aAC3D,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/commands/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,oBAAoB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/commands/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,oBAAoB,IAAI,OAAO,CAwC9C"}
|
|
@@ -10,12 +10,14 @@ export function buildManifestCommand() {
|
|
|
10
10
|
.addHelpText('after', `
|
|
11
11
|
Preferred machine-readable entrypoint for shells, scripts, and agents.
|
|
12
12
|
Use \`purvey context --json\` only for compatibility with existing context-based callers.
|
|
13
|
+
The \`reference-profile\` command group describes the SDK-backed Studio Artisan plan workflow.
|
|
13
14
|
|
|
14
15
|
Examples:
|
|
15
16
|
purvey manifest
|
|
16
17
|
purvey manifest --pretty
|
|
17
18
|
purvey manifest > cli-manifest.json
|
|
18
19
|
purvey manifest | jq '.commandGroups[].name'
|
|
20
|
+
purvey manifest | jq '.commandGroups[] | select(.name == "reference-profile")'
|
|
19
21
|
node --input-type=module -e "import { getCliManifest } from '@purveyors/cli/manifest'; console.log(JSON.stringify(getCliManifest()))"
|
|
20
22
|
`)
|
|
21
23
|
.action(withErrorHandling(async (opts, cmd) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/commands/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;SAC3B,WAAW,CACV,0FAA0F,CAC3F;SACA,MAAM,CAAC,QAAQ,EAAE,6CAA6C,CAAC;SAC/D,MAAM,CAAC,UAAU,EAAE,oCAAoC,CAAC;SACxD,WAAW,CACV,OAAO,EACP
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/commands/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;SAC3B,WAAW,CACV,0FAA0F,CAC3F;SACA,MAAM,CAAC,QAAQ,EAAE,6CAA6C,CAAC;SAC/D,MAAM,CAAC,UAAU,EAAE,oCAAoC,CAAC;SACxD,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;CAYL,CACI;SACA,MAAM,CACL,iBAAiB,CAAC,KAAK,EAAE,IAA6B,EAAE,GAAY,EAAE,EAAE;QACtE,MAAM,UAAU,GAAG,GAAG,CAAC,eAAe,EAAmB,CAAC;QAE1D,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACnB,MAAM,IAAI,UAAU,CAClB,kBAAkB,EAClB,sEAAsE,CACvE,CAAC;QACJ,CAAC;QAED,UAAU,CAAC,cAAc,EAAE,EAAE;YAC3B,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;SAC3D,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference-profile.d.ts","sourceRoot":"","sources":["../../src/commands/reference-profile.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0BpC,sFAAsF;AACtF,wBAAgB,4BAA4B,IAAI,OAAO,CAuPtD"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
2
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { PrvrsError, withErrorHandling } from '../lib/errors.js';
|
|
5
|
+
import { exportGeneratedReferenceProfile, getReferenceProfile, getReferenceProfileChart, importReferenceProfile, listReferenceProfiles, parseReferenceProfileImportRequest, previewReferenceProfile, readReferenceProfileGenerationRequest, REFERENCE_PROFILE_SOURCE_MAX_BYTES, saveGeneratedReferenceProfile, writeGeneratedReferenceFile, } from '../lib/reference-profiles.js';
|
|
6
|
+
import { normalizePathInput } from '../lib/path-input.js';
|
|
7
|
+
import { outputData } from '../lib/output.js';
|
|
8
|
+
function idempotencyKeyOption(command, description) {
|
|
9
|
+
return command.option('--idempotency-key <key>', `${description}; a new UUID is generated when omitted`);
|
|
10
|
+
}
|
|
11
|
+
/** `purvey reference-profile` — owner-scoped Studio plans through Parchment's SDK. */
|
|
12
|
+
export function buildReferenceProfileCommand() {
|
|
13
|
+
const referenceProfile = new Command('reference-profile').description('Preview, save, and export Studio Artisan reference plans through Parchment');
|
|
14
|
+
referenceProfile
|
|
15
|
+
.command('list')
|
|
16
|
+
.description('List your Studio reference profiles')
|
|
17
|
+
.option('--include-archived', 'Include archived reference profiles')
|
|
18
|
+
.addHelpText('after', `
|
|
19
|
+
Examples:
|
|
20
|
+
purvey reference-profile list --pretty
|
|
21
|
+
purvey reference-profile list --include-archived --json
|
|
22
|
+
|
|
23
|
+
Notes:
|
|
24
|
+
Requires a member credential and Studio access; entitlement is enforced by Parchment.`)
|
|
25
|
+
.action(withErrorHandling(async (opts, cmd) => {
|
|
26
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
27
|
+
const data = await listReferenceProfiles(Boolean(opts.includeArchived));
|
|
28
|
+
outputData(data, globalOpts);
|
|
29
|
+
}));
|
|
30
|
+
referenceProfile
|
|
31
|
+
.command('get <profile-id>')
|
|
32
|
+
.description('Get one reference profile and its current revision')
|
|
33
|
+
.addHelpText('after', `
|
|
34
|
+
Example:
|
|
35
|
+
purvey reference-profile get 5ea1af6f-234c-43a9-9bf8-5678dd24f854 --pretty
|
|
36
|
+
|
|
37
|
+
Use data.currentRevision.id as the revision id for chart, preview, and save.`)
|
|
38
|
+
.action(withErrorHandling(async (profileId, _opts, cmd) => {
|
|
39
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
40
|
+
const data = await getReferenceProfile(profileId);
|
|
41
|
+
outputData(data, globalOpts);
|
|
42
|
+
}));
|
|
43
|
+
referenceProfile
|
|
44
|
+
.command('chart <profile-id> <revision-id>')
|
|
45
|
+
.description('Get the typed Artisan chart for a reference revision')
|
|
46
|
+
.addHelpText('after', `
|
|
47
|
+
Example:
|
|
48
|
+
purvey reference-profile chart 5ea1af6f-234c-43a9-9bf8-5678dd24f854 8d2c41e0-7b9a-4f3e-a6d1-2c9e5f07b3a4 --pretty`)
|
|
49
|
+
.action(withErrorHandling(async (profileId, revisionId, _opts, cmd) => {
|
|
50
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
51
|
+
const data = await getReferenceProfileChart(profileId, revisionId);
|
|
52
|
+
outputData(data, globalOpts);
|
|
53
|
+
}));
|
|
54
|
+
const importCommand = referenceProfile
|
|
55
|
+
.command('import <file>')
|
|
56
|
+
.description('Upload an Artisan reference file as a private Studio profile')
|
|
57
|
+
.option('--title <text>', 'Title for the reference profile')
|
|
58
|
+
.option('--notes <text>', 'Notes about the reference profile')
|
|
59
|
+
.addHelpText('after', `
|
|
60
|
+
Examples:
|
|
61
|
+
purvey reference-profile import ~/artisan/ethiopia.alog --title "Ethiopia baseline" --pretty
|
|
62
|
+
purvey reference-profile import ~/artisan/ethiopia.alog --idempotency-key 3f6c2a1b-8e4d-4b7a-9c05-7e1f2d3a4b5c --json
|
|
63
|
+
|
|
64
|
+
Notes:
|
|
65
|
+
Parchment parses and retains the private source (up to 10,000,000 bytes); this command does not create roast history.
|
|
66
|
+
Reuse an explicit idempotency key to safely retry the same upload.`);
|
|
67
|
+
idempotencyKeyOption(importCommand, 'Stable key for safe retries');
|
|
68
|
+
importCommand.action(withErrorHandling(async (inputPath, opts, cmd) => {
|
|
69
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
70
|
+
const filePath = normalizePathInput(inputPath);
|
|
71
|
+
if (!filePath) {
|
|
72
|
+
throw new PrvrsError('INVALID_ARGUMENT', 'The Artisan reference file path cannot be blank.');
|
|
73
|
+
}
|
|
74
|
+
const fileInfo = await stat(filePath);
|
|
75
|
+
if (!fileInfo.isFile()) {
|
|
76
|
+
throw new PrvrsError('INVALID_ARGUMENT', 'The Artisan reference path must be a file.');
|
|
77
|
+
}
|
|
78
|
+
if (fileInfo.size === 0 || fileInfo.size > REFERENCE_PROFILE_SOURCE_MAX_BYTES) {
|
|
79
|
+
throw new PrvrsError('INVALID_ARGUMENT', `The Artisan reference must be between 1 and ${REFERENCE_PROFILE_SOURCE_MAX_BYTES} bytes.`);
|
|
80
|
+
}
|
|
81
|
+
const fileContent = await readFile(filePath, 'utf8');
|
|
82
|
+
const body = parseReferenceProfileImportRequest({
|
|
83
|
+
...(opts.title !== undefined ? { title: String(opts.title) } : {}),
|
|
84
|
+
...(opts.notes !== undefined ? { notes: String(opts.notes) } : {}),
|
|
85
|
+
fileName: basename(filePath),
|
|
86
|
+
fileContent,
|
|
87
|
+
fileSize: Buffer.byteLength(fileContent, 'utf8'),
|
|
88
|
+
});
|
|
89
|
+
const data = await importReferenceProfile(body, opts.idempotencyKey ? String(opts.idempotencyKey) : undefined);
|
|
90
|
+
outputData(data, globalOpts);
|
|
91
|
+
}));
|
|
92
|
+
const previewCommand = referenceProfile
|
|
93
|
+
.command('preview <profile-id> <revision-id>')
|
|
94
|
+
.description('Preview a bounded set of temperature adjustments without saving')
|
|
95
|
+
.requiredOption('--request <file>', 'JSON file with a title and bounded temperature adjustments')
|
|
96
|
+
.addHelpText('after', `
|
|
97
|
+
Example:
|
|
98
|
+
purvey reference-profile preview 5ea1af6f-234c-43a9-9bf8-5678dd24f854 8d2c41e0-7b9a-4f3e-a6d1-2c9e5f07b3a4 --request changes.json --pretty
|
|
99
|
+
|
|
100
|
+
The request file is also the exact body accepted by save. Parchment recalculates from the
|
|
101
|
+
immutable parent; preview never changes or stores the source.`);
|
|
102
|
+
previewCommand.action(withErrorHandling(async (profileId, revisionId, opts, cmd) => {
|
|
103
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
104
|
+
const request = await readReferenceProfileGenerationRequest(String(opts.request));
|
|
105
|
+
const data = await previewReferenceProfile(profileId, revisionId, request);
|
|
106
|
+
outputData(data, globalOpts);
|
|
107
|
+
}));
|
|
108
|
+
const saveCommand = referenceProfile
|
|
109
|
+
.command('save <profile-id> <revision-id>')
|
|
110
|
+
.description('Save the previewed changes as a new immutable generated reference')
|
|
111
|
+
.requiredOption('--request <file>', 'JSON file with a title and bounded temperature adjustments');
|
|
112
|
+
idempotencyKeyOption(saveCommand, 'Stable key for safe retries');
|
|
113
|
+
saveCommand.addHelpText('after', `
|
|
114
|
+
Example:
|
|
115
|
+
purvey reference-profile save 5ea1af6f-234c-43a9-9bf8-5678dd24f854 8d2c41e0-7b9a-4f3e-a6d1-2c9e5f07b3a4 --request changes.json --pretty
|
|
116
|
+
|
|
117
|
+
Notes:
|
|
118
|
+
Omit --idempotency-key to generate a new key for this call. Reuse an explicit key to replay a retry.
|
|
119
|
+
A generated reference is a plan, not executed roast history.`);
|
|
120
|
+
saveCommand.action(withErrorHandling(async (profileId, revisionId, opts, cmd) => {
|
|
121
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
122
|
+
const request = await readReferenceProfileGenerationRequest(String(opts.request));
|
|
123
|
+
const data = await saveGeneratedReferenceProfile(profileId, revisionId, request, opts.idempotencyKey ? String(opts.idempotencyKey) : undefined);
|
|
124
|
+
outputData(data, globalOpts);
|
|
125
|
+
}));
|
|
126
|
+
const exportCommand = referenceProfile
|
|
127
|
+
.command('export <profile-id> <revision-id>')
|
|
128
|
+
.description('Download a saved generated reference as an unsigned Artisan .alog plan')
|
|
129
|
+
.requiredOption('--output <file>', 'Destination for the generated .alog file')
|
|
130
|
+
.option('--force', 'Overwrite the destination file if it already exists')
|
|
131
|
+
.addHelpText('after', `
|
|
132
|
+
Example:
|
|
133
|
+
purvey reference-profile export 0b7e9f52-3c61-4d8a-9e24-6f1a8c3d5b90 c43a1d7e-95b2-4e06-8f7c-1d2b3a4e5f68 --output ~/artisan/next-batch.alog
|
|
134
|
+
|
|
135
|
+
Only a saved generated revision can be exported. Export writes the .alog file locally and
|
|
136
|
+
prints a JSON receipt; it does not claim verified Artisan 4.2 playback compatibility.`);
|
|
137
|
+
exportCommand.action(withErrorHandling(async (profileId, revisionId, opts, cmd) => {
|
|
138
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
139
|
+
const destination = normalizePathInput(String(opts.output ?? ''));
|
|
140
|
+
if (!destination) {
|
|
141
|
+
throw new PrvrsError('INVALID_ARGUMENT', 'The export destination path cannot be blank.');
|
|
142
|
+
}
|
|
143
|
+
const result = await exportGeneratedReferenceProfile(profileId, revisionId);
|
|
144
|
+
const outputFile = await writeGeneratedReferenceFile(result.data.fileContent, destination, Boolean(opts.force));
|
|
145
|
+
outputData({
|
|
146
|
+
data: {
|
|
147
|
+
profileId,
|
|
148
|
+
revisionId,
|
|
149
|
+
fileName: result.data.fileName,
|
|
150
|
+
fileSize: result.data.fileSize,
|
|
151
|
+
outputPath: outputFile,
|
|
152
|
+
},
|
|
153
|
+
}, globalOpts);
|
|
154
|
+
}));
|
|
155
|
+
return referenceProfile;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=reference-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference-profile.js","sourceRoot":"","sources":["../../src/commands/reference-profile.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/cherry.d.ts
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
1
|
/** Cherry roast classification through the canonical Parchment API. */
|
|
2
2
|
import type { CredentialContext } from './auth-client.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
title: string;
|
|
6
|
-
filename?: string;
|
|
7
|
-
roastertype?: string;
|
|
8
|
-
beans?: string;
|
|
9
|
-
roastingnotes?: string;
|
|
10
|
-
weight?: [number, number, string];
|
|
11
|
-
};
|
|
12
|
-
inventory: Array<{
|
|
13
|
-
id: number;
|
|
14
|
-
coffee_name: string;
|
|
15
|
-
origin?: string;
|
|
16
|
-
processing?: string;
|
|
17
|
-
}>;
|
|
18
|
-
}
|
|
3
|
+
import type { components } from '@purveyors/sdk';
|
|
4
|
+
export type ClassifyRoastInput = components['schemas']['RoastClassificationRequest'];
|
|
19
5
|
export interface ClassifyRoastResult {
|
|
20
6
|
match: {
|
|
21
7
|
inventoryId: number;
|
package/dist/lib/cherry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cherry.d.ts","sourceRoot":"","sources":["../../src/lib/cherry.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"cherry.d.ts","sourceRoot":"","sources":["../../src/lib/cherry.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAKjD,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,4BAA4B,CAAC,CAAC;AAErF,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE;QACL,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;CACV;AAED,qFAAqF;AACrF,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE;QACJ,UAAU,IAAI,OAAO,CAAC;YACpB,IAAI,EAAE;gBAAE,OAAO,EAAE;oBAAE,YAAY,EAAE,MAAM,CAAA;iBAAE,GAAG,IAAI,CAAA;aAAE,CAAC;SACpD,CAAC,CAAC;KACJ,CAAC;CACH;AAwHD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,iBAAiB,EAAE,iBAAiB,GAAG,wBAAwB,EAC/D,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAiB9B"}
|
package/dist/lib/cherry.js
CHANGED
|
@@ -27,11 +27,6 @@ function normalizeWeight(value) {
|
|
|
27
27
|
return [input, output, unit];
|
|
28
28
|
}
|
|
29
29
|
function normalizeClassificationInput(input) {
|
|
30
|
-
const filename = normalizeOptionalString(input.alogMetadata.filename, CLASSIFICATION_STRING_LIMIT);
|
|
31
|
-
const title = normalizeOptionalString(input.alogMetadata.title, CLASSIFICATION_STRING_LIMIT) ?? filename;
|
|
32
|
-
if (!title) {
|
|
33
|
-
throw new Error('Invalid roast classification input: alogMetadata.title and filename cannot both be blank.');
|
|
34
|
-
}
|
|
35
30
|
const inventory = input.inventory.slice(0, CLASSIFICATION_INVENTORY_LIMIT).map((item, index) => {
|
|
36
31
|
if (!Number.isInteger(item.id) || item.id <= 0) {
|
|
37
32
|
throw new Error(`Invalid roast classification input: inventory[${index}].id must be a positive integer.`);
|
|
@@ -44,6 +39,25 @@ function normalizeClassificationInput(input) {
|
|
|
44
39
|
processing: normalizeOptionalString(item.processing, CLASSIFICATION_STRING_LIMIT),
|
|
45
40
|
};
|
|
46
41
|
});
|
|
42
|
+
if ('artisanSource' in input) {
|
|
43
|
+
const fileName = normalizeOptionalString(input.artisanSource.fileName, CLASSIFICATION_STRING_LIMIT);
|
|
44
|
+
if (!fileName) {
|
|
45
|
+
throw new Error('Invalid roast classification input: artisanSource.fileName cannot be blank.');
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
artisanSource: {
|
|
49
|
+
fileName,
|
|
50
|
+
// Source content is integrity-sensitive. Never trim or rewrite it client-side.
|
|
51
|
+
fileContent: input.artisanSource.fileContent,
|
|
52
|
+
},
|
|
53
|
+
inventory,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const filename = normalizeOptionalString(input.alogMetadata.filename, CLASSIFICATION_STRING_LIMIT);
|
|
57
|
+
const title = normalizeOptionalString(input.alogMetadata.title, CLASSIFICATION_STRING_LIMIT) ?? filename;
|
|
58
|
+
if (!title) {
|
|
59
|
+
throw new Error('Invalid roast classification input: alogMetadata.title and filename cannot both be blank.');
|
|
60
|
+
}
|
|
47
61
|
return {
|
|
48
62
|
alogMetadata: {
|
|
49
63
|
title,
|
package/dist/lib/cherry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cherry.js","sourceRoot":"","sources":["../../src/lib/cherry.ts"],"names":[],"mappings":"AAAA,uEAAuE;
|
|
1
|
+
{"version":3,"file":"cherry.js","sourceRoot":"","sources":["../../src/lib/cherry.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,6 @@ import { watch } from 'fs';
|
|
|
9
9
|
import { readFile, access } from 'fs/promises';
|
|
10
10
|
import type { CredentialContext } from '../auth-client.js';
|
|
11
11
|
import type { ImportRoastResult } from '../roast.js';
|
|
12
|
-
import type { MilestoneData, ProcessedRoastData } from '../artisan/types.js';
|
|
13
12
|
import { listInventory } from '../inventory.js';
|
|
14
13
|
/**
|
|
15
14
|
* Arguments for a single watched roast import. Identity is resolved by the
|
|
@@ -52,8 +51,8 @@ export interface ImportRecord {
|
|
|
52
51
|
batchName: string;
|
|
53
52
|
status: 'pending' | 'success' | 'failed' | 'needs-review';
|
|
54
53
|
error?: string;
|
|
55
|
-
milestones?:
|
|
56
|
-
phases?:
|
|
54
|
+
milestones?: ImportRoastResult['milestones'];
|
|
55
|
+
phases?: ImportRoastResult['phases'];
|
|
57
56
|
importedAt: string;
|
|
58
57
|
selectedCoffeeId?: number;
|
|
59
58
|
selectedCoffeeName?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/lib/interactive/watch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAkB,MAAM,IAAI,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAoB,MAAM,aAAa,CAAC;AAGjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/lib/interactive/watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -708,25 +708,6 @@ function uniqueSupplierMatch(filename, inventory) {
|
|
|
708
708
|
* Returns skip=true if confidence < 50 or if the AI call fails.
|
|
709
709
|
*/
|
|
710
710
|
async function runAutoMatch(credentialContext, userId, filename, fileContent, inventoryLister, sessionTokenProvider) {
|
|
711
|
-
// Parse alog metadata without full import
|
|
712
|
-
let alogMetadata;
|
|
713
|
-
try {
|
|
714
|
-
const { processAlogFile } = await import('../artisan/parser.js');
|
|
715
|
-
const parsed = processAlogFile(fileContent);
|
|
716
|
-
alogMetadata = {
|
|
717
|
-
title: typeof parsed.title === 'string' ? parsed.title : filename,
|
|
718
|
-
roastertype: typeof parsed.roastertype === 'string' ? parsed.roastertype : undefined,
|
|
719
|
-
beans: typeof parsed.beans === 'string' ? parsed.beans : undefined,
|
|
720
|
-
roastingnotes: typeof parsed.roastingnotes === 'string' ? parsed.roastingnotes : undefined,
|
|
721
|
-
weight: Array.isArray(parsed.weight)
|
|
722
|
-
? parsed.weight
|
|
723
|
-
: undefined,
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
catch {
|
|
727
|
-
// If we can't parse the file, fall back to filename as title
|
|
728
|
-
alogMetadata = { title: filename };
|
|
729
|
-
}
|
|
730
711
|
// Fetch the user's stocked inventory
|
|
731
712
|
let inventory = [];
|
|
732
713
|
try {
|
|
@@ -773,14 +754,11 @@ async function runAutoMatch(credentialContext, userId, filename, fileContent, in
|
|
|
773
754
|
// Call the AI classifier
|
|
774
755
|
try {
|
|
775
756
|
const { classifyRoast } = await import('../cherry.js');
|
|
776
|
-
// Always include the filename — it often contains the bean name
|
|
777
|
-
// even when the .alog XML title is generic (e.g. "Roaster Scope")
|
|
778
|
-
const enrichedMetadata = {
|
|
779
|
-
...alogMetadata,
|
|
780
|
-
filename,
|
|
781
|
-
};
|
|
782
757
|
const result = await classifyRoast(credentialContext, {
|
|
783
|
-
|
|
758
|
+
artisanSource: {
|
|
759
|
+
fileName: filename,
|
|
760
|
+
fileContent,
|
|
761
|
+
},
|
|
784
762
|
inventory,
|
|
785
763
|
});
|
|
786
764
|
if (!result.match) {
|