markform 0.1.2 → 0.1.3

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 CHANGED
@@ -41,7 +41,7 @@ npx markform examples
41
41
  This walks you through an example form interactively, with optional AI agent filling.
42
42
  You’ll need at least one [API key](#supported-providers) to have LLMs fill in forms.
43
43
 
44
- ### A Simple Form
44
+ ### A Minimal Form
45
45
 
46
46
  A `.form.md` file is simply a Markdoc file.
47
47
  It combines YAML frontmatter with Markdoc-tagged content:
@@ -50,39 +50,38 @@ It combines YAML frontmatter with Markdoc-tagged content:
50
50
  ---
51
51
  markform:
52
52
  spec: MF/0.1
53
- title: Movie Research (Simple)
54
- roles: # Who can fill fields
53
+ title: Movie Research (Minimal)
54
+ description: Quick movie lookup with just the essentials (title, year, ratings, summary).
55
+ roles:
55
56
  - user
56
57
  - agent
57
- role_instructions: # Instructions shown to each role
58
+ role_instructions:
58
59
  user: "Enter the movie title."
59
- agent: "Research the movie and fill in the details from IMDB."
60
+ agent: |
61
+ Quickly identify the movie and fill in basic info from IMDB.
62
+ This is a minimal lookup - just get the core facts.
60
63
  ---
64
+ {% form id="movie_research_minimal" title="Movie Research (Minimal)" %}
61
65
 
62
- {% form id="movie_research" title="Movie Research" %}
66
+ <!-- The first field group is filled in by the user (role="user"): -->
63
67
 
64
- {% field-group id="input" title="Input" %}
65
-
66
- <!-- User fills this field -->
68
+ {% field-group id="movie_input" title="Movie Identification" %}
67
69
 
68
70
  {% string-field id="movie" label="Movie" role="user" required=true minLength=1 maxLength=300 %}{% /string-field %}
69
-
70
- {% instructions ref="movie" %}
71
-
72
- <!-- Guidance for filling the field -->
73
-
74
- Enter the movie title (add any details to help identify, like "Barbie 2023" or "the Batman movie with Robert Pattinson").
75
- {% /instructions %}
71
+ {% instructions ref="movie" %}Enter the movie title (add year or details for disambiguation).{% /instructions %}
76
72
 
77
73
  {% /field-group %}
78
74
 
79
- {% field-group id="details" title="Movie Details" %}
75
+ <!-- Everything else is filled in by the agent (role="agent"): -->
80
76
 
81
- <!-- Agent researches and fills these fields -->
77
+ {% field-group id="about_the_movie" title="About the Movie" %}
82
78
 
83
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 %}
84
81
 
85
- {% number-field id="year" label="Release Year" role="agent" min=1888 max=2030 %}{% /number-field %}
82
+ {% number-field id="year" label="Release Year" role="agent" required=true min=1888 max=2030 %}{% /number-field %}
83
+
84
+ {% url-field id="imdb_url" label="IMDB URL" role="agent" required=true %}{% /url-field %}
86
85
 
87
86
  {% single-select id="mpaa_rating" label="MPAA Rating" role="agent" %}
