markform 0.1.19 → 0.1.21

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 (46) hide show
  1. package/README.md +14 -10
  2. package/dist/ai-sdk.d.mts +1 -1
  3. package/dist/ai-sdk.mjs +2 -2
  4. package/dist/{apply-Dalpt-D6.mjs → apply-CD-t7ovb.mjs} +95 -24
  5. package/dist/apply-CD-t7ovb.mjs.map +1 -0
  6. package/dist/bin.mjs +1 -1
  7. package/dist/{cli-tpvFNqFY.mjs → cli-ChdIy1a7.mjs} +981 -24
  8. package/dist/cli-ChdIy1a7.mjs.map +1 -0
  9. package/dist/cli.mjs +1 -1
  10. package/dist/{coreTypes-CkxML8g2.d.mts → coreTypes-BQrWf_Wt.d.mts} +28 -2
  11. package/dist/{coreTypes-CPKXf2dc.mjs → coreTypes-CTLr-NGd.mjs} +24 -3
  12. package/dist/coreTypes-CTLr-NGd.mjs.map +1 -0
  13. package/dist/index.d.mts +23 -6
  14. package/dist/index.mjs +5 -5
  15. package/dist/{session-ZHBi3LVQ.mjs → session-BPuQ-ok0.mjs} +1 -1
  16. package/dist/{session-CK0x28RO.mjs → session-ZgegwtkT.mjs} +2 -2
  17. package/dist/{session-CK0x28RO.mjs.map → session-ZgegwtkT.mjs.map} +1 -1
  18. package/dist/{src-BTyz-wS6.mjs → src-DOPe4tmu.mjs} +356 -176
  19. package/dist/src-DOPe4tmu.mjs.map +1 -0
  20. package/docs/markform-reference.md +15 -1
  21. package/examples/movie-research/movie-deep-research-mock-filled.form.md +320 -343
  22. package/examples/movie-research/movie-deep-research.form.md +273 -308
  23. package/examples/movie-research/movie-research-demo.form.md +27 -41
  24. package/examples/parallel/parallel-research.form.md +33 -29
  25. package/examples/parallel/parallel-research.mock.filled.form.md +88 -0
  26. package/examples/rejection-test/rejection-test-mock-filled.form.md +21 -16
  27. package/examples/rejection-test/rejection-test-mock-filled.schema.json +1 -1
  28. package/examples/rejection-test/rejection-test.form.md +17 -15
  29. package/examples/rejection-test/rejection-test.session.yaml +88 -60
  30. package/examples/simple/simple-mock-filled.form.md +113 -126
  31. package/examples/simple/simple-mock-filled.schema.json +2 -3
  32. package/examples/simple/simple-skipped-filled.form.md +112 -129
  33. package/examples/simple/simple-skipped-filled.schema.json +2 -3
  34. package/examples/simple/simple-tags-syntax.form.md +32 -0
  35. package/examples/simple/simple-with-skips.session.yaml +663 -627
  36. package/examples/simple/simple.form.md +97 -113
  37. package/examples/simple/simple.schema.json +2 -3
  38. package/examples/simple/simple.session.yaml +663 -627
  39. package/examples/startup-deep-research/startup-deep-research.form.md +191 -235
  40. package/examples/startup-research/startup-research-mock-filled.form.md +128 -147
  41. package/examples/startup-research/startup-research.form.md +90 -129
  42. package/package.json +8 -8
  43. package/dist/apply-Dalpt-D6.mjs.map +0 -1
  44. package/dist/cli-tpvFNqFY.mjs.map +0 -1
  45. package/dist/coreTypes-CPKXf2dc.mjs.map +0 -1
  46. package/dist/src-BTyz-wS6.mjs.map +0 -1
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Markform
2
2
 
