markform 0.1.17 → 0.1.18
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 +2 -2
- package/dist/ai-sdk.d.mts +1 -1
- package/dist/ai-sdk.mjs +2 -2
- package/dist/{apply-DgDJBscb.mjs → apply-BYgtU64w.mjs} +29 -3
- package/dist/apply-BYgtU64w.mjs.map +1 -0
- package/dist/bin.mjs +1 -1
- package/dist/{cli-DAl8LQzI.mjs → cli-D9w0Bp4J.mjs} +192 -6
- package/dist/cli-D9w0Bp4J.mjs.map +1 -0
- package/dist/cli.mjs +1 -1
- package/dist/{coreTypes-CnEea7Kh.d.mts → coreTypes-BMEs8h_2.d.mts} +125 -2
- package/dist/{coreTypes-DiCddBKu.mjs → coreTypes-SDB3KRRJ.mjs} +9 -4
- package/dist/coreTypes-SDB3KRRJ.mjs.map +1 -0
- package/dist/index.d.mts +129 -2
- package/dist/index.mjs +5 -5
- package/dist/{session-B7aR6hno.mjs → session-CW9AQw6i.mjs} +1 -1
- package/dist/{session-XDrocA3j.mjs → session-Ci4B0Pna.mjs} +2 -2
- package/dist/{session-XDrocA3j.mjs.map → session-Ci4B0Pna.mjs.map} +1 -1
- package/dist/{src-CHVJLGKt.mjs → src-DDxi-2ne.mjs} +495 -14
- package/dist/src-DDxi-2ne.mjs.map +1 -0
- package/docs/markform-apis.md +31 -0
- package/docs/markform-reference.md +27 -0
- package/docs/markform-spec.md +115 -0
- package/examples/movie-research/movie-deep-research-mock-filled.form.md +1 -1
- package/examples/movie-research/movie-deep-research.form.md +1 -1
- package/examples/parallel/parallel-research.form.md +57 -0
- package/examples/startup-deep-research/startup-deep-research.form.md +1 -1
- package/package.json +1 -1
- package/dist/apply-DgDJBscb.mjs.map +0 -1
- package/dist/cli-DAl8LQzI.mjs.map +0 -1
- package/dist/coreTypes-DiCddBKu.mjs.map +0 -1
- package/dist/src-CHVJLGKt.mjs.map +0 -1
package/docs/markform-apis.md
CHANGED
|
@@ -202,10 +202,41 @@ const result = await fillForm({
|
|
|
202
202
|
| `maxStepsPerTurn` | `number` | `20` | Maximum AI SDK steps (tool call rounds) per turn |
|
|
203
203
|
| `targetRoles` | `string[]` | `['agent']` | Roles to fill |
|
|
204
204
|
| `fillMode` | `FillMode` | `'continue'` | `'continue'` or `'overwrite'` |
|
|
205
|
+
| `enableParallel` | `boolean` | `false` | Enable parallel execution for forms with `parallel` batches |
|
|
206
|
+
| `maxParallelAgents` | `number` | `4` | Max concurrent agents for parallel batches |
|
|
205
207
|
| `callbacks` | `FillCallbacks` | `undefined` | Progress callbacks |
|
|
206
208
|
| `signal` | `AbortSignal` | `undefined` | Cancellation signal |
|
|
207
209
|
| `additionalTools` | `Record<string, Tool>` | `undefined` | Custom tools for agent |
|
|
208
210
|
|
|
211
|
+
### Parallel Execution
|
|
212
|
+
|
|
213
|
+
When a form uses `parallel` attributes on groups, you can enable concurrent execution:
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const result = await fillForm({
|
|
217
|
+
form: formMarkdown,
|
|
218
|
+
model: 'anthropic/claude-sonnet-4-5',
|
|
219
|
+
enableWebSearch: true,
|
|
220
|
+
captureWireFormat: false,
|
|
221
|
+
enableParallel: true,
|
|
222
|
+
maxParallelAgents: 4,
|
|
223
|
+
callbacks: {
|
|
224
|
+
onOrderLevelStart: ({ order }) => console.log(`Order ${order} starting`),
|
|
225
|
+
onBatchStart: ({ batchId }) => console.log(`Batch ${batchId} starting`),
|
|
226
|
+
onBatchComplete: ({ batchId, patchesApplied }) =>
|
|
227
|
+
console.log(`Batch ${batchId}: ${patchesApplied} patches`),
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Behavior:**
|
|
233
|
+
- `enableParallel: false` (default): All fields filled serially, `parallel` attributes
|
|
234
|
+
ignored. The `order` attribute still controls issue filtering.
|
|
235
|
+
- `enableParallel: true`: Batch items run concurrently (up to `maxParallelAgents`).
|
|
236
|
+
Each agent runs a multi-turn loop with rejection feedback, same as the serial path.
|
|
237
|
+
- If the form has no `parallel` batches, falls back to serial automatically.
|
|
238
|
+
- `FillResult` shape is identical regardless of serial or parallel execution.
|
|
239
|
+
|
|
209
240
|
### FillStatus
|
|
210
241
|
|
|
211
242
|
The `status` field in `FillResult` indicates success or failure:
|
|
@@ -416,6 +416,8 @@ All fields support these attributes:
|
|
|
416
416
|
| `required` | boolean | false | Must be filled for completion |
|
|
417
417
|
| `role` | string | - | Target actor (`user`, `agent`) |
|
|
418
418
|
| `priority` | string | medium | `high`, `medium`, `low` |
|
|
419
|
+
| `order` | number | `0` | Fill order. Lower values filled first. Different order levels are filled in separate turns. |
|
|
420
|
+
| `parallel` | string | - | Parallel batch identifier. Items with the same value may execute concurrently. Top-level only. |
|
|
419
421
|
|
|
420
422
|
**Text-entry fields only** (string, number, string-list, url, url-list):
|
|
421
423
|
|
|
@@ -432,6 +434,31 @@ All fields support these attributes:
|
|
|
432
434
|
Note: `placeholder` and `examples` are NOT valid on chooser fields (single-select,
|
|
433
435
|
multi-select, checkboxes).
|
|
434
436
|
|
|
437
|
+
## Harness Configuration
|
|
438
|
+
|
|
439
|
+
Optional harness hints can be set in YAML frontmatter under `markform.harness`.
|
|
440
|
+
All keys must be `snake_case` and all values must be numbers.
|
|
441
|
+
These are suggestions — a harness may ignore or override them via API options.
|
|
442
|
+
|
|
443
|
+
| Key | Type | Description |
|
|
444
|
+
| --- | --- | --- |
|
|
445
|
+
| `max_turns` | number | Maximum turns before stopping |
|
|
446
|
+
| `max_patches_per_turn` | number | Maximum patches per turn |
|
|
447
|
+
| `max_issues_per_turn` | number | Maximum issues surfaced per turn |
|
|
448
|
+
| `max_parallel_agents` | number | Maximum concurrent agents for parallel execution |
|
|
449
|
+
|
|
450
|
+
```yaml
|
|
451
|
+
markform:
|
|
452
|
+
spec: MF/0.1
|
|
453
|
+
harness:
|
|
454
|
+
max_turns: 50
|
|
455
|
+
max_issues_per_turn: 5
|
|
456
|
+
max_patches_per_turn: 10
|
|
457
|
+
max_parallel_agents: 4
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Unrecognized keys or non-numeric values cause parse errors.
|
|
461
|
+
|
|
435
462
|
## Documentation Blocks
|
|
436
463
|
|
|
437
464
|
Add context to fields, groups, or the form.
|
package/docs/markform-spec.md
CHANGED
|
@@ -144,6 +144,30 @@ markform:
|
|
|
144
144
|
When omitted, tools may infer from field roles or require explicit selection.
|
|
145
145
|
This is a hint for tooling, not enforced by the engine.
|
|
146
146
|
|
|
147
|
+
- `harness` (*optional*): A map of harness configuration hints that suggest execution
|
|
148
|
+
parameters to harness implementations. These are suggestions — a harness MAY ignore
|
|
149
|
+
them or override them via API options.
|
|
150
|
+
|
|
151
|
+
Supported keys (all values must be numbers, all keys must be `snake_case`):
|
|
152
|
+
|
|
153
|
+
| Key | Description |
|
|
154
|
+
| --- | --- |
|
|
155
|
+
| `max_turns` | Suggested maximum turns before stopping |
|
|
156
|
+
| `max_patches_per_turn` | Suggested maximum patches per turn |
|
|
157
|
+
| `max_issues_per_turn` | Suggested maximum issues surfaced per turn |
|
|
158
|
+
| `max_parallel_agents` | Suggested maximum concurrent agents for parallel execution |
|
|
159
|
+
|
|
160
|
+
Unrecognized keys or non-numeric values are parse errors.
|
|
161
|
+
|
|
162
|
+
Example:
|
|
163
|
+
```yaml
|
|
164
|
+
markform:
|
|
165
|
+
spec: MF/0.1
|
|
166
|
+
harness:
|
|
167
|
+
max_turns: 50
|
|
168
|
+
max_parallel_agents: 4
|
|
169
|
+
```
|
|
170
|
+
|
|
147
171
|
**Behavioral rules (*required*):**
|
|
148
172
|
|
|
149
173
|
- *required:* `form_summary`, `form_progress`, and `form_state` are derived,
|
|
@@ -255,6 +279,8 @@ Example: `pattern="^[A-Z]{1,5}$"` for a ticker symbol.
|
|
|
255
279
|
| `label` | string | Required. Human-readable field name |
|
|
256
280
|
| `required` | boolean | Whether field must be filled for form completion |
|
|
257
281
|
| `role` | string | Target actor (e.g., `"user"`, `"agent"`). See role-filtered completion |
|
|
282
|
+
| `parallel` | string | Parallel batch identifier. Top-level fields/groups only. See [Parallel Execution Hints](#parallel-execution-hints) |
|
|
283
|
+
| `order` | number | Fill order (default: `0`). Lower values filled first. See [Fill Order](#fill-order) |
|
|
258
284
|
|
|
259
285
|
The `role` attribute enables multi-actor workflows where different fields are assigned
|
|
260
286
|
to different actors.
|
|
@@ -1259,6 +1285,59 @@ On GitHub, all `<!-- ... -->` comments are hidden, leaving only the visible cont
|
|
|
1259
1285
|
**Constraint:** Values containing the literal string `-->` require escaping or should
|
|
1260
1286
|
use the tag syntax to avoid prematurely closing the comment.
|
|
1261
1287
|
|
|
1288
|
+
##### Parallel Execution Hints
|
|
1289
|
+
|
|
1290
|
+
Top-level fields and groups MAY include a `parallel` attribute to indicate that they
|
|
1291
|
+
can be filled concurrently with other items sharing the same value.
|
|
1292
|
+
|
|
1293
|
+
```markdown
|
|
1294
|
+
<!-- field kind="string" id="a" label="A" parallel="batch_1" --><!-- /field -->
|
|
1295
|
+
<!-- field kind="string" id="b" label="B" parallel="batch_1" --><!-- /field -->
|
|
1296
|
+
```
|
|
1297
|
+
|
|
1298
|
+
**Rules:**
|
|
1299
|
+
- `parallel` value is an arbitrary string identifier (recommended: `snake_case`)
|
|
1300
|
+
- Items with the same `parallel` value form a *parallel batch*
|
|
1301
|
+
- Items without `parallel` remain in loose-serial mode (single agent, no enforced
|
|
1302
|
+
ordering) — identical to current behavior
|
|
1303
|
+
- `parallel` MUST NOT appear on fields inside groups (parse error) — only on
|
|
1304
|
+
top-level fields and groups
|
|
1305
|
+
- All items in a parallel batch MUST have the same effective `role` (parse error)
|
|
1306
|
+
- `parallel` is a hint — a harness MAY ignore it and fill everything in
|
|
1307
|
+
loose-serial mode
|
|
1308
|
+
|
|
1309
|
+
**Execution model:**
|
|
1310
|
+
```
|
|
1311
|
+
Without parallel: All items filled by one agent in loose-serial mode (current behavior).
|
|
1312
|
+
|
|
1313
|
+
With parallel: Items are partitioned into two pools:
|
|
1314
|
+
1. Loose-serial pool: items without `parallel`, filled by primary agent
|
|
1315
|
+
2. Parallel batches: items with `parallel`, each item filled by a separate agent
|
|
1316
|
+
All agents (primary + parallel) run concurrently. No barriers between them.
|
|
1317
|
+
```
|
|
1318
|
+
|
|
1319
|
+
##### Fill Order
|
|
1320
|
+
|
|
1321
|
+
Fields and groups MAY include an `order` attribute (numeric) that controls the
|
|
1322
|
+
sequence in which the harness presents fields to the agent.
|
|
1323
|
+
|
|
1324
|
+
```markdown
|
|
1325
|
+
<!-- field kind="string" id="details" label="Details" --><!-- /field -->
|
|
1326
|
+
<!-- field kind="string" id="summary" label="Summary" order=99 --><!-- /field -->
|
|
1327
|
+
```
|
|
1328
|
+
|
|
1329
|
+
**Rules:**
|
|
1330
|
+
- `order` is a number (integer or float). Default: `0`.
|
|
1331
|
+
- Lower `order` values are filled first. Fields at the same order level are
|
|
1332
|
+
filled in loose-serial order (agent chooses).
|
|
1333
|
+
- The harness MUST NOT surface issues for `order=N` fields until all fields at
|
|
1334
|
+
`order<N` are complete (answered, skipped, or aborted).
|
|
1335
|
+
- Fields at different order levels are always filled in separate agent turns.
|
|
1336
|
+
- A field inside a group with `order` MUST NOT specify a different `order`
|
|
1337
|
+
(parse error). Use separate groups for different order levels.
|
|
1338
|
+
- `order` composes with `parallel`: all items in a parallel batch MUST have the
|
|
1339
|
+
same effective `order` value (parse error otherwise).
|
|
1340
|
+
|
|
1262
1341
|
* * *
|
|
1263
1342
|
|
|
1264
1343
|
## Layer 2: Form Data Model
|
|
@@ -1442,6 +1521,8 @@ interface FieldGroup {
|
|
|
1442
1521
|
// Note: `required` on groups is not supported in MF/0.1 (ignored with warning)
|
|
1443
1522
|
validate?: ValidatorRef[]; // validator references (string IDs or parameterized objects)
|
|
1444
1523
|
children: Field[]; // MF/0.1/0.2: fields only; nested groups deferred (future)
|
|
1524
|
+
parallel?: string; // Parallel batch identifier
|
|
1525
|
+
order?: number; // Fill order (default: 0). Applies to all child fields.
|
|
1445
1526
|
}
|
|
1446
1527
|
|
|
1447
1528
|
type FieldPriorityLevel = 'high' | 'medium' | 'low';
|
|
@@ -1452,6 +1533,8 @@ interface FieldBase {
|
|
|
1452
1533
|
required: boolean; // explicit: parser defaults to false if not specified
|
|
1453
1534
|
priority: FieldPriorityLevel; // explicit: parser defaults to 'medium' if not specified
|
|
1454
1535
|
validate?: ValidatorRef[]; // validator references (string IDs or parameterized objects)
|
|
1536
|
+
parallel?: string; // Parallel batch identifier (top-level only)
|
|
1537
|
+
order?: number; // Fill order (default: 0). Lower = filled first.
|
|
1455
1538
|
}
|
|
1456
1539
|
|
|
1457
1540
|
// NOTE: `required` and `priority` are explicit (not optional) in the data model.
|
|
@@ -2664,6 +2747,38 @@ isRetryableError(error) // LLM error with retryable=true
|
|
|
2664
2747
|
`ParseError` is exported as an alias for `MarkformParseError` for backward compatibility.
|
|
2665
2748
|
Use `MarkformParseError` in new code.
|
|
2666
2749
|
|
|
2750
|
+
#### Execution Plan
|
|
2751
|
+
|
|
2752
|
+
An **execution plan** partitions top-level form items into a loose-serial pool and
|
|
2753
|
+
zero or more parallel batches:
|
|
2754
|
+
|
|
2755
|
+
```typescript
|
|
2756
|
+
interface ExecutionPlan {
|
|
2757
|
+
/** Items without `parallel` — filled by primary agent in loose-serial mode */
|
|
2758
|
+
looseSerial: Array<{ itemId: Id; itemType: 'field' | 'group' }>;
|
|
2759
|
+
|
|
2760
|
+
/** Parallel batches — each item filled by a separate concurrent agent */
|
|
2761
|
+
parallelBatches: Array<{
|
|
2762
|
+
batchId: string;
|
|
2763
|
+
items: Array<{ itemId: Id; itemType: 'field' | 'group' }>;
|
|
2764
|
+
}>;
|
|
2765
|
+
}
|
|
2766
|
+
```
|
|
2767
|
+
|
|
2768
|
+
**Computation:** Walk top-level items (fields and groups) in document order:
|
|
2769
|
+
- If item has no `parallel`: add to the loose-serial pool
|
|
2770
|
+
- If item has `parallel`: add to the batch with that ID (create batch if new)
|
|
2771
|
+
|
|
2772
|
+
**Execution:** The primary agent fills loose-serial items. For each parallel batch,
|
|
2773
|
+
one agent per item is spawned. All agents (primary + batch agents) run concurrently.
|
|
2774
|
+
When all complete, patches are merged and validation runs.
|
|
2775
|
+
|
|
2776
|
+
**Order-based filtering:** The harness partitions items by their effective `order`
|
|
2777
|
+
value (default `0`). Issues for fields at `order=N` are only surfaced after all fields
|
|
2778
|
+
at `order<N` are complete (answered, skipped, or aborted). This ensures fields at
|
|
2779
|
+
different order levels are always filled in separate agent turns, so higher-order fields
|
|
2780
|
+
see completed lower-order field values in the form markdown.
|
|
2781
|
+
|
|
2667
2782
|
* * *
|
|
2668
2783
|
|
|
2669
2784
|
## Layer 4: Tool API & Interfaces
|
|
@@ -35,7 +35,7 @@ markform:
|
|
|
35
35
|
- Skip fields if data unavailable (older films may lack some metrics)
|
|
36
36
|
- For box office, use millions (e.g., 100.5 for $100.5M)
|
|
37
37
|
- Add notes for any missing, confusing, or unclear information
|
|
38
|
-
|
|
38
|
+
harness:
|
|
39
39
|
max_issues_per_turn: 5
|
|
40
40
|
max_patches_per_turn: 15
|
|
41
41
|
---
|
|
@@ -35,7 +35,7 @@ markform:
|
|
|
35
35
|
- Skip fields if data unavailable (older films may lack some metrics)
|
|
36
36
|
- For box office, use millions (e.g., 100.5 for $100.5M)
|
|
37
37
|
- Add notes for any missing, confusing, or unclear information
|
|
38
|
-
|
|
38
|
+
harness:
|
|
39
39
|
max_issues_per_turn: 5
|
|
40
40
|
max_patches_per_turn: 15
|
|
41
41
|
---
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
markform:
|
|
3
|
+
spec: MF/0.1
|
|
4
|
+
title: Company Research (Parallel)
|
|
5
|
+
description: "Demonstrates parallel and order attributes for concurrent form filling."
|
|
6
|
+
roles:
|
|
7
|
+
- agent
|
|
8
|
+
role_instructions:
|
|
9
|
+
agent: "Research the company and fill in all fields."
|
|
10
|
+
harness:
|
|
11
|
+
max_turns: 10
|
|
12
|
+
max_parallel_agents: 4
|
|
13
|
+
---
|
|
14
|
+
{% form id="company_research" title="Company Research (Parallel)" %}
|
|
15
|
+
|
|
16
|
+
{% description ref="company_research" %}
|
|
17
|
+
A company research form that uses `parallel` for concurrent deep research
|
|
18
|
+
and `order` to sequence synthesis after data gathering.
|
|
19
|
+
{% /description %}
|
|
20
|
+
|
|
21
|
+
{% group id="overview" order=0 %}
|
|
22
|
+
|
|
23
|
+
{% field kind="string" id="company_name" label="Company Name" role="agent" required=true %}{% /field %}
|
|
24
|
+
|
|
25
|
+
{% field kind="string" id="company_overview" label="Company Overview" role="agent" %}{% /field %}
|
|
26
|
+
|
|
27
|
+
{% /group %}
|
|
28
|
+
|
|
29
|
+
{% group id="financials" parallel="deep_research" order=0 %}
|
|
30
|
+
|
|
31
|
+
{% field kind="string" id="revenue" label="Annual Revenue" role="agent" %}{% /field %}
|
|
32
|
+
|
|
33
|
+
{% field kind="string" id="margins" label="Margin Analysis" role="agent" %}{% /field %}
|
|
34
|
+
|
|
35
|
+
{% /group %}
|
|
36
|
+
|
|
37
|
+
{% group id="team" parallel="deep_research" order=0 %}
|
|
38
|
+
|
|
39
|
+
{% field kind="string" id="leadership" label="Team & Leadership" role="agent" %}{% /field %}
|
|
40
|
+
|
|
41
|
+
{% /group %}
|
|
42
|
+
|
|
43
|
+
{% group id="market" parallel="deep_research" order=0 %}
|
|
44
|
+
|
|
45
|
+
{% field kind="string" id="tam" label="TAM" role="agent" %}{% /field %}
|
|
46
|
+
|
|
47
|
+
{% field kind="string" id="competitors" label="Competitors" role="agent" %}{% /field %}
|
|
48
|
+
|
|
49
|
+
{% /group %}
|
|
50
|
+
|
|
51
|
+
{% group id="synthesis" order=10 %}
|
|
52
|
+
|
|
53
|
+
{% field kind="string" id="overall" label="Overall Assessment" role="agent" required=true %}{% /field %}
|
|
54
|
+
|
|
55
|
+
{% /group %}
|
|
56
|
+
|
|
57
|
+
{% /form %}
|
|
@@ -21,7 +21,7 @@ markform:
|
|
|
21
21
|
7. Include source URLs for every piece of information
|
|
22
22
|
8. Leave unknown fields empty - don't guess or fabricate
|
|
23
23
|
9. Keep descriptions concise (50-150 words max)
|
|
24
|
-
|
|
24
|
+
harness:
|
|
25
25
|
max_issues_per_turn: 5
|
|
26
26
|
max_patches_per_turn: 10
|
|
27
27
|
---
|