markform 0.1.3 → 0.1.5

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.
Files changed (36) hide show
  1. package/README.md +110 -70
  2. package/dist/ai-sdk.d.mts +2 -2
  3. package/dist/ai-sdk.mjs +5 -5
  4. package/dist/{apply-00UmzDKL.mjs → apply-BCCiJzQr.mjs} +371 -26
  5. package/dist/bin.mjs +6 -6
  6. package/dist/{cli-D--Lel-e.mjs → cli-D469amuk.mjs} +386 -96
  7. package/dist/cli.mjs +6 -6
  8. package/dist/{coreTypes-BXhhz9Iq.d.mts → coreTypes-9XZSNOv6.d.mts} +1878 -325
  9. package/dist/{coreTypes-Dful87E0.mjs → coreTypes-pyctKRgc.mjs} +79 -5
  10. package/dist/index.d.mts +142 -5
  11. package/dist/index.mjs +5 -5
  12. package/dist/session-B_stoXQn.mjs +4 -0
  13. package/dist/{session-Bqnwi9wp.mjs → session-uF0e6m6k.mjs} +9 -5
  14. package/dist/{shared-N_s1M-_K.mjs → shared-BqPnYXrn.mjs} +82 -1
  15. package/dist/shared-CZsyShck.mjs +3 -0
  16. package/dist/{src-Dm8jZ5dl.mjs → src-Df0XX7UB.mjs} +818 -125
  17. package/docs/markform-apis.md +194 -0
  18. package/{DOCS.md → docs/markform-reference.md} +130 -69
  19. package/{SPEC.md → docs/markform-spec.md} +359 -108
  20. package/examples/earnings-analysis/earnings-analysis.form.md +88 -800
  21. package/examples/earnings-analysis/earnings-analysis.valid.ts +16 -148
  22. package/examples/movie-research/movie-research-basic.form.md +41 -37
  23. package/examples/movie-research/movie-research-deep.form.md +110 -98
  24. package/examples/movie-research/movie-research-minimal.form.md +29 -15
  25. package/examples/simple/simple-mock-filled.form.md +105 -41
  26. package/examples/simple/simple-skipped-filled.form.md +103 -41
  27. package/examples/simple/simple-with-skips.session.yaml +93 -25
  28. package/examples/simple/simple.form.md +86 -32
  29. package/examples/simple/simple.session.yaml +98 -25
  30. package/examples/startup-deep-research/startup-deep-research.form.md +130 -103
  31. package/examples/startup-research/startup-research-mock-filled.form.md +55 -55
  32. package/examples/startup-research/startup-research.form.md +36 -36
  33. package/package.json +18 -19
  34. package/dist/session-DdAtY2Ni.mjs +0 -4
  35. package/dist/shared-D7gf27Tr.mjs +0 -3
  36. package/examples/celebrity-deep-research/celebrity-deep-research.form.md +0 -912
package/README.md CHANGED
@@ -21,6 +21,8 @@ which makes creating new workflows much easier.
21
21
 
22
22
  ## Installation
23
23
 
24
+ Requires Node.js 20+.
25
+
24
26
  ```bash
25
27
  # As a global CLI
26
28
  npm install -g markform
@@ -29,8 +31,6 @@ npm install -g markform
29
31
  npm install markform
30
32
  ```
31
33
 
32
- Requires Node.js 20+ (v24 recommended).
33
-
34
34
  ## Quick Start
35
35
 
36
36
  ```bash
@@ -39,9 +39,12 @@ npx markform examples
39
39
  ```
40
40
 
41
41
  This walks you through an example form interactively, with optional AI agent filling.