88
87
  - [ ] G {% #g %}
@@ -93,21 +92,22 @@ Enter the movie title (add any details to help identify, like "Barbie 2023" or "
93
92
  - [ ] NR/Unrated {% #nr %}
94
93
  {% /single-select %}
95
94
 
96
- {% url-field id="imdb_url" label="IMDB URL" role="agent" %}{% /url-field %}
97
-
98
95
  {% number-field id="imdb_rating" label="IMDB Rating" role="agent" min=1.0 max=10.0 %}{% /number-field %}
96
+ {% instructions ref="imdb_rating" %}IMDB user rating (1.0-10.0 scale).{% /instructions %}
99
97
 
100
- {% string-field id="logline" label="Summary" role="agent" maxLength=200 %}{% /string-field %}
98
+ {% string-field id="logline" label="One-Line Summary" role="agent" maxLength=300 %}{% /string-field %}
99
+ {% instructions ref="logline" %}Brief plot summary in 1-2 sentences, no spoilers.{% /instructions %}
101
100
 
102
101
  {% /field-group %}
103
102
 
104
103
  {% /form %}
105
104
  ```
106
105
 
107
- This is a simplified version of the [full movie research
108
- form](https://github.com/jlevy/markform/blob/main/packages/markform/examples/movie-research/movie-research.form.md),
109
- which includes multiple rating sources (IMDB, Rotten Tomatoes, Metacritic), detailed
110
- instructions, and harness configuration.
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.
111
111
 
112
112
  **Key concepts:**
113
113
 
@@ -282,7 +282,9 @@ flowchart LR
282
282
  subgraph L4["<b>LAYER 4: TOOL API & INTERFACES</b><br/>Abstract API for agents and humans (TypeScript and AI SDK integration)"]
283
283
  end
284
284
 
285
- L4 --> L3 --> L2 --> L1
285
+ L4 -->
286
+
287
+ L3 --> L2 --> L1
286
288
  end
287
289
 
288
290
  subgraph IMPL["<b>THIS IMPLEMENTATION</b>"]
package/dist/ai-sdk.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { N as PatchSchema } from "./coreTypes-Dful87E0.mjs";
2
- import { r as inspect, t as applyPatches, u as serialize } from "./apply-BfAGTHMh.mjs";
2
+ import { r as inspect, t as applyPatches, u as serialize } from "./apply-00UmzDKL.mjs";
3
3
  import { z } from "zod";
4
4
 
5
5
  //#region src/integrations/ai-sdk.ts
@@ -233,6 +233,18 @@ function deriveExportPath(basePath, format) {
233
233
  }
234
234
  return base + EXPORT_EXTENSIONS[format];
235
235
  }
236
+ /**
237
+ * Derive report path from any markform file path.
238
+ * Strips known extensions and appends .report.md.
239
+ */
240
+ function deriveReportPath(basePath) {
241
+ let base = basePath;
242
+ for (const ext of Object.values(ALL_EXTENSIONS)) if (base.endsWith(ext)) {
243
+ base = base.slice(0, -ext.length);
244
+ break;
245
+ }
246
+ return base + REPORT_EXTENSION;
247
+ }
236
248
 
237
249
  //#endregion
238
250
  //#region src/engine/serialize.ts
@@ -2467,4 +2479,4 @@ function applyPatches(form, patches) {
2467
2479
  }
2468
2480
 
2469
2481
  //#endregion
2470
- export { SUGGESTED_LLMS as A, DEFAULT_ROLE_INSTRUCTIONS as C, detectFileType as D, deriveExportPath as E, formatSuggestedLlms as M, getWebSearchConfig as N, getFormsDir as O, hasWebSearchSupport as P, DEFAULT_ROLES as S, USER_ROLE as T, DEFAULT_MAX_TURNS as _, computeAllSummaries as a, DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN as b, computeStructureSummary as c, serializeRawMarkdown as d, serializeReportMarkdown as f, DEFAULT_MAX_PATCHES_PER_TURN as g, DEFAULT_MAX_ISSUES_PER_TURN as h, validate as i, WEB_SEARCH_CONFIG as j, parseRolesFlag as k, isFormComplete as l, DEFAULT_FORMS_DIR as m, getFieldsForRoles as n, computeFormState as o, AGENT_ROLE as p, inspect as r, computeProgressSummary as s, applyPatches as t, serialize as u, DEFAULT_PORT as v, REPORT_EXTENSION as w, DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN as x, DEFAULT_PRIORITY as y };
2482
+ export { parseRolesFlag as A, DEFAULT_ROLE_INSTRUCTIONS as C, deriveReportPath as D, deriveExportPath as E, hasWebSearchSupport as F, WEB_SEARCH_CONFIG as M, formatSuggestedLlms as N, detectFileType as O, getWebSearchConfig as P, DEFAULT_ROLES as S, USER_ROLE as T, DEFAULT_MAX_TURNS as _, computeAllSummaries as a, DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN as b, computeStructureSummary as c, serializeRawMarkdown as d, serializeReportMarkdown as f, DEFAULT_MAX_PATCHES_PER_TURN as g, DEFAULT_MAX_ISSUES_PER_TURN as h, validate as i, SUGGESTED_LLMS as j, getFormsDir as k, isFormComplete as l, DEFAULT_FORMS_DIR as m, getFieldsForRoles as n, computeFormState as o, AGENT_ROLE as p, inspect as r, computeProgressSummary as s, applyPatches as t, serialize as u, DEFAULT_PORT as v, REPORT_EXTENSION as w, DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN as x, DEFAULT_PRIORITY as y };
package/dist/bin.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import "./coreTypes-Dful87E0.mjs";
3
- import "./apply-BfAGTHMh.mjs";
4
- import "./src-BXRkGFpG.mjs";
3
+ import "./apply-00UmzDKL.mjs";
4
+ import "./src-Dm8jZ5dl.mjs";
5
5
  import "./session-Bqnwi9wp.mjs";
6
6
  import "./shared-N_s1M-_K.mjs";
7
- import { t as runCli } from "./cli-B3NVm6zL.mjs";
7
+ import { t as runCli } from "./cli-D--Lel-e.mjs";
8
8
  import { resolve } from "node:path";
9
9
  import { existsSync } from "node:fs";
10
10
  import { config } from "dotenv";
@@ -1,6 +1,6 @@
1
1
  import { N as PatchSchema } from "./coreTypes-Dful87E0.mjs";
2
- import { A as SUGGESTED_LLMS, D as detectFileType, E as deriveExportPath, M as formatSuggestedLlms, O as getFormsDir, P as hasWebSearchSupport, T as USER_ROLE, _ as DEFAULT_MAX_TURNS, b as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, d as serializeRawMarkdown, f as serializeReportMarkdown, g as DEFAULT_MAX_PATCHES_PER_TURN, h as DEFAULT_MAX_ISSUES_PER_TURN, j as WEB_SEARCH_CONFIG, k as parseRolesFlag, m as DEFAULT_FORMS_DIR, p as AGENT_ROLE, r as inspect, t as applyPatches, u as serialize, v as DEFAULT_PORT, w as REPORT_EXTENSION, x as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN } from "./apply-BfAGTHMh.mjs";
3
- import { a as resolveHarnessConfig, c as getProviderNames, f as createMockAgent, i as runResearch, l as resolveModel, m as createHarness, s as getProviderInfo, t as VERSION, u as createLiveAgent, v as parseForm } from "./src-BXRkGFpG.mjs";
2
+ import { A as parseRolesFlag, D as deriveReportPath, E as deriveExportPath, F as hasWebSearchSupport, M as WEB_SEARCH_CONFIG, N as formatSuggestedLlms, O as detectFileType, T as USER_ROLE, _ as DEFAULT_MAX_TURNS, b as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, d as serializeRawMarkdown, f as serializeReportMarkdown, g as DEFAULT_MAX_PATCHES_PER_TURN, h as DEFAULT_MAX_ISSUES_PER_TURN, j as SUGGESTED_LLMS, k as getFormsDir, m as DEFAULT_FORMS_DIR, p as AGENT_ROLE, r as inspect, t as applyPatches, u as serialize, v as DEFAULT_PORT, w as REPORT_EXTENSION, x as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN } from "./apply-00UmzDKL.mjs";
3
+ import { a as resolveHarnessConfig, c as getProviderNames, f as createMockAgent, i as runResearch, l as resolveModel, m as createHarness, s as getProviderInfo, t as VERSION, u as createLiveAgent, v as parseForm } from "./src-Dm8jZ5dl.mjs";
4
4
  import { n as serializeSession } from "./session-Bqnwi9wp.mjs";
5
5
  import { a as getCommandContext, c as logInfo, d as logVerbose, f as logWarn, h as writeFile, i as formatPath, l as logSuccess, n as ensureFormsDir, o as logDryRun, p as readFile$1, r as formatOutput, s as logError, t as OUTPUT_FORMATS, u as logTiming } from "./shared-N_s1M-_K.mjs";
6
6
  import YAML from "yaml";
@@ -334,23 +334,29 @@ function toNotesArray(form) {
334
334
  * Derive export paths from a base form path.
335
335
  * Uses centralized extension constants from settings.ts.
336
336
  *
337
+ * Standard exports: report, values (yaml), form.
338
+ * Raw markdown is available via CLI but not in standard exports.
339
+ *
337
340
  * @param basePath - Path to the .form.md file
338
341
  * @returns Object with paths for all export formats
339
342
  */
340
343
  function deriveExportPaths(basePath) {
341
344
  return {
342
- formPath: deriveExportPath(basePath, "form"),
343
- rawPath: deriveExportPath(basePath, "raw"),
344
- yamlPath: deriveExportPath(basePath, "yaml")
345
+ reportPath: deriveReportPath(basePath),
346
+ yamlPath: deriveExportPath(basePath, "yaml"),
347
+ formPath: deriveExportPath(basePath, "form")
345
348
  };
346
349
  }
347
350
  /**
348
351
  * Export form to multiple formats.
349
352
  *
350
- * Writes:
353
+ * Standard exports:
354
+ * - Report format (.report.md) - filtered markdown (excludes instructions, report=false)
355
+ * - YAML values (.yml) - structured format with state and notes
351
356
  * - Markform format (.form.md) - canonical form with directives
352
- * - Raw markdown (.raw.md) - plain readable markdown (no directives)
353
- * - YAML values (.yml) - structured format with state and notes (markform-218, markform-219)
357
+ *
358
+ * Note: Raw markdown (.raw.md) is available via CLI `markform export --raw`
359
+ * but is not included in standard multi-format export.
354
360
  *
355
361
  * @param form - The parsed form to export
356
362
  * @param basePath - Base path for the .form.md file (other paths are derived)
@@ -358,10 +364,8 @@ function deriveExportPaths(basePath) {
358
364
  */
359
365
  async function exportMultiFormat(form, basePath) {
360
366
  const paths = deriveExportPaths(basePath);
361
- const formContent = serialize(form);
362
- await writeFile(paths.formPath, formContent);
363
- const rawContent = serializeRawMarkdown(form);
364
- await writeFile(paths.rawPath, rawContent);
367
+ const reportContent = serializeReportMarkdown(form);
368
+ await writeFile(paths.reportPath, reportContent);
365
369
  const values = toStructuredValues(form);
366
370
  const notes = toNotesArray(form);
367
371
  const exportData = {
@@ -370,6 +374,8 @@ async function exportMultiFormat(form, basePath) {
370
374
  };
371
375
  const yamlContent = YAML.stringify(exportData);
372
376
  await writeFile(paths.yamlPath, yamlContent);
377
+ const formContent = serialize(form);
378
+ await writeFile(paths.formPath, formContent);
373
379
  return paths;
374
380
  }
375
381
 
@@ -1380,29 +1386,42 @@ async function viewFile(filePath) {
1380
1386
  /**
1381
1387
  * Show an interactive file viewer chooser.
1382
1388
  *
1383
- * Presents a list of files to view with descriptions, plus a Skip option.
1384
- * Loops until the user selects Skip.
1389
+ * Presents a list of files to view:
1390
+ * - "Show report:" for the report output (.report.md) at the top
1391
+ * - "Show source:" for other files (.form.md, .raw.md, .yml)
1392
+ * - "Quit" at the bottom
1393
+ *
1394
+ * Loops until the user selects Quit.
1385
1395
  *
1386
1396
  * @param files Array of file options to display
1387
1397
  */
1388
1398
  async function showFileViewerChooser(files) {
1389
1399
  if (!isInteractive$2()) return;
1390
1400
  console.log("");
1401
+ const reportFile = files.find((f) => f.path.endsWith(".report.md"));
1402
+ const sourceFiles = files.filter((f) => !f.path.endsWith(".report.md"));
1391
1403
  while (true) {
1392
- const options = [...files.map((file) => ({
1404
+ const options = [];
1405
+ if (reportFile) options.push({
1406
+ value: reportFile.path,
1407
+ label: `Show report: ${pc.green(basename(reportFile.path))}`,
1408
+ hint: reportFile.hint ?? ""
1409
+ });
1410
+ for (const file of sourceFiles) options.push({
1393
1411
  value: file.path,
1394
- label: pc.green(basename(file.path)),
1412
+ label: `Show source: ${pc.green(basename(file.path))}`,
1395
1413
  hint: file.hint ?? ""
1396
- })), {
1397
- value: "skip",
1398
- label: "Done viewing",
1399
- hint: "exit file viewer"
1400
- }];
1414
+ });
1415
+ options.push({
1416
+ value: "quit",
1417
+ label: "Quit",
1418
+ hint: ""
1419
+ });
1401
1420
  const selection = await p.select({
1402
- message: "View an output file?",
1421
+ message: "View files:",
1403
1422
  options
1404
1423
  });
1405
- if (p.isCancel(selection) || selection === "skip") break;
1424
+ if (p.isCancel(selection) || selection === "quit") break;
1406
1425
  await viewFile(selection);
1407
1426
  console.log("");
1408
1427
  }
@@ -1682,9 +1701,9 @@ async function runInteractiveFlow(preselectedId, formsDirOverride) {
1682
1701
  showInteractiveOutro(patches.length, false);
1683
1702
  console.log("");
1684
1703
  p.log.success("Outputs:");
1685
- console.log(` ${formatPath(userFillOutputs.formPath)} ${pc.dim("(markform)")}`);
1686
- console.log(` ${formatPath(userFillOutputs.rawPath)} ${pc.dim("(plain markdown)")}`);
1687
- console.log(` ${formatPath(userFillOutputs.yamlPath)} ${pc.dim("(values as YAML)")}`);
1704
+ console.log(` ${formatPath(userFillOutputs.reportPath)} ${pc.dim("(output report)")}`);
1705
+ console.log(` ${formatPath(userFillOutputs.yamlPath)} ${pc.dim("(output values)")}`);
1706
+ console.log(` ${formatPath(userFillOutputs.formPath)} ${pc.dim("(filled markform source)")}`);
1688
1707
  logTiming({
1689
1708
  verbose: false,
1690
1709
  format: "console",
@@ -1710,19 +1729,19 @@ async function runInteractiveFlow(preselectedId, formsDirOverride) {
1710
1729
  console.log(cliCommand);
1711
1730
  if (userFillOutputs) await showFileViewerChooser([
1712
1731
  {
1713
- path: userFillOutputs.formPath,
1714
- label: "Markform",
1715
- hint: "form with tags"
1732
+ path: userFillOutputs.reportPath,
1733
+ label: "Report",
1734
+ hint: "output report"
1716
1735
  },
1717
1736
  {
1718
- path: userFillOutputs.rawPath,
1719
- label: "Plain Markdown",
1720
- hint: "rendered output"
1737
+ path: userFillOutputs.yamlPath,
1738
+ label: "Values",
1739
+ hint: "output values"
1721
1740
  },
1722
1741
  {
1723
- path: userFillOutputs.yamlPath,
1724
- label: "YAML",
1725
- hint: "extracted values"
1742
+ path: userFillOutputs.formPath,
1743
+ label: "Form",
1744
+ hint: "filled markform source"
1726
1745
  }
1727
1746
  ]);
1728
1747
  p.outro("Happy form filling!");
@@ -1760,29 +1779,29 @@ async function runInteractiveFlow(preselectedId, formsDirOverride) {
1760
1779
  dryRun: false,
1761
1780
  quiet: false
1762
1781
  }, timingLabel, Date.now() - agentStartTime);
1763
- const { formPath, rawPath, yamlPath } = await exportMultiFormat(form, agentOutputPath);
1782
+ const { reportPath, yamlPath, formPath } = await exportMultiFormat(form, agentOutputPath);
1764
1783
  console.log("");
1765
1784
  const successMessage = isResearchExample ? "Research complete. Outputs:" : "Agent fill complete. Outputs:";
1766
1785
  p.log.success(successMessage);
1767
- console.log(` ${formatPath(formPath)} (markform)`);
1768
- console.log(` ${formatPath(rawPath)} (plain markdown)`);
1769
- console.log(` ${formatPath(yamlPath)} (values as YAML)`);
1786
+ console.log(` ${formatPath(reportPath)} ${pc.dim("(output report)")}`);
1787
+ console.log(` ${formatPath(yamlPath)} ${pc.dim("(output values)")}`);
1788
+ console.log(` ${formatPath(formPath)} ${pc.dim("(filled markform source)")}`);
1770
1789
  if (!success) p.log.warn("Agent did not complete all fields. You may need to run it again.");
1771
1790
  await showFileViewerChooser([
1772
1791
  {
1773
- path: formPath,
1774
- label: "Markform",
1775
- hint: "form with tags"
1792
+ path: reportPath,
1793
+ label: "Report",
1794
+ hint: "output report"
1776
1795
  },
1777
1796
  {
1778
- path: rawPath,
1779
- label: "Plain Markdown",
1780
- hint: "rendered output"
1797
+ path: yamlPath,
1798
+ label: "Values",
1799
+ hint: "output values"
1781
1800
  },
1782
1801
  {
1783
- path: yamlPath,
1784
- label: "YAML",
1785
- hint: "extracted values"
1802
+ path: formPath,
1803
+ label: "Form",
1804
+ hint: "filled markform source"
1786
1805
  }
1787
1806
  ]);
1788
1807
  } catch (error) {
@@ -1987,13 +2006,13 @@ function registerFillCommand(program) {
1987
2006
  logInfo(ctx, `[DRY RUN] Would write form to: ${outputPath$1}`);
1988
2007
  showInteractiveOutro(patches.length, false);
1989
2008
  } else {
1990
- const { formPath, rawPath, yamlPath } = await exportMultiFormat(form, outputPath$1);
2009
+ const { reportPath, yamlPath, formPath } = await exportMultiFormat(form, outputPath$1);
1991
2010
  showInteractiveOutro(patches.length, false);
1992
2011
  console.log("");
1993
2012
  p.log.success("Outputs:");
1994
- console.log(` ${formatPath(formPath)} ${pc.dim("(markform)")}`);
1995
- console.log(` ${formatPath(rawPath)} ${pc.dim("(plain markdown)")}`);
1996
- console.log(` ${formatPath(yamlPath)} ${pc.dim("(values as YAML)")}`);
2013
+ console.log(` ${formatPath(reportPath)} ${pc.dim("(output report)")}`);
2014
+ console.log(` ${formatPath(yamlPath)} ${pc.dim("(output values)")}`);
2015
+ console.log(` ${formatPath(formPath)} ${pc.dim("(filled markform source)")}`);
1997
2016
  }
1998
2017
  logTiming(ctx, "Fill time", durationMs$1);
1999
2018
  if (patches.length > 0) {
@@ -3721,11 +3740,11 @@ function registerResearchCommand(program) {
3721
3740
  logInfo(ctx, `Status: ${(result.status === "completed" ? pc.green : result.status === "max_turns_reached" ? pc.yellow : pc.red)(result.status)}`);
3722
3741
  logInfo(ctx, `Turns: ${result.totalTurns}`);
3723
3742
  if (result.inputTokens || result.outputTokens) logVerbose(ctx, `Tokens: ${result.inputTokens ?? 0} in, ${result.outputTokens ?? 0} out`);
3724
- const { formPath, rawPath, yamlPath } = await exportMultiFormat(result.form, outputPath);
3743
+ const { reportPath, yamlPath, formPath } = await exportMultiFormat(result.form, outputPath);
3725
3744
  logSuccess(ctx, "Outputs:");
3726
- console.log(` ${formPath} ${pc.dim("(markform)")}`);
3727
- console.log(` ${rawPath} ${pc.dim("(plain markdown)")}`);
3728
- console.log(` ${yamlPath} ${pc.dim("(values as YAML)")}`);
3745
+ console.log(` ${reportPath} ${pc.dim("(output report)")}`);
3746
+ console.log(` ${yamlPath} ${pc.dim("(output values)")}`);
3747
+ console.log(` ${formPath} ${pc.dim("(filled markform source)")}`);
3729
3748
  if (options.transcript && result.transcript) {
3730
3749
  const { serializeSession: serializeSession$1 } = await import("./session-DdAtY2Ni.mjs");
3731
3750
  const transcriptPath = outputPath.replace(/\.form\.md$/, ".session.yaml");
package/dist/cli.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import "./coreTypes-Dful87E0.mjs";
2
- import "./apply-BfAGTHMh.mjs";
3
- import "./src-BXRkGFpG.mjs";
2
+ import "./apply-00UmzDKL.mjs";
3
+ import "./src-Dm8jZ5dl.mjs";
4
4
  import "./session-Bqnwi9wp.mjs";
5
5
  import "./shared-N_s1M-_K.mjs";
6
- import { t as runCli } from "./cli-B3NVm6zL.mjs";
6
+ import { t as runCli } from "./cli-D--Lel-e.mjs";
7
7
 
8
8
  export { runCli };
package/dist/index.d.mts CHANGED
@@ -593,12 +593,12 @@ interface ResearchResult {
593
593
  outputTokens?: number;
594
594
  /** Tools available to the agent */
595
595
  availableTools?: string[];
596
- /** Path to saved .form.md file */
597
- formPath?: string;
598
- /** Path to saved .raw.md file */
599
- rawPath?: string;
596
+ /** Path to saved .report.md file */
597
+ reportPath?: string;
600
598
  /** Path to saved .yaml file */
601
599
  yamlPath?: string;
600
+ /** Path to saved .form.md file */
601
+ formPath?: string;
602
602
  }
603
603
  //#endregion
604
604
  //#region src/research/runResearch.d.ts
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { $ as StringFieldSchema, A as NumberValueSchema, B as SetCheckboxesPatchSchema, C as IssueReasonSchema, D as MultiSelectFieldSchema, E as MultiCheckboxStateSchema, F as ProgressStateSchema, G as SetStringPatchSchema, H as SetNumberPatchSchema, I as ProgressSummarySchema, J as SingleSelectFieldSchema, K as SeveritySchema, L as SessionFinalSchema, M as OptionSchema, N as PatchSchema, O as MultiSelectValueSchema, P as ProgressCountsSchema, Q as StepResultSchema, R as SessionTranscriptSchema, S as InspectResultSchema, T as MarkformFrontmatterSchema, U as SetSingleSelectPatchSchema, V as SetMultiSelectPatchSchema, W as SetStringListPatchSchema, X as SourcePositionSchema, Y as SingleSelectValueSchema, Z as SourceRangeSchema, _ as FieldValueSchema, a as CheckboxValueSchema, at as ValidatorRefSchema, b as IdSchema, c as ClearFieldPatchSchema, d as ExplicitCheckboxValueSchema, et as StringListFieldSchema, f as FieldGroupSchema, g as FieldSchema, h as FieldResponseSchema, i as CheckboxProgressCountsSchema, it as ValidationIssueSchema, j as OptionIdSchema, k as NumberFieldSchema, l as DocumentationBlockSchema, m as FieldProgressSchema, n as ApplyResultSchema, nt as StringValueSchema, o as CheckboxesFieldSchema, p as FieldKindSchema, q as SimpleCheckboxStateSchema, r as CheckboxModeSchema, rt as StructureSummarySchema, s as CheckboxesValueSchema, t as AnswerStateSchema, tt as StringListValueSchema, u as DocumentationTagSchema, v as FormSchemaSchema, w as IssueScopeSchema, x as InspectIssueSchema, y as HarnessConfigSchema, z as SessionTurnSchema } from "./coreTypes-Dful87E0.mjs";
2
- import { a as computeAllSummaries, c as computeStructureSummary, i as validate, l as isFormComplete, o as computeFormState, r as inspect, s as computeProgressSummary, t as applyPatches, u as serialize } from "./apply-BfAGTHMh.mjs";
3
- import { _ as findFieldById, a as resolveHarnessConfig, d as MockAgent, f as createMockAgent, g as coerceToFieldPatch, h as coerceInputContext, i as runResearch, m as createHarness, n as isResearchForm, o as fillForm, p as FormHarness, r as validateResearchForm, t as VERSION, v as parseForm, y as ParseError } from "./src-BXRkGFpG.mjs";
2
+ import { a as computeAllSummaries, c as computeStructureSummary, i as validate, l as isFormComplete, o as computeFormState, r as inspect, s as computeProgressSummary, t as applyPatches, u as serialize } from "./apply-00UmzDKL.mjs";
3
+ import { _ as findFieldById, a as resolveHarnessConfig, d as MockAgent, f as createMockAgent, g as coerceToFieldPatch, h as coerceInputContext, i as runResearch, m as createHarness, n as isResearchForm, o as fillForm, p as FormHarness, r as validateResearchForm, t as VERSION, v as parseForm, y as ParseError } from "./src-Dm8jZ5dl.mjs";
4
4
  import { n as serializeSession, t as parseSession } from "./session-Bqnwi9wp.mjs";
5
5
 
6
6
  export { AnswerStateSchema, ApplyResultSchema, CheckboxModeSchema, CheckboxProgressCountsSchema, CheckboxValueSchema, CheckboxesFieldSchema, CheckboxesValueSchema, ClearFieldPatchSchema, DocumentationBlockSchema, DocumentationTagSchema, ExplicitCheckboxValueSchema, FieldGroupSchema, FieldKindSchema, FieldProgressSchema, FieldResponseSchema, FieldSchema, FieldValueSchema, FormHarness, FormSchemaSchema, HarnessConfigSchema, IdSchema, InspectIssueSchema, InspectResultSchema, IssueReasonSchema, IssueScopeSchema, MarkformFrontmatterSchema, MockAgent, MultiCheckboxStateSchema, MultiSelectFieldSchema, MultiSelectValueSchema, NumberFieldSchema, NumberValueSchema, OptionIdSchema, OptionSchema, ParseError, PatchSchema, ProgressCountsSchema, ProgressStateSchema, ProgressSummarySchema, SessionFinalSchema, SessionTranscriptSchema, SessionTurnSchema, SetCheckboxesPatchSchema, SetMultiSelectPatchSchema, SetNumberPatchSchema, SetSingleSelectPatchSchema, SetStringListPatchSchema, SetStringPatchSchema, SeveritySchema, SimpleCheckboxStateSchema, SingleSelectFieldSchema, SingleSelectValueSchema, SourcePositionSchema, SourceRangeSchema, StepResultSchema, StringFieldSchema, StringListFieldSchema, StringListValueSchema, StringValueSchema, StructureSummarySchema, VERSION, ValidationIssueSchema, ValidatorRefSchema, applyPatches, coerceInputContext, coerceToFieldPatch, computeAllSummaries, computeFormState, computeProgressSummary, computeStructureSummary, createHarness, createMockAgent, fillForm, findFieldById, inspect, isFormComplete, isResearchForm, parseForm, parseSession, resolveHarnessConfig, runResearch, serialize, serializeSession, validate, validateResearchForm };
@@ -1,5 +1,5 @@
1
1
  import { N as PatchSchema } from "./coreTypes-Dful87E0.mjs";
2
- import { C as DEFAULT_ROLE_INSTRUCTIONS, N as getWebSearchConfig, S as DEFAULT_ROLES, _ as DEFAULT_MAX_TURNS, b as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, g as DEFAULT_MAX_PATCHES_PER_TURN, h as DEFAULT_MAX_ISSUES_PER_TURN, n as getFieldsForRoles, p as AGENT_ROLE, r as inspect, t as applyPatches, u as serialize, x as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN, y as DEFAULT_PRIORITY } from "./apply-BfAGTHMh.mjs";
2
+ import { C as DEFAULT_ROLE_INSTRUCTIONS, P as getWebSearchConfig, S as DEFAULT_ROLES, _ as DEFAULT_MAX_TURNS, b as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, g as DEFAULT_MAX_PATCHES_PER_TURN, h as DEFAULT_MAX_ISSUES_PER_TURN, n as getFieldsForRoles, p as AGENT_ROLE, r as inspect, t as applyPatches, u as serialize, x as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN, y as DEFAULT_PRIORITY } from "./apply-00UmzDKL.mjs";
3
3
  import { z } from "zod";
4
4
  import Markdoc from "@markdoc/markdoc";
5
5
  import YAML from "yaml";
@@ -2,7 +2,7 @@
2
2
  markform:
3
3
  spec: MF/0.1
4
4
  title: Movie Research (Minimal)
5
- description: Quick movie lookup - just the essentials (title, year, rating, summary).
5
+ description: Quick movie lookup with just the essentials (title, year, ratings, summary).
6
6
  roles:
7
7
  - user
8
8
  - agent
@@ -11,62 +11,43 @@ markform:
11
11
  agent: |
12
12
  Quickly identify the movie and fill in basic info from IMDB.
13
13
  This is a minimal lookup - just get the core facts.
14
- harness_config:
15
- max_issues_per_turn: 3
16
- max_patches_per_turn: 8
17
14
  ---
18
-
19
15
  {% form id="movie_research_minimal" title="Movie Research (Minimal)" %}
20
16
 
21
- {% description ref="movie_research_minimal" %}
22
- A quick movie lookup for essential info: title, year, rating, and a brief summary.
23
- {% /description %}
17
+ <!-- The first field group is filled in by the user (role="user"): -->
24
18
 
25
19
  {% field-group id="movie_input" title="Movie Identification" %}
26
20
 
27
21
  {% string-field id="movie" label="Movie" role="user" required=true minLength=1 maxLength=300 %}{% /string-field %}
28
-
29
- {% instructions ref="movie" %}
30
- Enter the movie title (add year or details if needed for disambiguation).
31
- {% /instructions %}
22
+ {% instructions ref="movie" %}Enter the movie title (add year or details for disambiguation).{% /instructions %}
32
23
 
33
24
  {% /field-group %}
34
25
 
35
- {% field-group id="title_identification" title="Title Identification" %}
26
+ <!-- Everything else is filled in by the agent (role="agent"): -->
36
27
 
37
- {% string-field id="full_title" label="Full Title" role="agent" required=true %}{% /string-field %}
28
+ {% field-group id="about_the_movie" title="About the Movie" %}
38
29
 
39
- {% instructions ref="full_title" %}
40
- Official title including subtitle if any.
41
- {% /instructions %}
30
+ {% string-field id="full_title" label="Full Title" role="agent" required=true %}{% /string-field %}
31
+ {% instructions ref="full_title" %}Official title including subtitle if any.{% /instructions %}
42
32
 
43
33
  {% number-field id="year" label="Release Year" role="agent" required=true min=1888 max=2030 %}{% /number-field %}
44
34
 
45
- {% /field-group %}
46
-
47
- {% field-group id="primary_sources" title="Source" %}
48
-
49
35
  {% url-field id="imdb_url" label="IMDB URL" role="agent" required=true %}{% /url-field %}
50
36
 
51
- {% /field-group %}
52
-
53
- {% field-group id="ratings" title="Rating" %}
37
+ {% single-select id="mpaa_rating" label="MPAA Rating" role="agent" %}
38
+ - [ ] G {% #g %}
39
+ - [ ] PG {% #pg %}
40
+ - [ ] PG-13 {% #pg_13 %}
41
+ - [ ] R {% #r %}
42
+ - [ ] NC-17 {% #nc_17 %}
43
+ - [ ] NR/Unrated {% #nr %}
44
+ {% /single-select %}
54
45
 
55
46
  {% number-field id="imdb_rating" label="IMDB Rating" role="agent" min=1.0 max=10.0 %}{% /number-field %}
56
-
57
- {% instructions ref="imdb_rating" %}
58
- IMDB user rating (1.0-10.0 scale).
59
- {% /instructions %}
60
-
61
- {% /field-group %}
62
-
63
- {% field-group id="summary" title="Summary" %}
47
+ {% instructions ref="imdb_rating" %}IMDB user rating (1.0-10.0 scale).{% /instructions %}
64
48
 
65
49
  {% string-field id="logline" label="One-Line Summary" role="agent" maxLength=300 %}{% /string-field %}
66
-
67
- {% instructions ref="logline" %}
68
- Brief plot summary in 1-2 sentences, no spoilers.
69
- {% /instructions %}
50
+ {% instructions ref="logline" %}Brief plot summary in 1-2 sentences, no spoilers.{% /instructions %}
70
51
 
71
52
  {% /field-group %}
72
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markform",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Markdown forms for token-friendly workflows",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "author": "Joshua Levy",
@@ -62,6 +62,7 @@
62
62
  "@ai-sdk/xai": "^3.0.1",
63
63
  "@clack/prompts": "^0.9.0",
64
64
  "@markdoc/markdoc": "^0.5.0",
65
+ "ai": "^6.0.0",
65
66
  "atomically": "^2.0.0",
66
67
  "commander": "^13.0.0",
67
68
  "dotenv": "^17.2.3",
@@ -71,19 +72,10 @@
71
72
  "yaml": "^2.7.0",
72
73
  "zod": "^3.24.0"
73
74
  },
74
- "peerDependencies": {
75
- "ai": "^6.0.0"
76
- },
77
- "peerDependenciesMeta": {
78
- "ai": {
79
- "optional": true
80
- }
81
- },
82
75
  "devDependencies": {
83
76
  "@ai-sdk/anthropic": "^3.0.1",
84
77
  "@types/node": "^24.0.0",
85
78
  "@vitest/coverage-v8": "^3.2.4",
86
- "ai": "^6.0.3",
87
79
  "publint": "^0.3.0",
88
80
  "tsdown": "^0.16.0",
89
81
  "typescript": "^5.0.0",