@eigenpal/cli 0.0.1 → 0.4.2
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/CHANGELOG.md +441 -0
- package/LICENSE +201 -0
- package/README.md +60 -2
- package/dist/cli.js +162295 -0
- package/dist/skill/SKILL.md +366 -0
- package/dist/skill/examples/hello-world/dataset/examples/sample/expected/output.json +4 -0
- package/dist/skill/examples/hello-world/dataset/examples/sample/input/arguments.json +3 -0
- package/dist/skill/examples/hello-world/evaluators.yaml +5 -0
- package/dist/skill/examples/hello-world/workflow.yaml +28 -0
- package/dist/skill/reference/cli/agent.md +7 -0
- package/dist/skill/reference/cli/auth.md +75 -0
- package/dist/skill/reference/cli/completion.md +13 -0
- package/dist/skill/reference/cli/init.md +63 -0
- package/dist/skill/reference/cli/skill.md +79 -0
- package/dist/skill/reference/cli/status.md +14 -0
- package/dist/skill/reference/cli/workflow.md +788 -0
- package/dist/skill/reference/dataset-format.md +251 -0
- package/dist/skill/reference/debugging.md +280 -0
- package/dist/skill/reference/evaluators.md +210 -0
- package/dist/skill/reference/step-exec.md +164 -0
- package/dist/skill/reference/step-types.md +519 -0
- package/dist/skill/reference/workflow-yaml.md +304 -0
- package/dist/templates/blank/README.md +22 -0
- package/dist/templates/blank/dataset/examples/sample/expected/output.json +4 -0
- package/dist/templates/blank/dataset/examples/sample/input/arguments.json +3 -0
- package/dist/templates/blank/evaluators.yaml +9 -0
- package/dist/templates/blank/workflow.yaml +39 -0
- package/dist/templates/pdf-extraction/README.md +20 -0
- package/dist/templates/pdf-extraction/dataset/examples/sample-invoice/README.md +5 -0
- package/dist/templates/pdf-extraction/dataset/examples/sample-invoice/expected/output.json +6 -0
- package/dist/templates/pdf-extraction/dataset/examples/sample-invoice/input/arguments.json +1 -0
- package/dist/templates/pdf-extraction/evaluators.yaml +5 -0
- package/dist/templates/pdf-extraction/workflow.yaml +38 -0
- package/dist/templates/text-classification/README.md +8 -0
- package/dist/templates/text-classification/dataset/examples/negative/expected/output.json +3 -0
- package/dist/templates/text-classification/dataset/examples/negative/input/arguments.json +3 -0
- package/dist/templates/text-classification/dataset/examples/positive/expected/output.json +3 -0
- package/dist/templates/text-classification/dataset/examples/positive/input/arguments.json +3 -0
- package/dist/templates/text-classification/evaluators.yaml +6 -0
- package/dist/templates/text-classification/workflow.yaml +35 -0
- package/package.json +60 -15
- package/index.js +0 -4
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# workflow.yaml — required schema
|
|
2
|
+
|
|
3
|
+
A workflow is a DAG of named steps with named inputs, named outputs, and
|
|
4
|
+
trigger metadata. The full Zod schema lives in
|
|
5
|
+
`@eigenpal/types/src/workflow/` and ships with the CLI — query the
|
|
6
|
+
authoritative shape per step type with:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
eigenpal workflow step-type list # all step types
|
|
10
|
+
eigenpal workflow step-type get <type> # JSON Schema for one type's config + output
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Top-level required fields
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
name: extract-invoices # string, lowercase kebab/snake-case, unique within tenant
|
|
17
|
+
version: 1.0.0 # bare semver `MAJOR.MINOR.PATCH`, no leading `v`
|
|
18
|
+
description: Parse a PDF and extract invoice fields. # string, optional
|
|
19
|
+
triggerMethods: [api] # array, ≥1 entry from: api | cron | email
|
|
20
|
+
inputs: [...] # array of input definitions (see below)
|
|
21
|
+
steps: [...] # array of steps, executed in topological order
|
|
22
|
+
output: {...} # object — the workflow's return shape
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`name` + `version` together identify the version row. Pushing a new
|
|
26
|
+
version with the same `name` and a different `version` appends to history;
|
|
27
|
+
re-using the same `version` is rejected.
|
|
28
|
+
|
|
29
|
+
### `triggerMethods`
|
|
30
|
+
|
|
31
|
+
Required. Each entry adds an invocation surface:
|
|
32
|
+
|
|
33
|
+
- `api` — the workflow can be called via REST or the CLI's `workflow execution run`
|
|
34
|
+
- `cron` — scheduled. Add a sibling `cron: { schedule: "0 9 * * *", timezone: "UTC" }`
|
|
35
|
+
- `email` — inbound email. Add a sibling `email: { subject?: ..., aliases?: [...] }`
|
|
36
|
+
|
|
37
|
+
If `api` is missing, `eigenpal workflow execution run` and `workflow run` reject with a
|
|
38
|
+
403 / "Workflow does not have API trigger enabled."
|
|
39
|
+
|
|
40
|
+
### `inputs`
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
inputs:
|
|
44
|
+
- name: document # required — becomes a key on triggerInput
|
|
45
|
+
type: file # one of: string | number | boolean | object | file
|
|
46
|
+
file: true # required when type=file (legacy duplicate of `type: file`)
|
|
47
|
+
description: PDF or image to extract from
|
|
48
|
+
required: true # default true; pass false for optional inputs
|
|
49
|
+
|
|
50
|
+
- name: language
|
|
51
|
+
type: string
|
|
52
|
+
description: Language hint
|
|
53
|
+
default: auto
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Per input:
|
|
57
|
+
|
|
58
|
+
- `name` — `[a-z0-9][a-z0-9-_]*`
|
|
59
|
+
- `type` — `string` | `number` | `boolean` | `object` | `array` | `file`
|
|
60
|
+
- `file: true` for binary inputs (PDF, DOCX, image). The CLI uploads,
|
|
61
|
+
then references via `{{ input.<name> }}` which resolves to a
|
|
62
|
+
`FilePathDescriptor` the worker reads.
|
|
63
|
+
- `default` — used when the input is omitted at runtime
|
|
64
|
+
- `description` — surfaced in the dashboard + agent tools
|
|
65
|
+
|
|
66
|
+
#### File input shape — single vs array
|
|
67
|
+
|
|
68
|
+
The materialized shape on `triggerInput` is driven by the YAML, not by
|
|
69
|
+
how many files the dataset uploaded. Get this wrong and the worker
|
|
70
|
+
sees the opposite shape:
|
|
71
|
+
|
|
72
|
+
| YAML | `triggerInput.<name>` | Template |
|
|
73
|
+
| ------------------------------------------ | --------------------- | --------------------------------------- |
|
|
74
|
+
| `type: file` | `{ fileId }` | `{{ input.<name> }}` |
|
|
75
|
+
| `type: array`, `items: { type: file }` | `[{ fileId }, ...]` | `{{ input.<name>[0] }}` (or `forEach:`) |
|
|
76
|
+
|
|
77
|
+
If you see `Invalid input ... expected object, received array` from a
|
|
78
|
+
step that takes a single file, the workflow input is `type: file` but
|
|
79
|
+
the dataset folder probably has multiple files in it (or the workflow
|
|
80
|
+
was on a stale version that materialized arrays unconditionally).
|
|
81
|
+
Trim the folder to one file, or switch the input to the array form.
|
|
82
|
+
|
|
83
|
+
### `steps`
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
steps:
|
|
87
|
+
- name: parse # required, unique within the workflow
|
|
88
|
+
type: ai.document-parser # see `reference/step-types.md`; introspect with `step-type get`
|
|
89
|
+
if: '{{ input.skipParse != true }}' # optional — Liquid expression; falsy skips the step
|
|
90
|
+
forEach: '{{ input.documents }}' # optional — runs the step over each item; output is array
|
|
91
|
+
with: # step-specific config — schema depends on `type`
|
|
92
|
+
file: '{{ input.document }}'
|
|
93
|
+
parser: auto
|
|
94
|
+
|
|
95
|
+
- name: extract
|
|
96
|
+
type: ai.extract
|
|
97
|
+
with:
|
|
98
|
+
input: '{{ steps.parse.output.text }}'
|
|
99
|
+
schema:
|
|
100
|
+
type: object
|
|
101
|
+
properties:
|
|
102
|
+
invoiceNumber: { type: string }
|
|
103
|
+
totalAmount: { type: number }
|
|
104
|
+
required: [invoiceNumber]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Step references resolve via Liquid template expressions:
|
|
108
|
+
|
|
109
|
+
- `{{ input.<name> }}` — workflow input
|
|
110
|
+
- `{{ steps.<step-name>.output.<field> }}` — prior step output
|
|
111
|
+
- `{{ item.<field> }}` — current item inside `forEach`
|
|
112
|
+
|
|
113
|
+
`steps[].name` is the only handle into the step from later steps. Use
|
|
114
|
+
short, descriptive names (`parse`, `extract`, `score`).
|
|
115
|
+
|
|
116
|
+
### `output`
|
|
117
|
+
|
|
118
|
+
```yaml
|
|
119
|
+
output:
|
|
120
|
+
invoiceNumber: '{{ steps.extract.output.invoiceNumber }}'
|
|
121
|
+
totalAmount: '{{ steps.extract.output.totalAmount }}'
|
|
122
|
+
confidence: '{{ steps.score.output.confidence | default: 0 }}'
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Whatever shape you write here is the workflow's return value. Reference
|
|
126
|
+
any step's output. Static keys are fine — only the values are templated.
|
|
127
|
+
|
|
128
|
+
## Step types — pick the right one
|
|
129
|
+
|
|
130
|
+
See `reference/step-types.md` for the full catalog. Categories:
|
|
131
|
+
|
|
132
|
+
- `action.*` — side-effectful operations (HTTP, email, connectors)
|
|
133
|
+
- `ai.*` — model-backed processing (parse, extract, classify, judge)
|
|
134
|
+
- `transform.*` — deterministic data transforms (script, template, merge)
|
|
135
|
+
- `control.*` — flow control (if, for-each, parallel-map)
|
|
136
|
+
|
|
137
|
+
When in doubt, use `eigenpal workflow step-type get <type>` — it returns
|
|
138
|
+
the exact JSON Schema for the step's `config` + `output` so you know
|
|
139
|
+
which fields are required and what values they accept.
|
|
140
|
+
|
|
141
|
+
## Liquid vs `transform.script`
|
|
142
|
+
|
|
143
|
+
Use Liquid `{{ ... }}` for one-liners:
|
|
144
|
+
|
|
145
|
+
| Use case | Use |
|
|
146
|
+
| ------------- | -------------------------------- |
|
|
147
|
+
| Field access | `{{ steps.x.output.field }}` |
|
|
148
|
+
| Default value | `{{ value \| default: 0 }}` |
|
|
149
|
+
| Simple math | `{{ price \| times: quantity }}` |
|
|
150
|
+
|
|
151
|
+
Anything more complex (array reduce/filter, multi-step calc, date
|
|
152
|
+
arithmetic, regex) goes in `transform.script`:
|
|
153
|
+
|
|
154
|
+
```yaml
|
|
155
|
+
- name: total
|
|
156
|
+
type: transform.script
|
|
157
|
+
with:
|
|
158
|
+
inputs: # explicit data deps — visible to the validator
|
|
159
|
+
lineItems: '{{ steps.extract.output.lineItems }}'
|
|
160
|
+
taxRate: '{{ input.taxRate }}'
|
|
161
|
+
code: |
|
|
162
|
+
const subtotal = lineItems.reduce((s, i) => s + i.price * i.qty, 0);
|
|
163
|
+
const tax = subtotal * taxRate;
|
|
164
|
+
return { subtotal, tax, total: subtotal + tax };
|
|
165
|
+
outputSchema: # optional but recommended — runtime-validated
|
|
166
|
+
type: object
|
|
167
|
+
properties:
|
|
168
|
+
subtotal: { type: number }
|
|
169
|
+
tax: { type: number }
|
|
170
|
+
total: { type: number }
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The script runs in a WASM sandbox: 5s wall clock, 10 MB heap, no network,
|
|
174
|
+
no filesystem. Trips show up as `script_timeout` / `script_memory_limit`
|
|
175
|
+
on the step execution.
|
|
176
|
+
|
|
177
|
+
## Common patterns
|
|
178
|
+
|
|
179
|
+
### Conditional branches
|
|
180
|
+
|
|
181
|
+
```yaml
|
|
182
|
+
- name: classify
|
|
183
|
+
type: ai.extract
|
|
184
|
+
with:
|
|
185
|
+
input: '{{ input.text }}'
|
|
186
|
+
schema:
|
|
187
|
+
type: object
|
|
188
|
+
properties:
|
|
189
|
+
kind: { type: string, enum: [invoice, contract, other] }
|
|
190
|
+
|
|
191
|
+
- name: extract-invoice
|
|
192
|
+
type: ai.extract
|
|
193
|
+
if: '{{ steps.classify.output.kind == "invoice" }}'
|
|
194
|
+
with: { ... }
|
|
195
|
+
|
|
196
|
+
- name: extract-contract
|
|
197
|
+
type: ai.extract
|
|
198
|
+
if: '{{ steps.classify.output.kind == "contract" }}'
|
|
199
|
+
with: { ... }
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Map over an array input
|
|
203
|
+
|
|
204
|
+
```yaml
|
|
205
|
+
- name: extract-each
|
|
206
|
+
type: ai.extract
|
|
207
|
+
forEach: '{{ input.documents }}'
|
|
208
|
+
with:
|
|
209
|
+
input: '{{ item.text }}'
|
|
210
|
+
schema: { ... }
|
|
211
|
+
# steps.extract-each.output is an array of {invoiceNumber, totalAmount, ...}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Parallel fan-out
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
- name: extract-fields
|
|
218
|
+
type: control.parallel-map
|
|
219
|
+
forEach: '{{ input.fieldNames }}'
|
|
220
|
+
with:
|
|
221
|
+
steps:
|
|
222
|
+
- name: extract-one
|
|
223
|
+
type: ai.extract
|
|
224
|
+
with:
|
|
225
|
+
input: '{{ input.document }}'
|
|
226
|
+
schema: { type: object, properties: { value: { type: string } } }
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Validate before pushing
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
eigenpal workflow validate ./workflow.yaml
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Reports field-level issues:
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
✗ workflow (./workflow.yaml) — 2 issues
|
|
239
|
+
steps.2.config.passThreshold Required
|
|
240
|
+
steps.2.type Invalid step type: 'eval.llm-judg'
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Push:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# Create a new workflow (version comes from the YAML's top-level `version:` field)
|
|
247
|
+
eigenpal workflow push --file workflow.yaml
|
|
248
|
+
|
|
249
|
+
# Update an existing one — three ways to set the new version:
|
|
250
|
+
eigenpal workflow push --file workflow.yaml --workflow-id wf_… # bump in YAML's `version:`
|
|
251
|
+
eigenpal workflow push --file workflow.yaml --workflow-id wf_… --set-version 2.0.0 # explicit semver
|
|
252
|
+
eigenpal workflow push --file workflow.yaml --workflow-id wf_… --bump patch # auto-bump (patch | minor | major)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
`--bump` requires `--workflow-id` (it bumps from the current server
|
|
256
|
+
version). `--set-version` works with or without `--workflow-id`. The
|
|
257
|
+
YAML's top-level `version:` field is the fallback when neither flag is
|
|
258
|
+
passed — server rejects pushes whose version doesn't strictly increase.
|
|
259
|
+
|
|
260
|
+
## Discover step + evaluator types
|
|
261
|
+
|
|
262
|
+
Don't memorize fields — introspect:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
eigenpal workflow step-type list # full step catalog
|
|
266
|
+
eigenpal workflow step-type get <type> # config + output schema for one step type
|
|
267
|
+
eigenpal workflow evaluator-type list # full evaluator catalog
|
|
268
|
+
eigenpal workflow evaluator-type get <type> # config schema for one evaluator type
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Both catalogs are generated from the canonical Zod schemas in
|
|
272
|
+
`@eigenpal/types`, so they're always in sync with what the deployment
|
|
273
|
+
supports.
|
|
274
|
+
|
|
275
|
+
<!-- GENERATED:WORKFLOW_REFERENCE START -->
|
|
276
|
+
## Top-level fields — full reference
|
|
277
|
+
|
|
278
|
+
_Generated from `WorkflowDefinitionSchema` in `@eigenpal/types/src/workflow/workflow.ts`. Do not hand-edit between the GENERATED fences — run `bun run --cwd packages/cli generate:skill`._
|
|
279
|
+
|
|
280
|
+
| Field | Type | Required | Default | Description |
|
|
281
|
+
| --- | --- | --- | --- | --- |
|
|
282
|
+
| `name` | string | yes | | |
|
|
283
|
+
| `kind` | `"workflow"` \| `"block"` | no | `"workflow"` | |
|
|
284
|
+
| `version` | string | no | `"1.0.0"` | |
|
|
285
|
+
| `description` | string | no | | |
|
|
286
|
+
| `enabled` | boolean | no | `true` | |
|
|
287
|
+
| `triggerMethods` | array<object> | no | `[{"type":"manual"}]` | |
|
|
288
|
+
| `inputs` | array<object> | no | | |
|
|
289
|
+
| `steps` | array<unknown> | yes | | |
|
|
290
|
+
| `output` | record<string, string> | no | | |
|
|
291
|
+
| `settings` | object | no | | |
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
## Per-input fields
|
|
295
|
+
|
|
296
|
+
| Field | Type | Required | Default | Description |
|
|
297
|
+
| --- | --- | --- | --- | --- |
|
|
298
|
+
| `name` | string | yes | | |
|
|
299
|
+
| `type` | string | yes | | |
|
|
300
|
+
| `description` | string | no | | |
|
|
301
|
+
| `required` | boolean | no | `true` | |
|
|
302
|
+
| `default` | unknown | no | | |
|
|
303
|
+
| `items` | object | no | | |
|
|
304
|
+
<!-- GENERATED:WORKFLOW_REFERENCE END -->
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# __NAME__
|
|
2
|
+
|
|
3
|
+
Generated by `eigenpal init workflow`. Edit `workflow.yaml` to define your pipeline,
|
|
4
|
+
then run:
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
# Validate locally (no server contact)
|
|
8
|
+
eigenpal workflow validate
|
|
9
|
+
|
|
10
|
+
# Run an example end-to-end against the configured base URL
|
|
11
|
+
eigenpal workflow execution run __NAME__ sample
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Add more examples under `dataset/examples/<name>/`. Each example needs an
|
|
15
|
+
`input/arguments.json`; `expected/output.json` and `meta.json` are optional.
|
|
16
|
+
File arguments live in `input/<arg-name>/<filename>`.
|
|
17
|
+
|
|
18
|
+
When you're ready to push this workflow to the server:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
eigenpal workflow push --file workflow.yaml
|
|
22
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Evaluators run after every workflow execution that's part of an eval batch.
|
|
2
|
+
# Comment them in once you have an `expected/output.json` to compare against.
|
|
3
|
+
#
|
|
4
|
+
# evaluators:
|
|
5
|
+
# - name: exact-match
|
|
6
|
+
# type: exact-diff
|
|
7
|
+
# config:
|
|
8
|
+
# passThreshold: 1.0
|
|
9
|
+
evaluators: []
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: __NAME__
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
description: Replace this with what your workflow does.
|
|
4
|
+
|
|
5
|
+
# `triggerMethods` controls how this workflow can be invoked:
|
|
6
|
+
# - api: workflow can be called via the REST API and CLI
|
|
7
|
+
# - cron: workflow can be scheduled (set `cron` field below)
|
|
8
|
+
triggerMethods:
|
|
9
|
+
- api
|
|
10
|
+
|
|
11
|
+
# `inputs` declares the schema of arguments the workflow accepts. Each entry
|
|
12
|
+
# becomes a top-level key on the call's `triggerInput` object. Use `file: true`
|
|
13
|
+
# to mark an input as a file-arg (its value is a `[{ fileId }]` array at
|
|
14
|
+
# runtime; in the dataset folder layout it lives under `input/<name>/`).
|
|
15
|
+
inputs:
|
|
16
|
+
- name: text
|
|
17
|
+
type: string
|
|
18
|
+
description: Free-form text to process
|
|
19
|
+
|
|
20
|
+
# A pipeline of one or more steps. The first step receives `input.*`; later
|
|
21
|
+
# steps reference earlier outputs via `{{ steps.<name>.output.<field> }}`.
|
|
22
|
+
steps:
|
|
23
|
+
- name: passthrough
|
|
24
|
+
type: transform.script
|
|
25
|
+
with:
|
|
26
|
+
inputs:
|
|
27
|
+
text: '{{ input.text }}'
|
|
28
|
+
code: |
|
|
29
|
+
return { length: text.length, original: text };
|
|
30
|
+
outputSchema:
|
|
31
|
+
type: object
|
|
32
|
+
properties:
|
|
33
|
+
length: { type: number }
|
|
34
|
+
original: { type: string }
|
|
35
|
+
|
|
36
|
+
# `output` shapes the final return value. References any step's output.
|
|
37
|
+
output:
|
|
38
|
+
length: '{{ steps.passthrough.output.length }}'
|
|
39
|
+
original: '{{ steps.passthrough.output.original }}'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# __NAME__
|
|
2
|
+
|
|
3
|
+
A PDF/document extraction workflow scaffolded by `eigenpal init workflow`. The
|
|
4
|
+
pipeline parses an uploaded document with the auto-detected parser
|
|
5
|
+
(plaintext / office / OCR / LLM-vision), then runs `ai.extract` against a
|
|
6
|
+
fixed JSON schema.
|
|
7
|
+
|
|
8
|
+
## Wire it up
|
|
9
|
+
|
|
10
|
+
1. Drop a sample PDF at `dataset/examples/sample-invoice/input/document/<filename>`.
|
|
11
|
+
2. Adjust the `extract.with.schema` to the fields your documents actually carry.
|
|
12
|
+
3. Run an example: `eigenpal workflow execution run __NAME__ sample-invoice`.
|
|
13
|
+
4. When the output looks right, push: `eigenpal workflow push --file workflow.yaml`.
|
|
14
|
+
|
|
15
|
+
## Extending
|
|
16
|
+
|
|
17
|
+
- Multiple file inputs: declare more inputs in `workflow.yaml` and add
|
|
18
|
+
`dataset/examples/<name>/input/<arg>/` folders with their files.
|
|
19
|
+
- Per-example overrides: drop a `meta.json` next to the example with
|
|
20
|
+
`{ "overrides": { "steps": { "<step>": { ... } } } }` to skip steps in eval.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: __NAME__
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
description: Parse a PDF and extract structured fields with an LLM.
|
|
4
|
+
|
|
5
|
+
triggerMethods:
|
|
6
|
+
- api
|
|
7
|
+
|
|
8
|
+
inputs:
|
|
9
|
+
- name: document
|
|
10
|
+
type: file
|
|
11
|
+
file: true
|
|
12
|
+
description: PDF or image to extract from
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- name: parse
|
|
16
|
+
type: ai.document-parser
|
|
17
|
+
with:
|
|
18
|
+
file: '{{ input.document }}'
|
|
19
|
+
parser: auto
|
|
20
|
+
|
|
21
|
+
- name: extract
|
|
22
|
+
type: ai.extract
|
|
23
|
+
with:
|
|
24
|
+
input: '{{ steps.parse.output.text }}'
|
|
25
|
+
schema:
|
|
26
|
+
type: object
|
|
27
|
+
properties:
|
|
28
|
+
invoiceNumber: { type: string }
|
|
29
|
+
totalAmount: { type: number }
|
|
30
|
+
vendorName: { type: string }
|
|
31
|
+
dueDate: { type: string, format: date }
|
|
32
|
+
required: [invoiceNumber, totalAmount, vendorName]
|
|
33
|
+
|
|
34
|
+
output:
|
|
35
|
+
invoiceNumber: '{{ steps.extract.output.invoiceNumber }}'
|
|
36
|
+
totalAmount: '{{ steps.extract.output.totalAmount }}'
|
|
37
|
+
vendorName: '{{ steps.extract.output.vendorName }}'
|
|
38
|
+
dueDate: '{{ steps.extract.output.dueDate | default: null }}'
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# __NAME__
|
|
2
|
+
|
|
3
|
+
A text classification workflow scaffolded by `eigenpal init workflow`. Two examples
|
|
4
|
+
are pre-seeded so you can immediately run `eigenpal workflow execution run __NAME__` and see
|
|
5
|
+
end-to-end behavior.
|
|
6
|
+
|
|
7
|
+
The eval config asserts on the `label` path only — confidence/rationale are
|
|
8
|
+
free to vary between runs without failing the eval.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: __NAME__
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
description: Classify free-form text into one of a fixed set of labels.
|
|
4
|
+
|
|
5
|
+
triggerMethods:
|
|
6
|
+
- api
|
|
7
|
+
|
|
8
|
+
inputs:
|
|
9
|
+
- name: text
|
|
10
|
+
type: string
|
|
11
|
+
description: Text to classify
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- name: classify
|
|
15
|
+
type: ai.extract
|
|
16
|
+
with:
|
|
17
|
+
input: '{{ input.text }}'
|
|
18
|
+
schema:
|
|
19
|
+
type: object
|
|
20
|
+
properties:
|
|
21
|
+
label:
|
|
22
|
+
type: string
|
|
23
|
+
enum: [positive, neutral, negative]
|
|
24
|
+
confidence:
|
|
25
|
+
type: number
|
|
26
|
+
minimum: 0
|
|
27
|
+
maximum: 1
|
|
28
|
+
rationale:
|
|
29
|
+
type: string
|
|
30
|
+
required: [label, confidence]
|
|
31
|
+
|
|
32
|
+
output:
|
|
33
|
+
label: '{{ steps.classify.output.label }}'
|
|
34
|
+
confidence: '{{ steps.classify.output.confidence }}'
|
|
35
|
+
rationale: '{{ steps.classify.output.rationale | default: null }}'
|
package/package.json
CHANGED
|
@@ -1,12 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eigenpal/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Eigenpal CLI —
|
|
3
|
+
"version": "0.4.2",
|
|
4
|
+
"description": "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"eigenpal",
|
|
7
|
+
"cli",
|
|
8
|
+
"ai",
|
|
9
|
+
"agent",
|
|
10
|
+
"workflow",
|
|
11
|
+
"llm",
|
|
12
|
+
"evals",
|
|
13
|
+
"experiments",
|
|
14
|
+
"document",
|
|
15
|
+
"extraction",
|
|
16
|
+
"ocr"
|
|
17
|
+
],
|
|
18
|
+
"homepage": "https://github.com/eigenpal/cli#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/eigenpal/cli/issues"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/eigenpal/cli.git"
|
|
25
|
+
},
|
|
5
26
|
"license": "Apache-2.0",
|
|
27
|
+
"author": "Eigenpal <hello@eigenpal.com> (https://eigenpal.com)",
|
|
6
28
|
"type": "module",
|
|
7
|
-
"main": "./index.
|
|
29
|
+
"main": "./src/index.ts",
|
|
30
|
+
"types": "./src/index.ts",
|
|
8
31
|
"bin": {
|
|
9
|
-
"eigenpal": "
|
|
32
|
+
"eigenpal": "dist/cli.js"
|
|
10
33
|
},
|
|
11
34
|
"engines": {
|
|
12
35
|
"node": ">=20"
|
|
@@ -14,16 +37,38 @@
|
|
|
14
37
|
"publishConfig": {
|
|
15
38
|
"access": "public"
|
|
16
39
|
},
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
40
|
+
"scripts": {
|
|
41
|
+
"dev": "bun src/cli.ts",
|
|
42
|
+
"build": "bun run generate:skill && bun build src/cli.ts --outdir dist --target node --format esm && rm -rf dist/templates dist/skill && cp -R src/templates dist/templates && cp -R src/skill dist/skill",
|
|
43
|
+
"generate:skill": "bun scripts/generate-skill-reference.ts",
|
|
44
|
+
"generate:skill:check": "bun scripts/generate-skill-reference.ts --check",
|
|
45
|
+
"generate:cli-docs": "bun scripts/generate-cli-docs.ts",
|
|
46
|
+
"generate:cli-docs:check": "bun scripts/generate-cli-docs.ts --check",
|
|
47
|
+
"generate:logo": "bun scripts/render-logo-ascii.ts --cells 20",
|
|
48
|
+
"lint": "eslint src/",
|
|
49
|
+
"typecheck": "tsc --noEmit"
|
|
24
50
|
},
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@clack/prompts": "^0.10.1",
|
|
53
|
+
"ajv": "^8.17.1",
|
|
54
|
+
"commander": "^13.1.0",
|
|
55
|
+
"fflate": "0.8.2",
|
|
56
|
+
"openai": "^6.27.0",
|
|
57
|
+
"picocolors": "^1.1.1",
|
|
58
|
+
"quickjs-emscripten": "^0.31.0",
|
|
59
|
+
"yaml": "^2.7.0",
|
|
60
|
+
"zod": "^4.0.0"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@eigenpal/types": "workspace:*",
|
|
64
|
+
"@eigenpal/workflow-yaml": "workspace:*",
|
|
65
|
+
"@t3-oss/env-core": "^0.13.11",
|
|
66
|
+
"typescript": "^5.3.0"
|
|
67
|
+
},
|
|
68
|
+
"files": [
|
|
69
|
+
"dist",
|
|
70
|
+
"LICENSE",
|
|
71
|
+
"README.md",
|
|
72
|
+
"CHANGELOG.md"
|
|
73
|
+
]
|
|
29
74
|
}
|
package/index.js
DELETED