42
- You’ll need at least one [API key](#supported-providers) to have LLMs fill in forms.
42
+ You’ll need at least one [API key](#supported-providers) form a provider with a model
43
+ that supports web search to have LLMs fill in forms.
43
44
 
44
- ### A Minimal Form
45
+ ## Example: Research a Movie
46
+
47
+ ### Form Definition
45
48
 
46
49
  A `.form.md` file is simply a Markdoc file.
47
50
  It combines YAML frontmatter with Markdoc-tagged content:
@@ -63,105 +66,114 @@ markform:
63
66
  ---
64
67
  {% form id="movie_research_minimal" title="Movie Research (Minimal)" %}
65
68
 
66
- <!-- The first field group is filled in by the user (role="user"): -->
69
+ ## Movie Research Example
70
+
71
+ {% group id="movie_input" title="Movie Identification" %}
67
72
 
68
- {% field-group id="movie_input" title="Movie Identification" %}
73
+ What movie do you want to research? \[*This field is filled in by the user (`role="user"`).*\]
69
74
 
70
- {% string-field id="movie" label="Movie" role="user" required=true minLength=1 maxLength=300 %}{% /string-field %}
75
+ {% field kind="string" id="movie" label="Movie" role="user" required=true minLength=1 maxLength=300 %}{% /field %}
71
76
  {% instructions ref="movie" %}Enter the movie title (add year or details for disambiguation).{% /instructions %}
72
77
 
73
- {% /field-group %}
78
+ {% /group %}
79
+
80
+ ## About the Movie
81
+
82
+ {% group id="about_the_movie" title="About the Movie" %}
83
+
84
+ **Title:**
85
+
86
+ {% field kind="string" id="full_title" label="Full Title" role="agent" required=true %}{% /field %}
87
+ {% instructions ref="full_title" %}Official title, including subtitle if any.{% /instructions %}
74
88
 
75
- <!-- Everything else is filled in by the agent (role="agent"): -->
89
+ **Release year:**
76
90
 
77
- {% field-group id="about_the_movie" title="About the Movie" %}
91
+ {% field kind="number" id="year" label="Release Year" role="agent" required=true min=1888 max=2030 %}{% /field %}
78
92
 
79
- {% string-field id="full_title" label="Full Title" role="agent" required=true %}{% /string-field %}
80
- {% instructions ref="full_title" %}Official title including subtitle if any.{% /instructions %}
93
+ **IMDB:**
81
94
 
82
- {% number-field id="year" label="Release Year" role="agent" required=true min=1888 max=2030 %}{% /number-field %}
95
+ {% field kind="url" id="imdb_url" label="IMDB URL" role="agent" required=true %}{% /field %}
83
96
 
84
- {% url-field id="imdb_url" label="IMDB URL" role="agent" required=true %}{% /url-field %}
97
+ **MPAA rating:**
85
98
 
86
- {% single-select id="mpaa_rating" label="MPAA Rating" role="agent" %}
99
+ {% field kind="single_select" id="mpaa_rating" label="MPAA Rating" role="agent" %}
87
100
  - [ ] G {% #g %}
88
101
  - [ ] PG {% #pg %}
89
102
  - [ ] PG-13 {% #pg_13 %}
90
103
  - [ ] R {% #r %}
91
104
  - [ ] NC-17 {% #nc_17 %}
92
105
  - [ ] NR/Unrated {% #nr %}
93
- {% /single-select %}
106
+ {% /field %}
94
107
 
95
- {% number-field id="imdb_rating" label="IMDB Rating" role="agent" min=1.0 max=10.0 %}{% /number-field %}
108
+ **IMDB rating:**
109
+
110
+ {% field kind="number" id="imdb_rating" label="IMDB Rating" role="agent" min=1.0 max=10.0 %}{% /field %}
96
111
  {% instructions ref="imdb_rating" %}IMDB user rating (1.0-10.0 scale).{% /instructions %}
97
112
 
98
- {% string-field id="logline" label="One-Line Summary" role="agent" maxLength=300 %}{% /string-field %}
113
+ **Summary:**
114
+
115
+ {% field kind="string" id="logline" label="One-Line Summary" role="agent" maxLength=300 %}{% /field %}
99
116
  {% instructions ref="logline" %}Brief plot summary in 1-2 sentences, no spoilers.{% /instructions %}
100
117
 
101
- {% /field-group %}
118
+ {% /group %}
102
119
 
103
120
  {% /form %}
104
121
  ```
105
122
 
106
- This is the minimal movie research form.
107
- See the
108
- [examples/](https://github.com/jlevy/markform/tree/main/packages/markform/examples)
109
- directory for forms with more fields, including multiple rating sources (IMDB, Rotten
110
- Tomatoes, Metacritic) and comprehensive analysis.
123
+ ### Form Report Output
124
+
125
+ Run the `npx markform examples` and select the `Movie Research (Minimal)` example and
126
+ view the report:
127
+
128
+ ```markdown
129
+ # Movie Research (Minimal)
130
+
131
+ ## Movie Identification
132
+
133
+ Movie:
134
+ shawshank redemption
111
135
 
112
- **Key concepts:**
136
+ ## About the Movie
113
137
 
114
- - **Roles**: Define who fills what (`user` for humans, `agent` for AI)
138
+ Full Title:
139
+ The Shawshank Redemption
115
140
 
116
- - **Field types**: `string-field`, `number-field`, `url-field`, `string-list`,
117
- `single-select`, `multi-select`, `checkboxes`
141
+ Release Year:
142
+ 1994
118
143
 
119
- - **Validation**: `required`, `min/max`, `minLength/maxLength`, `pattern`
144
+ IMDB URL:
145
+ https://www.imdb.com/title/tt0111161/
120
146
 
121
- - **Structure**: Fields organized in `field-group` containers
147
+ MPAA Rating:
148
+ R
122
149
 
123
- - **Instructions**: Per-field guidance for users or agents
150
+ IMDB Rating:
151
+ 9.3
152
+
153
+ One-Line Summary:
154
+ Convicted banker Andy Dufresne is sent to Shawshank State Penitentiary, where he forms an unexpected friendship with inmate Red while holding onto hope and striving to maintain his dignity in a corrupt prison system.
155
+ ```
124
156
 
125
157
  ### More Example Forms
126
158
 
127
159
  The package includes example forms in
128
- [`examples/`](https://github.com/jlevy/markform/tree/main/packages/markform/examples):
160
+ [`examples/`](https://github.com/jlevy/markform/tree/main/packages/markform/examples).
161
+ View them with `markform examples --list` or try these interactively:
129
162
 
130
163
  - [`movie-research/movie-research-minimal.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/movie-research/movie-research-minimal.form.md)
131
- \- Quick movie lookup (title, year, rating)
164
+ \- The quick example above.
132
165
 
133
166
  - [`movie-research/movie-research-basic.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/movie-research/movie-research-basic.form.md)
134
- \- Standard research with IMDB, Rotten Tomatoes, Metacritic
167
+ \- Standard movie research with IMDB, Rotten Tomatoes, Metacritic.
135
168
 
136
169
  - [`movie-research/movie-research-deep.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/movie-research/movie-research-deep.form.md)
137
- \- Comprehensive analysis with streaming, box office
170
+ \- Comprehensive movie analysis with streaming, box office, analysis.
138
171
 
139
172
  - [`simple/simple.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/simple/simple.form.md)
140
- \- Basic form demonstrating all field types
173
+ \- Basic form demonstrating all field kinds.
141
174
 
142
175
  - [`earnings-analysis/earnings-analysis.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/earnings-analysis/earnings-analysis.form.md)
143
- \- Financial analysis form
144
-
145
- View them with `markform examples --list` or try them interactively.
146
-
147
- ## Supported Providers
148
-
149
- Standard LLMs can be used to fill in forms or create research reports from form
150
- templates. The package currently has support for these models built in, and enables web
151
- search tools for them if possible.
152
-
153
- | Provider | Env Variable | Example Models |
154
- | --- | --- | --- |
155
- | openai | `OPENAI_API_KEY` | gpt-5-mini, gpt-5.1, gpt-5.2 |
156
- | anthropic | `ANTHROPIC_API_KEY` | claude-sonnet-4-5, claude-opus-4-5 |
157
- | google | `GOOGLE_API_KEY` | gemini-2.5-pro, gemini-2.5-flash |
158
- | xai | `XAI_API_KEY` | grok-4, grok-4-fast |
159
- | deepseek | `DEEPSEEK_API_KEY` | deepseek-chat, deepseek-reasoner |
160
-
161
- Set the appropriate environment variable for your provider before running `markform
162
- fill`. See
163
- [`src/settings.ts`](https://github.com/jlevy/markform/blob/main/packages/markform/src/settings.ts)
164
- for the full list of models.
176
+ \- Financial analysis form.
165
177
 
166
178
  ## Why?
167
179
 
@@ -250,9 +262,12 @@ markform serve my-form.form.md
250
262
  # Quick reference for writing forms (agent-friendly)
251
263
  markform docs
252
264
 
253
- # Full specification (SPEC.md)
265
+ # Full specification
254
266
  markform spec
255
267
 
268
+ # TypeScript and AI SDK API documentation
269
+ markform apis
270
+
256
271
  # This README
257
272
  markform readme
258
273
 
@@ -263,6 +278,25 @@ markform models
263
278
  markform --help
264
279
  ```
265
280
 
281
+ ## Supported Providers
282
+
283
+ Standard LLMs can be used to fill in forms or create research reports from form
284
+ templates. The package currently has support for these models built in, and enables web
285
+ search tools for them if possible.
286
+
287
+ | Provider | Env Variable | Example Models |
288
+ | --- | --- | --- |
289
+ | openai | `OPENAI_API_KEY` | gpt-5-mini, gpt-5.1, gpt-5.2 |
290
+ | anthropic | `ANTHROPIC_API_KEY` | claude-sonnet-4-5, claude-opus-4-5 |
291
+ | google | `GOOGLE_API_KEY` | gemini-2.5-pro, gemini-2.5-flash |
292
+ | xai | `XAI_API_KEY` | grok-4, grok-4-fast |
293
+ | deepseek | `DEEPSEEK_API_KEY` | deepseek-chat, deepseek-reasoner |
294
+
295
+ Set the appropriate environment variable for your provider before running `markform
296
+ fill`. See
297
+ [`src/settings.ts`](https://github.com/jlevy/markform/blob/main/packages/markform/src/settings.ts)
298
+ for the full list of models.
299
+
266
300
  ## Architecture
267
301
 
268
302
  ```mermaid
@@ -270,7 +304,7 @@ flowchart LR
270
304
  subgraph SPEC["<b>MARKFORM SPEC</b>"]
271
305
  direction TB
272
306
 
273
- subgraph L1["<b>LAYER 1: SYNTAX</b><br/>Markdoc tag syntax and frontmatter (form, field-group, string-field, checkboxes, etc.)"]
307
+ subgraph L1["<b>LAYER 1: SYNTAX</b><br/>Markdoc tag syntax and frontmatter (form, group, string-field, checkboxes, etc.)"]
274
308
  end
275
309
 
276
310
  subgraph L2["<b>LAYER 2: FORM DATA MODEL</b><br/>Schema definitions for forms, fields, values (in Zod but mappable to JSON Schema or Pydantic)"]
@@ -391,7 +425,8 @@ But it’s been useful for me already.
391
425
 
392
426
  It’s all written by LLMs but using a strongly spec-driven process, using rules from
393
427
  [Speculate](https://github.com/jlevy/speculate).
394
- See [the spec](SPEC.md) and the architecture docs and specs in [docs/](docs/).
428
+ See [the spec](docs/markform-spec.md) and the architecture docs and specs in
429
+ [docs/](docs/).
395
430
 
396
431
  ### What are the goals of Markform?
397
432
 
@@ -446,12 +481,13 @@ Not really. The closest alternatives are:
446
481
  human-friendly UI. But these do not have a human-friendly text format for use by
447
482
  agents as well as humans.
448
483
 
449
- | Approach | Human-readable | Agent-editable | Custom validations |
450
- | --- | :---: | :---: | :---: |
451
- | Plain Markdown | ✅ | ⚠️ fragile | ❌ |
452
- | JSON Schema | | ✅ | ✅ |
453
- | PDF Forms, SaaS tools | ⚠️ | | ⚠️ |
454
- | **Markform** | ✅ | | ✅ |
484
+ | Approach | Has GUI | Human-readable text format | Agent-editable | APIs and validation rules |
485
+ | --- | :---: | :---: | :---: | :---: |
486
+ | Plain Markdown | ☑️ existing tools | ✅ | ⚠️ fragile | ❌ |
487
+ | JSON with schema | ☑️ existing tools | ⚠️ hey it’s JSON | ✅ | ✅ |
488
+ | SaaS tools (Typeform, Docusign, PDF forms) | ✅ | ⚠️ rarely | ⚠️ if they add it | ⚠️ if they add it |
489
+ | Excel/Google Sheets | ✅ | .xlsx | ⚠️ with tools | ✅ |
490
+ | **Markform** | ☑️ existing tools | ✅ | ✅ | ✅ |
455
491
 
456
492
  ### What are example use cases?
457
493
 
@@ -496,11 +532,15 @@ Or see [markdoc/language-server](https://github.com/markdoc/language-server).
496
532
  ## Documentation
497
533
 
498
534
  - **[Quick
499
- Reference](https://github.com/jlevy/markform/blob/main/packages/markform/DOCS.md)**
535
+ Reference](https://github.com/jlevy/markform/blob/main/docs/markform-reference.md)**
500
536
  (or run `markform docs`) - Concise syntax reference (agent-friendly)
501
537
 
502
- - **[Markform Spec](https://github.com/jlevy/markform/blob/main/SPEC.md)** (or run
503
- `markform spec`) - Complete syntax and semantics
538
+ - **[Markform Spec](https://github.com/jlevy/markform/blob/main/docs/markform-spec.md)**
539
+ (or run `markform spec`) - Complete syntax and semantics
540
+
541
+ - **[API
542
+ Documentation](https://github.com/jlevy/markform/blob/main/docs/markform-apis.md)**
543
+ (or run `markform apis`) - TypeScript and AI SDK APIs
504
544
 
505
545
  - **[Design
506
546
  Doc](https://github.com/jlevy/markform/blob/main/docs/project/architecture/current/arch-markform-design.md)**
package/dist/ai-sdk.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { H as Id, L as FormSchema, Sn as ValidatorRegistry, _t as ParsedForm, j as FieldResponse, q as InspectResult, r as ApplyResult, vt as Patch, yt as PatchSchema } from "./coreTypes-BXhhz9Iq.mjs";
3
+ import { Dt as PatchSchema, Et as Patch, G as FormSchema, Tt as ParsedForm, X as Id, ar as ValidatorRegistry, r as ApplyResult, tt as InspectResult, z as FieldResponse } from "./coreTypes-9XZSNOv6.mjs";
4
4
  import { z } from "zod";
5
5
 
6
6
  //#region src/integrations/toolTypes.d.ts
@@ -62,7 +62,7 @@ interface MarkformToolSet {
62
62
  markform_get_markdown?: MarkformTool<Record<string, never>, GetMarkdownToolResult>;
63
63
  }
64
64
  //#endregion
65
- //#region src/integrations/ai-sdk.d.ts
65
+ //#region src/integrations/vercelAiSdkTools.d.ts
66
66
  /**
67
67
  * Session store for managing form state during AI interactions.
68
68
  *
package/dist/ai-sdk.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { N as PatchSchema } from "./coreTypes-Dful87E0.mjs";
2
- import { r as inspect, t as applyPatches, u as serialize } from "./apply-00UmzDKL.mjs";
1
+ import { L as PatchSchema } from "./coreTypes-pyctKRgc.mjs";
2
+ import { r as inspect, t as applyPatches, u as serialize } from "./apply-BCCiJzQr.mjs";
3
3
  import { z } from "zod";
4
4
 
5
- //#region src/integrations/ai-sdk.ts
5
+ //#region src/integrations/vercelAiSdkTools.ts
6
6
  /**
7
7
  * AI SDK Integration for Markform.
8
8
  *
@@ -63,7 +63,7 @@ const InspectInputSchema = z.object({}).describe("No input parameters required.
63
63
  /**
64
64
  * Input schema for markform_apply tool.
65
65
  */
66
- const ApplyInputSchema = z.object({ patches: z.array(PatchSchema).min(1).max(20).describe("Array of patches to apply to the form. Each patch sets or clears a field value. Operations: set_string, set_number, set_string_list, set_single_select, set_multi_select, set_checkboxes, clear_field. Example: [{ \"op\": \"set_string\", \"fieldId\": \"name\", \"value\": \"Alice\" }]") }).describe("Apply patches to update form field values.");
66
+ const ApplyInputSchema = z.object({ patches: z.array(PatchSchema).min(1).max(20).describe("Array of patches to apply to the form. Each patch sets or clears a field value. Operations: set_string, set_number, set_string_list, set_single_select, set_multi_select, set_checkboxes, set_url, set_url_list, set_date, set_year, set_table, clear_field, skip_field, abort_field. Example: [{ \"op\": \"set_string\", \"fieldId\": \"name\", \"value\": \"Alice\" }]") }).describe("Apply patches to update form field values.");
67
67
  /**
68
68
  * Input schema for markform_export tool (no parameters).
69
69
  */
@@ -115,7 +115,7 @@ function createMarkformTools(options) {
115
115
  }
116
116
  },
117
117
  markform_apply: {
118
- description: "Apply patches to update form field values. Use this after inspecting the form to set values for fields that need to be filled. Patches are applied as a transaction - all succeed or all fail. Returns the updated form state and any remaining issues. Patch operations: set_string, set_number, set_string_list, set_single_select, set_multi_select, set_checkboxes, clear_field.",
118
+ description: "Apply patches to update form field values. Use this after inspecting the form to set values for fields that need to be filled. Patches are applied as a transaction - all succeed or all fail. Returns the updated form state and any remaining issues. Patch operations: set_string, set_number, set_string_list, set_single_select, set_multi_select, set_checkboxes, set_url, set_url_list, set_date, set_year, set_table, clear_field, skip_field, abort_field.",
119
119
  inputSchema: ApplyInputSchema,
120
120
  execute: ({ patches }) => {
121
121
  const form = sessionStore.getForm();