3
- [![CI](https://github.com/jlevy/markform/actions/workflows/ci.yml/badge.svg)](https://github.com/jlevy/markform/actions/runs/21506874671)
4
- [![Coverage](https://raw.githubusercontent.com/jlevy/markform/main/badges/packages/markform/coverage-total.svg)](https://github.com/jlevy/markform/actions/runs/21506874671)
3
+ [![CI](https://github.com/jlevy/markform/actions/workflows/ci.yml/badge.svg)](https://github.com/jlevy/markform/actions/runs/21611973252)
4
+ [![Coverage](https://raw.githubusercontent.com/jlevy/markform/main/badges/packages/markform/coverage-total.svg)](https://github.com/jlevy/markform/actions/runs/21611973252)
5
5
  [![npm version](https://img.shields.io/npm/v/markform)](https://www.npmjs.com/package/markform)
6
6
  [![X Follow](https://img.shields.io/twitter/follow/ojoshe)](https://x.com/ojoshe)
7
7
 
@@ -529,7 +529,10 @@ markform --help
529
529
  ## API Key Setup
530
530
 
531
531
  Set the appropriate environment variable for your provider before running
532
- `markform fill`:
532
+ `markform fill`. The CLI automatically loads from `.env.local` and `.env` files in the
533
+ current directory.
534
+
535
+ Supported providers:
533
536
 
534
537
  | Provider | Env Variable | Native Web Search |
535
538
  | --- | --- | :---: |
@@ -587,7 +590,8 @@ if (result.status.ok) {
587
590
  }
588
591
  ```
589
592
 
590
- See the [API documentation](https://github.com/jlevy/markform/blob/main/docs/markform-apis.md)
593
+ See the
594
+ [API documentation](https://github.com/jlevy/markform/blob/main/docs/markform-apis.md)
591
595
  for options like parallel execution, callbacks, and checkpointing.
592
596
 
593
597
  ### AI SDK Integration
@@ -768,12 +772,14 @@ more on the philosophy behind “docs-as-data” that Markform extends to “for
768
772
  We could use XML tags, but Markdoc has some niceties like tagging Markdown AST nodes
769
773
  (`{% #some-id %}`) so I decided to go with this.
770
774
 
771
- ### Is there a VSCode plugin for Markform or Markdoc?
775
+ ### What editor settings work best?
776
+
777
+ **HTML comment syntax (recommended):** Regular Markdown mode works perfectly since
778
+ `<!-- tag -->` comments are standard Markdown.
772
779
 
773
- For quick syntax highlighting of `{% tag %}` syntax, install
780
+ **Markdoc syntax (`{% tag %}`):** Install
774
781
  [Better Jinja](https://marketplace.visualstudio.com/items?itemName=samuelcolvin.jinjahtml)
775
- and associate `.form.md` files with the `jinja-md` language mode in your VS Code
776
- settings:
782
+ and associate `.form.md` files with `jinja-md` mode:
777
783
 
778
784
  ```json
779
785
  "files.associations": {
@@ -781,8 +787,6 @@ settings:
781
787
  }
782
788
  ```
783
789
 
784
- Or see [markdoc/language-server](https://github.com/markdoc/language-server).
785
-
786
790
  ## License
787
791
 
788
792
  This project uses a dual licensing approach:
package/dist/ai-sdk.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- import { At as Patch, Mt as PatchSchema, U as FieldResponse, Y as FormSchema, at as InspectResult, et as Id, kt as ParsedForm, mr as ValidatorRegistry, r as ApplyResult } from "./coreTypes-CkxML8g2.mjs";
2
+ import { At as ParsedForm, Nt as PatchSchema, U as FieldResponse, Y as FormSchema, at as InspectResult, et as Id, hr as ValidatorRegistry, jt as Patch, r as ApplyResult } from "./coreTypes-BQrWf_Wt.mjs";
3
3
  import { z } from "zod";
4
4
 
5
5
  //#region src/integrations/toolTypes.d.ts
package/dist/ai-sdk.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
- import { L as PatchSchema } from "./coreTypes-CPKXf2dc.mjs";
3
- import { d as serializeForm, i as inspect, t as applyPatches } from "./apply-Dalpt-D6.mjs";
2
+ import { R as PatchSchema } from "./coreTypes-CTLr-NGd.mjs";
3
+ import { d as serializeForm, i as inspect, t as applyPatches } from "./apply-CD-t7ovb.mjs";
4
4
  import { z } from "zod";
5
5
 
6
6
  //#region src/integrations/vercelAiSdkTools.ts
@@ -2,7 +2,7 @@
2
2
  import YAML from "yaml";
3
3
 
4
4
  //#region src/errors.ts
5
- const VERSION = "0.1.19";
5
+ const VERSION = "0.1.21";
6
6
  /**
7
7
  * Base error class for all markform errors.
8
8
  * Consumers can catch this to handle any markform error.
@@ -359,6 +359,56 @@ const MAX_FORMS_IN_MENU = 30;
359
359
  */
360
360
  const DEFAULT_PORT = 3344;
361
361
  /**
362
+ * Default line width for YAML output.
363
+ * Long strings will wrap at this column for readability.
364
+ * 88 is a common line width that works well with most editors.
365
+ */
366
+ const DEFAULT_YAML_LINE_WIDTH = 88;
367
+ /**
368
+ * YAML stringify options for readable output.
369
+ * - No forced quoting (YAML only quotes when necessary)
370
+ * - lineWidth provides reasonable wrapping for long strings
371
+ * - Plain keys without quotes
372
+ */
373
+ const YAML_STRINGIFY_OPTIONS = {
374
+ lineWidth: DEFAULT_YAML_LINE_WIDTH,
375
+ defaultKeyType: "PLAIN"
376
+ };
377
+ /**
378
+ * Mapping between YAML snake_case keys and TypeScript camelCase keys
379
+ * for harness configuration. Single source of truth for all transformations.
380
+ */
381
+ const HARNESS_CONFIG_MAPPING = {
382
+ max_turns: "maxTurns",
383
+ max_patches_per_turn: "maxPatchesPerTurn",
384
+ max_issues_per_turn: "maxIssuesPerTurn",
385
+ max_parallel_agents: "maxParallelAgents"
386
+ };
387
+ /**
388
+ * Transform harness config from YAML snake_case to TypeScript camelCase.
389
+ * Used by the parser when reading frontmatter.
390
+ */
391
+ function transformHarnessConfigToTs(yaml) {
392
+ const result = {};
393
+ for (const [snakeKey, camelKey] of Object.entries(HARNESS_CONFIG_MAPPING)) {
394
+ const value = yaml[snakeKey];
395
+ if (value !== void 0) result[camelKey] = value;
396
+ }
397
+ return result;
398
+ }
399
+ /**
400
+ * Transform harness config from TypeScript camelCase to YAML snake_case.
401
+ * Used by the serializer when writing frontmatter.
402
+ */
403
+ function transformHarnessConfigToYaml(ts) {
404
+ const result = {};
405
+ for (const [snakeKey, camelKey] of Object.entries(HARNESS_CONFIG_MAPPING)) {
406
+ const value = ts[camelKey];
407
+ if (value !== void 0) result[snakeKey] = value;
408
+ }
409
+ return result;
410
+ }
411
+ /**
362
412
  * Default maximum turns for the fill harness.
363
413
  * Prevents runaway loops during agent execution.
364
414
  */
@@ -413,6 +463,24 @@ const REPORT_EXTENSION = ".report.md";
413
463
  */
414
464
  const SCHEMA_EXTENSION = ".schema.json";
415
465
  /**
466
+ * Fill record extension - sidecar file containing execution metadata.
467
+ * Generated by `markform fill --record-fill` and read by `markform serve`.
468
+ *
469
+ * **Recommended naming convention:**
470
+ * - Form file: `document.form.md` → Fill record: `document.fill.json`
471
+ * - Form file: `document.md` → Fill record: `document.fill.json`
472
+ *
473
+ * Using `.form.md` for forms and `.fill.json` for fill records helps tools
474
+ * discover related files automatically. The CLI enforces this convention.
475
+ *
476
+ * The fill record contains:
477
+ * - Session timing and duration
478
+ * - LLM token usage (input/output)
479
+ * - Tool call timeline with results
480
+ * - Form progress at completion
481
+ */
482
+ const FILL_RECORD_EXTENSION = ".fill.json";
483
+ /**
416
484
  * All recognized markform file extensions.
417
485
  * Combines export formats with report and schema formats.
418
486
  */
@@ -471,6 +539,22 @@ function deriveSchemaPath(basePath) {
471
539
  }
472
540
  return base + SCHEMA_EXTENSION;
473
541
  }
542
+ /**
543
+ * Derive fill record sidecar path from a form file path.
544
+ *
545
+ * **Convention:**
546
+ * - `document.form.md` → `document.fill.json`
547
+ * - `document.md` → `document.fill.json`
548
+ *
549
+ * Priority: strips `.form.md` first, then falls back to `.md`.
550
+ * This ensures the recommended `.form.md` extension is handled correctly
551
+ * while also supporting plain `.md` files.
552
+ */
553
+ function deriveFillRecordPath(formPath) {
554
+ if (formPath.endsWith(EXPORT_EXTENSIONS.form)) return formPath.slice(0, -EXPORT_EXTENSIONS.form.length) + FILL_RECORD_EXTENSION;
555
+ if (formPath.endsWith(".md")) return formPath.slice(0, -3) + FILL_RECORD_EXTENSION;
556
+ return formPath + FILL_RECORD_EXTENSION;
557
+ }
474
558
 
475
559
  //#endregion
476
560
  //#region src/engine/parseHelpers.ts
@@ -2083,27 +2167,17 @@ function serializeFormSchema(schema, responses, docs, notes) {
2083
2167
  return lines.join("\n");
2084
2168
  }
2085
2169
  /**
2086
- * Build harness config object for YAML output (camelCase to snake_case).
2087
- */
2088
- function buildHarnessConfig(config) {
2089
- const result = {};
2090
- if (config.maxTurns !== void 0) result.max_turns = config.maxTurns;
2091
- if (config.maxPatchesPerTurn !== void 0) result.max_patches_per_turn = config.maxPatchesPerTurn;
2092
- if (config.maxIssuesPerTurn !== void 0) result.max_issues_per_turn = config.maxIssuesPerTurn;
2093
- if (config.maxParallelAgents !== void 0) result.max_parallel_agents = config.maxParallelAgents;
2094
- return result;
2095
- }
2096
- /**
2097
2170
  * Build frontmatter YAML from form metadata.
2098
- * Preserves roles, role_instructions, harness config, and run_mode.
2171
+ * Preserves title, description, roles, role_instructions, harness config, and run_mode.
2099
2172
  */
2100
2173
  function buildFrontmatter(metadata, specVersion) {
2101
2174
  const markformSection = { spec: specVersion };
2175
+ if (metadata?.title) markformSection.title = metadata.title;
2176
+ if (metadata?.description) markformSection.description = metadata.description;
2102
2177
  if (metadata?.runMode) markformSection.run_mode = metadata.runMode;
2103
- if (metadata?.harnessConfig && Object.keys(metadata.harnessConfig).length > 0) markformSection.harness = buildHarnessConfig(metadata.harnessConfig);
2104
- const frontmatterObj = { markform: markformSection };
2178
+ if (metadata?.harnessConfig && Object.keys(metadata.harnessConfig).length > 0) markformSection.harness = transformHarnessConfigToYaml(metadata.harnessConfig);
2105
2179
  const defaultRoles = ["user", "agent"];
2106
- if (metadata?.roles && (metadata.roles.length !== defaultRoles.length || !metadata.roles.every((r, i) => r === defaultRoles[i]))) frontmatterObj.roles = metadata.roles;
2180
+ if (metadata?.roles && (metadata.roles.length !== defaultRoles.length || !metadata.roles.every((r, i) => r === defaultRoles[i]))) markformSection.roles = metadata.roles;
2107
2181
  const defaultInstructions = {
2108
2182
  user: "",
2109
2183
  agent: ""
@@ -2111,13 +2185,10 @@ function buildFrontmatter(metadata, specVersion) {
2111
2185
  if (metadata?.roleInstructions) {
2112
2186
  if (Object.entries(metadata.roleInstructions).some(([role, instruction]) => {
2113
2187
  return instruction !== (defaultInstructions[role] ?? "") && instruction.trim() !== "";
2114
- })) frontmatterObj.role_instructions = metadata.roleInstructions;
2188
+ })) markformSection.role_instructions = metadata.roleInstructions;
2115
2189
  }
2116
- return `---\n${YAML.stringify(frontmatterObj, {
2117
- lineWidth: 0,
2118
- defaultStringType: "QUOTE_DOUBLE",
2119
- defaultKeyType: "PLAIN"
2120
- })}---`;
2190
+ const frontmatterObj = { markform: markformSection };
2191
+ return `---\n${YAML.stringify(frontmatterObj, YAML_STRINGIFY_OPTIONS)}---`;
2121
2192
  }
2122
2193
  /**
2123
2194
  * Serialize a ParsedForm to canonical Markdoc markdown format.
@@ -4259,5 +4330,5 @@ function applyPatches(form, patches) {
4259
4330
  }
4260
4331
 
4261
4332
  //#endregion
4262
- export { WEB_SEARCH_CONFIG as $, parseOptionText as A, DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN as B, extractTableContent as C, getStringAttr as D, getStringArrayAttr as E, DEFAULT_MAX_PATCHES_PER_TURN as F, REPORT_EXTENSION as G, DEFAULT_ROLES as H, DEFAULT_MAX_STEPS_PER_TURN as I, deriveReportPath as J, USER_ROLE as K, DEFAULT_MAX_TURNS as L, DEFAULT_FORMS_DIR as M, DEFAULT_MAX_ISSUES_PER_TURN as N, getValidateAttr as O, DEFAULT_MAX_PARALLEL_AGENTS as P, SUGGESTED_LLMS as Q, DEFAULT_PORT as R, extractOptionItems as S, getNumberAttr as T, DEFAULT_ROLE_INSTRUCTIONS as U, DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN as V, MAX_FORMS_IN_MENU as W, detectFileType as X, deriveSchemaPath as Y, parseRolesFlag as Z, preprocessCommentSyntax as _, isPatchError as _t, validate as a, MarkformConfigError as at, CHECKBOX_MARKERS as b, computeProgressSummary as c, MarkformParseError as ct, serializeForm as d, ParseError as dt, formatSuggestedLlms as et, serializeRawMarkdown as f, isAbortError as ft, detectSyntaxStyle as g, isParseError as gt, friendlyUrlAbbrev as h, isMarkformError as ht, inspect as i, MarkformAbortError as it, AGENT_ROLE as j, isTagNode as k, computeStructureSummary as l, MarkformPatchError as lt, formatBareUrlsAsHtmlLinks as m, isLlmError as mt, getAllFields as n, hasWebSearchSupport as nt, computeAllSummaries as o, MarkformError as ot, serializeReport as p, isConfigError as pt, deriveExportPath as q, getFieldsForRoles as r, parseModelIdForDisplay as rt, computeFormState as s, MarkformLlmError as st, applyPatches as t, getWebSearchConfig as tt, isFormComplete as u, MarkformValidationError as ut, validateSyntaxConsistency as v, isRetryableError as vt, getBooleanAttr as w, extractFenceValue as x, tryParseSentinelResponse as y, isValidationError as yt, DEFAULT_PRIORITY as z };
4263
- //# sourceMappingURL=apply-Dalpt-D6.mjs.map
4333
+ export { transformHarnessConfigToTs as $, parseOptionText as A, DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN as B, extractTableContent as C, getStringAttr as D, getStringArrayAttr as E, DEFAULT_MAX_PATCHES_PER_TURN as F, REPORT_EXTENSION as G, DEFAULT_ROLES as H, DEFAULT_MAX_STEPS_PER_TURN as I, deriveFillRecordPath as J, USER_ROLE as K, DEFAULT_MAX_TURNS as L, DEFAULT_FORMS_DIR as M, DEFAULT_MAX_ISSUES_PER_TURN as N, getValidateAttr as O, DEFAULT_MAX_PARALLEL_AGENTS as P, parseRolesFlag as Q, DEFAULT_PORT as R, extractOptionItems as S, getNumberAttr as T, DEFAULT_ROLE_INSTRUCTIONS as U, DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN as V, MAX_FORMS_IN_MENU as W, deriveSchemaPath as X, deriveReportPath as Y, detectFileType as Z, preprocessCommentSyntax as _, isMarkformError as _t, validate as a, parseModelIdForDisplay as at, CHECKBOX_MARKERS as b, isRetryableError as bt, computeProgressSummary as c, MarkformError as ct, serializeForm as d, MarkformPatchError as dt, SUGGESTED_LLMS as et, serializeRawMarkdown as f, MarkformValidationError as ft, detectSyntaxStyle as g, isLlmError as gt, friendlyUrlAbbrev as h, isConfigError as ht, inspect as i, hasWebSearchSupport as it, AGENT_ROLE as j, isTagNode as k, computeStructureSummary as l, MarkformLlmError as lt, formatBareUrlsAsHtmlLinks as m, isAbortError as mt, getAllFields as n, formatSuggestedLlms as nt, computeAllSummaries as o, MarkformAbortError as ot, serializeReport as p, ParseError as pt, deriveExportPath as q, getFieldsForRoles as r, getWebSearchConfig as rt, computeFormState as s, MarkformConfigError as st, applyPatches as t, WEB_SEARCH_CONFIG as tt, isFormComplete as u, MarkformParseError as ut, validateSyntaxConsistency as v, isParseError as vt, getBooleanAttr as w, extractFenceValue as x, isValidationError as xt, tryParseSentinelResponse as y, isPatchError as yt, DEFAULT_PRIORITY as z };
4334
+ //# sourceMappingURL=apply-CD-t7ovb.mjs.map