@eigenpal/cli 0.17.4 → 0.18.0

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.
@@ -504,6 +504,7 @@ Extract text from documents (PDF, DOCX, images) using native extraction, OCR, or
504
504
  | `nativeText` | boolean | no | `false` | Extract native/embedded text from PDFs without OCR/VLM. Faster and uses no credits. Falls back to OCR/VLM if the PDF has no embedded text. |
505
505
  | `describeFigures` | boolean | no | | Opt-in (default off). After text extraction, detect which pages contain figures with an in-worker layout model, then caption those pages with a vision model and append `<figure>description</figure>` to their text — so image-only pages (property photos, signatures, charts) become findable by text-based steps like ai.split. Note: the layout scan runs over all pages, and the caption step and its vision calls are billed. Skipped for plaintext. |
506
506
  | `figureInstructions` | string | no | | Custom instruction for the figure-description pass, e.g. "Describe each figure; label a handwritten signature as `<figure>signature</figure>` and a stamp as `<figure>stamp</figure>`; for property photos note the room or exterior shown." Applied only when describeFigures runs. |
507
+ | `cache` | boolean | no | `false` | When true, reuse a prior parse for identical file bytes and parse settings. Skips OCR/vision on cache hit. Stored in tenant blob storage with no automatic expiry (TTL/lifecycle is a follow-up). Default off. |
507
508
 
508
509
  **Output:** `object`
509
510
 
@@ -643,6 +644,11 @@ Config schema:
643
644
  "figureInstructions": {
644
645
  "description": "Custom instruction for the figure-description pass, e.g. \"Describe each figure; label a handwritten signature as `<figure>signature</figure>` and a stamp as `<figure>stamp</figure>`; for property photos note the room or exterior shown.\" Applied only when describeFigures runs.",
645
646
  "type": "string"
647
+ },
648
+ "cache": {
649
+ "description": "When true, reuse a prior parse for identical file bytes and parse settings. Skips OCR/vision on cache hit. Stored in tenant blob storage with no automatic expiry (TTL/lifecycle is a follow-up). Default off.",
650
+ "default": false,
651
+ "type": "boolean"
646
652
  }
647
653
  },
648
654
  "required": [
@@ -698,6 +704,9 @@ Output schema:
698
704
  "type": "integer",
699
705
  "minimum": 0,
700
706
  "maximum": 9007199254740991
707
+ },
708
+ "cached": {
709
+ "type": "boolean"
701
710
  }
702
711
  },
703
712
  "required": [
@@ -3152,6 +3161,217 @@ Output schema:
3152
3161
  ```
3153
3162
 
3154
3163
 
3164
+ #### `ai.figure-crops` — Figure Crops
3165
+
3166
+ Crop and caption figure elements from a parsed PDF. Renders the source document, crops each kind=figure bbox from ai.parse output, and describes the crop with a vision model. Output is captions plus normalized bboxes for evidence viewers.
3167
+
3168
+ **Behavior and examples:** `eigenpal docs read steps/ai/figure-crops`
3169
+
3170
+ **Durable retry:** Provider request retries are separate; the workflow engine does not durably retry this step.
3171
+
3172
+ **Config** (in `step.with`):
3173
+
3174
+ | Field | Type | Required | Default | Description |
3175
+ | --- | --- | --- | --- | --- |
3176
+ | `input` | string | yes | | Storage reference or template expression for the source PDF |
3177
+ | `parseOutput` | unknown | yes | | ai.parse output object (template {{steps.<parse>.output}}); figure elements are read from its `elements` array |
3178
+ | `model` | string | no | | Vision model for captions (defaults to workspace model) |
3179
+ | `figureInstructions` | string | no | | Custom caption instruction; applied per figure crop |
3180
+ | `maxFigures` | integer | no | `40` | Cap on figures processed per document |
3181
+ | `minAreaFrac` | number | no | `0` | Skip figures below this page-area fraction (logos/decorations) |
3182
+ | `includeCrops` | boolean | no | `false` | Include base64 JPEG crops in output (heavy; default off — captions + bboxes only) |
3183
+ | `renderScale` | number | no | `1` | Scale factor for rendering PDF pages before cropping |
3184
+ | `imageQuality` | integer | no | `85` | JPEG quality for crops |
3185
+ | `llmReasoningEffort` | `"none"` \| `"minimal"` \| `"low"` \| `"medium"` \| `"high"` \| `"xhigh"` \| `"max"` | no | | Reasoning effort for models that support it. Omit to use the selected model's default. |
3186
+
3187
+ **Output:** `object`
3188
+
3189
+ | Field | Type | Required | Default | Description |
3190
+ | --- | --- | --- | --- | --- |
3191
+ | `figures` | array<object> | yes | | |
3192
+ | `_figureCrops` | object | yes | | |
3193
+
3194
+ ##### Complete machine-readable schemas
3195
+
3196
+ Config schema:
3197
+
3198
+ ```json
3199
+ {
3200
+ "$schema": "http://json-schema.org/draft-07/schema#",
3201
+ "type": "object",
3202
+ "properties": {
3203
+ "input": {
3204
+ "type": "string",
3205
+ "description": "Storage reference or template expression for the source PDF"
3206
+ },
3207
+ "parseOutput": {
3208
+ "description": "ai.parse output object (template {{steps.<parse>.output}}); figure elements are read from its `elements` array"
3209
+ },
3210
+ "model": {
3211
+ "description": "Vision model for captions (defaults to workspace model)",
3212
+ "type": "string"
3213
+ },
3214
+ "figureInstructions": {
3215
+ "description": "Custom caption instruction; applied per figure crop",
3216
+ "type": "string"
3217
+ },
3218
+ "maxFigures": {
3219
+ "description": "Cap on figures processed per document",
3220
+ "default": 40,
3221
+ "type": "integer",
3222
+ "minimum": 1,
3223
+ "maximum": 100
3224
+ },
3225
+ "minAreaFrac": {
3226
+ "description": "Skip figures below this page-area fraction (logos/decorations)",
3227
+ "default": 0,
3228
+ "type": "number",
3229
+ "minimum": 0,
3230
+ "maximum": 1
3231
+ },
3232
+ "includeCrops": {
3233
+ "description": "Include base64 JPEG crops in output (heavy; default off — captions + bboxes only)",
3234
+ "default": false,
3235
+ "type": "boolean"
3236
+ },
3237
+ "renderScale": {
3238
+ "description": "Scale factor for rendering PDF pages before cropping",
3239
+ "default": 1,
3240
+ "type": "number",
3241
+ "minimum": 1,
3242
+ "maximum": 4
3243
+ },
3244
+ "imageQuality": {
3245
+ "description": "JPEG quality for crops",
3246
+ "default": 85,
3247
+ "type": "integer",
3248
+ "minimum": 1,
3249
+ "maximum": 100
3250
+ },
3251
+ "llmReasoningEffort": {
3252
+ "description": "Reasoning effort for models that support it. Omit to use the selected model's default.",
3253
+ "type": "string",
3254
+ "enum": [
3255
+ "none",
3256
+ "minimal",
3257
+ "low",
3258
+ "medium",
3259
+ "high",
3260
+ "xhigh",
3261
+ "max"
3262
+ ]
3263
+ }
3264
+ },
3265
+ "required": [
3266
+ "input",
3267
+ "parseOutput"
3268
+ ],
3269
+ "additionalProperties": false
3270
+ }
3271
+ ```
3272
+
3273
+
3274
+ Output schema:
3275
+
3276
+ ```json
3277
+ {
3278
+ "$schema": "http://json-schema.org/draft-07/schema#",
3279
+ "type": "object",
3280
+ "properties": {
3281
+ "figures": {
3282
+ "type": "array",
3283
+ "items": {
3284
+ "type": "object",
3285
+ "properties": {
3286
+ "id": {
3287
+ "type": "string"
3288
+ },
3289
+ "page": {
3290
+ "type": "number"
3291
+ },
3292
+ "bboxNorm": {
3293
+ "anyOf": [
3294
+ {
3295
+ "type": "array",
3296
+ "items": [
3297
+ {
3298
+ "type": "number"
3299
+ },
3300
+ {
3301
+ "type": "number"
3302
+ },
3303
+ {
3304
+ "type": "number"
3305
+ },
3306
+ {
3307
+ "type": "number"
3308
+ }
3309
+ ]
3310
+ },
3311
+ {
3312
+ "type": "null"
3313
+ }
3314
+ ]
3315
+ },
3316
+ "areaFrac": {
3317
+ "type": "number"
3318
+ },
3319
+ "caption": {
3320
+ "anyOf": [
3321
+ {
3322
+ "type": "string"
3323
+ },
3324
+ {
3325
+ "type": "null"
3326
+ }
3327
+ ]
3328
+ },
3329
+ "cropJpegBase64": {
3330
+ "type": "string"
3331
+ }
3332
+ },
3333
+ "required": [
3334
+ "id",
3335
+ "page",
3336
+ "bboxNorm",
3337
+ "areaFrac",
3338
+ "caption"
3339
+ ],
3340
+ "additionalProperties": false
3341
+ }
3342
+ },
3343
+ "_figureCrops": {
3344
+ "type": "object",
3345
+ "properties": {
3346
+ "pages": {
3347
+ "type": "array",
3348
+ "items": {
3349
+ "type": "number"
3350
+ }
3351
+ },
3352
+ "model": {
3353
+ "type": "string"
3354
+ },
3355
+ "skippedSmall": {
3356
+ "type": "number"
3357
+ }
3358
+ },
3359
+ "required": [
3360
+ "pages",
3361
+ "skippedSmall"
3362
+ ],
3363
+ "additionalProperties": false
3364
+ }
3365
+ },
3366
+ "required": [
3367
+ "figures",
3368
+ "_figureCrops"
3369
+ ],
3370
+ "additionalProperties": false
3371
+ }
3372
+ ```
3373
+
3374
+
3155
3375
  ### Transform steps — deterministic data transforms
3156
3376
 
3157
3377
  #### `transform.set` — Set Value
@@ -3768,6 +3988,262 @@ Output schema:
3768
3988
  ```
3769
3989
 
3770
3990
 
3991
+ #### `transform.crop-regions` — Crop Regions
3992
+
3993
+ Render a PDF or image and crop normalized bounding boxes into JPEG run output artifacts. Pair with transform.script (bbox lists from ai.parse layout) and ai.extract or ai.vision for captions.
3994
+
3995
+ **Behavior and examples:** `eigenpal docs read steps/transform/crop-regions`
3996
+
3997
+ **Durable retry:** Transforms, including those that write files, are not durably retried.
3998
+
3999
+ **Config** (in `step.with`):
4000
+
4001
+ | Field | Type | Required | Default | Description |
4002
+ | --- | --- | --- | --- | --- |
4003
+ | `input` | string | yes | | File input — template expression e.g. {{ input.document }} resolving to a PDF or image |
4004
+ | `regions` | string \| array<object> | yes | | Regions to crop — pageIndex + normalized bbox per entry |
4005
+ | `renderScale` | number | no | `1` | Scale factor when rasterizing PDF pages before cropping |
4006
+ | `imageQuality` | integer | no | `85` | JPEG quality for cropped outputs |
4007
+ | `paddingFrac` | number | no | `0.02` | Padding around each bbox as a fraction of the shorter page edge |
4008
+ | `minCropPx` | integer | no | `8` | Minimum crop width/height in pixels; smaller crops fall back to the full page |
4009
+ | `maxRegions` | integer | no | `100` | Maximum regions processed per invocation |
4010
+
4011
+ **Output:** `object`
4012
+
4013
+ | Field | Type | Required | Default | Description |
4014
+ | --- | --- | --- | --- | --- |
4015
+ | `regions` | array<object> | yes | | Successfully cropped regions |
4016
+ | `skipped` | integer | no | | Regions skipped (invalid bbox or missing page) |
4017
+
4018
+ ##### Complete machine-readable schemas
4019
+
4020
+ Config schema:
4021
+
4022
+ ```json
4023
+ {
4024
+ "$schema": "http://json-schema.org/draft-07/schema#",
4025
+ "type": "object",
4026
+ "properties": {
4027
+ "input": {
4028
+ "type": "string",
4029
+ "description": "File input — template expression e.g. {{ input.document }} resolving to a PDF or image"
4030
+ },
4031
+ "regions": {
4032
+ "anyOf": [
4033
+ {
4034
+ "type": "string",
4035
+ "minLength": 1,
4036
+ "description": "Template expression resolving to a region array, e.g. {{ steps.list-figures.output.regions }}"
4037
+ },
4038
+ {
4039
+ "minItems": 1,
4040
+ "type": "array",
4041
+ "items": {
4042
+ "type": "object",
4043
+ "properties": {
4044
+ "id": {
4045
+ "description": "Stable region id used in output and crop filenames (defaults to region-N)",
4046
+ "type": "string"
4047
+ },
4048
+ "pageIndex": {
4049
+ "description": "0-based page index to crop from (images use page 0)",
4050
+ "default": 0,
4051
+ "type": "integer",
4052
+ "minimum": 0,
4053
+ "maximum": 9007199254740991
4054
+ },
4055
+ "bbox": {
4056
+ "type": "array",
4057
+ "items": [
4058
+ {
4059
+ "type": "number",
4060
+ "minimum": 0,
4061
+ "maximum": 1
4062
+ },
4063
+ {
4064
+ "type": "number",
4065
+ "minimum": 0,
4066
+ "maximum": 1
4067
+ },
4068
+ {
4069
+ "type": "number",
4070
+ "minimum": 0,
4071
+ "maximum": 1
4072
+ },
4073
+ {
4074
+ "type": "number",
4075
+ "minimum": 0,
4076
+ "maximum": 1
4077
+ }
4078
+ ],
4079
+ "description": "Normalized axis-aligned bbox [x0, y0, x1, y1]"
4080
+ }
4081
+ },
4082
+ "required": [
4083
+ "bbox"
4084
+ ],
4085
+ "additionalProperties": false
4086
+ },
4087
+ "description": "Regions to crop from the rendered document"
4088
+ }
4089
+ ],
4090
+ "description": "Regions to crop — pageIndex + normalized bbox per entry"
4091
+ },
4092
+ "renderScale": {
4093
+ "description": "Scale factor when rasterizing PDF pages before cropping",
4094
+ "default": 1,
4095
+ "type": "number",
4096
+ "minimum": 0.5,
4097
+ "maximum": 4
4098
+ },
4099
+ "imageQuality": {
4100
+ "description": "JPEG quality for cropped outputs",
4101
+ "default": 85,
4102
+ "type": "integer",
4103
+ "minimum": 1,
4104
+ "maximum": 100
4105
+ },
4106
+ "paddingFrac": {
4107
+ "description": "Padding around each bbox as a fraction of the shorter page edge",
4108
+ "default": 0.02,
4109
+ "type": "number",
4110
+ "minimum": 0,
4111
+ "maximum": 0.2
4112
+ },
4113
+ "minCropPx": {
4114
+ "description": "Minimum crop width/height in pixels; smaller crops fall back to the full page",
4115
+ "default": 8,
4116
+ "type": "integer",
4117
+ "minimum": 1,
4118
+ "maximum": 9007199254740991
4119
+ },
4120
+ "maxRegions": {
4121
+ "description": "Maximum regions processed per invocation",
4122
+ "default": 100,
4123
+ "type": "integer",
4124
+ "minimum": 1,
4125
+ "maximum": 200
4126
+ }
4127
+ },
4128
+ "required": [
4129
+ "input",
4130
+ "regions"
4131
+ ],
4132
+ "additionalProperties": false
4133
+ }
4134
+ ```
4135
+
4136
+
4137
+ Output schema:
4138
+
4139
+ ```json
4140
+ {
4141
+ "$schema": "http://json-schema.org/draft-07/schema#",
4142
+ "type": "object",
4143
+ "properties": {
4144
+ "regions": {
4145
+ "type": "array",
4146
+ "items": {
4147
+ "type": "object",
4148
+ "properties": {
4149
+ "id": {
4150
+ "type": "string",
4151
+ "description": "Region id (from input or auto-generated)"
4152
+ },
4153
+ "pageIndex": {
4154
+ "type": "integer",
4155
+ "minimum": 0,
4156
+ "maximum": 9007199254740991,
4157
+ "description": "0-based page index the crop was taken from"
4158
+ },
4159
+ "bbox": {
4160
+ "type": "array",
4161
+ "items": [
4162
+ {
4163
+ "type": "number",
4164
+ "minimum": 0,
4165
+ "maximum": 1
4166
+ },
4167
+ {
4168
+ "type": "number",
4169
+ "minimum": 0,
4170
+ "maximum": 1
4171
+ },
4172
+ {
4173
+ "type": "number",
4174
+ "minimum": 0,
4175
+ "maximum": 1
4176
+ },
4177
+ {
4178
+ "type": "number",
4179
+ "minimum": 0,
4180
+ "maximum": 1
4181
+ }
4182
+ ],
4183
+ "description": "Normalized bbox that was cropped"
4184
+ },
4185
+ "width": {
4186
+ "type": "integer",
4187
+ "minimum": 1,
4188
+ "maximum": 9007199254740991,
4189
+ "description": "Crop width in pixels"
4190
+ },
4191
+ "height": {
4192
+ "type": "integer",
4193
+ "minimum": 1,
4194
+ "maximum": 9007199254740991,
4195
+ "description": "Crop height in pixels"
4196
+ },
4197
+ "fileId": {
4198
+ "type": "string",
4199
+ "description": "Run output file id for the JPEG crop"
4200
+ },
4201
+ "filename": {
4202
+ "type": "string",
4203
+ "description": "Stored crop filename"
4204
+ },
4205
+ "mimeType": {
4206
+ "type": "string",
4207
+ "const": "image/jpeg",
4208
+ "description": "Always image/jpeg"
4209
+ },
4210
+ "size": {
4211
+ "type": "integer",
4212
+ "minimum": 0,
4213
+ "maximum": 9007199254740991,
4214
+ "description": "JPEG size in bytes"
4215
+ }
4216
+ },
4217
+ "required": [
4218
+ "id",
4219
+ "pageIndex",
4220
+ "bbox",
4221
+ "width",
4222
+ "height",
4223
+ "fileId",
4224
+ "filename",
4225
+ "mimeType",
4226
+ "size"
4227
+ ],
4228
+ "additionalProperties": false
4229
+ },
4230
+ "description": "Successfully cropped regions"
4231
+ },
4232
+ "skipped": {
4233
+ "description": "Regions skipped (invalid bbox or missing page)",
4234
+ "type": "integer",
4235
+ "minimum": 0,
4236
+ "maximum": 9007199254740991
4237
+ }
4238
+ },
4239
+ "required": [
4240
+ "regions"
4241
+ ],
4242
+ "additionalProperties": false
4243
+ }
4244
+ ```
4245
+
4246
+
3771
4247
  #### `transform.xlsx-to-json` — Spreadsheet to JSON
3772
4248
 
3773
4249
  Convert an XLS or XLSX spreadsheet to a JSON array of row objects. Supports headerless files, named or positional columns, displayed text, and a single rectangular range.
@@ -1009,7 +1009,8 @@ This JSON Schema is generated from the same Zod schema used to parse workflow YA
1009
1009
  "ai.classify",
1010
1010
  "ai.classify-pages",
1011
1011
  "ai.vision",
1012
- "ai.search-files"
1012
+ "ai.search-files",
1013
+ "ai.figure-crops"
1013
1014
  ]
1014
1015
  },
1015
1016
  "name": {
@@ -1113,6 +1114,7 @@ This JSON Schema is generated from the same Zod schema used to parse workflow YA
1113
1114
  "transform.merge",
1114
1115
  "transform.template",
1115
1116
  "transform.pdf-embed",
1117
+ "transform.crop-regions",
1116
1118
  "transform.xlsx-to-json",
1117
1119
  "transform.json-to-xlsx",
1118
1120
  "transform.script",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eigenpal/cli",
3
- "version": "0.17.4",
3
+ "version": "0.18.0",
4
4
  "description": "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
5
5
  "keywords": [
6
6
  "eigenpal",