markform 0.1.24 → 0.1.25

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 (44) hide show
  1. package/README.md +54 -31
  2. package/dist/ai-sdk.d.mts +1 -1
  3. package/dist/ai-sdk.mjs +2 -2
  4. package/dist/bin.mjs +1 -1
  5. package/dist/{cli-B1DhFYBS.mjs → cli-B1T8kMFt.mjs} +85 -40
  6. package/dist/cli-B1T8kMFt.mjs.map +1 -0
  7. package/dist/cli.mjs +1 -1
  8. package/dist/{coreTypes-GxzWNXap.d.mts → coreTypes-CxpqKpBA.d.mts} +45 -2
  9. package/dist/{coreTypes-CctFK6uE.mjs → coreTypes-DIv9Aabl.mjs} +19 -5
  10. package/dist/coreTypes-DIv9Aabl.mjs.map +1 -0
  11. package/dist/{fillRecord-DeqI2pQ5.d.mts → fillRecord-V3vlyobd.d.mts} +5 -1
  12. package/dist/{fillRecordRenderer-VBQ2vwPV.mjs → fillRecordRenderer-BqRPHPmE.mjs} +47 -15
  13. package/dist/fillRecordRenderer-BqRPHPmE.mjs.map +1 -0
  14. package/dist/index.d.mts +32 -4
  15. package/dist/index.mjs +4 -4
  16. package/dist/{prompts-BCnYaH4_.mjs → prompts-DaPKumGY.mjs} +114 -11
  17. package/dist/prompts-DaPKumGY.mjs.map +1 -0
  18. package/dist/render.d.mts +2 -2
  19. package/dist/render.mjs +1 -1
  20. package/dist/{session-BLjN3BkJ.mjs → session-BW9jtYNV.mjs} +2 -2
  21. package/dist/{session-BLjN3BkJ.mjs.map → session-BW9jtYNV.mjs.map} +1 -1
  22. package/dist/{session-D7C7IlEv.mjs → session-DHyTMP67.mjs} +1 -1
  23. package/dist/{shared-DtorFV21.mjs → shared-BLh342F5.mjs} +1 -1
  24. package/dist/{shared-CuSRYcIB.mjs → shared-BszoSkAO.mjs} +8 -8
  25. package/dist/{shared-CuSRYcIB.mjs.map → shared-BszoSkAO.mjs.map} +1 -1
  26. package/dist/{src-C5OWf1dL.mjs → src-DrXmaOWl.mjs} +155 -27
  27. package/dist/src-DrXmaOWl.mjs.map +1 -0
  28. package/docs/markform-apis.md +19 -7
  29. package/docs/markform-reference.md +247 -178
  30. package/docs/markform-spec.md +81 -33
  31. package/docs/skill/SKILL.md +62 -20
  32. package/examples/markform-demo-playbook.md +342 -0
  33. package/examples/parallel/parallel-research.form.md +2 -6
  34. package/examples/simple/simple-mock-filled.report.md +2 -2
  35. package/examples/simple/simple-skipped-filled.report.md +2 -2
  36. package/examples/twitter-thread/twitter-thread.form.md +5 -5
  37. package/package.json +1 -1
  38. package/dist/cli-B1DhFYBS.mjs.map +0 -1
  39. package/dist/coreTypes-CctFK6uE.mjs.map +0 -1
  40. package/dist/fillRecordRenderer-VBQ2vwPV.mjs.map +0 -1
  41. package/dist/prompts-BCnYaH4_.mjs.map +0 -1
  42. package/dist/src-C5OWf1dL.mjs.map +0 -1
  43. package/examples/startup-research/startup-research-mock-filled.form.md +0 -297
  44. package/examples/startup-research/startup-research.form.md +0 -181
package/dist/render.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
- import { At as ParsedForm } from "./coreTypes-GxzWNXap.mjs";
3
- import { r as FillRecord } from "./fillRecord-DeqI2pQ5.mjs";
2
+ import { At as ParsedForm } from "./coreTypes-CxpqKpBA.mjs";
3
+ import { r as FillRecord } from "./fillRecord-V3vlyobd.mjs";
4
4
 
5
5
  //#region src/render/renderUtils.d.ts
6
6
  /**
package/dist/render.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
- import { a as renderJsonContent, c as renderViewContent, d as formatDuration, f as formatTokens, l as renderYamlContent, n as FILL_RECORD_STYLES, o as renderMarkdownContent, r as renderFillRecordContent, s as renderSourceContent, t as FILL_RECORD_SCRIPTS, u as escapeHtml } from "./fillRecordRenderer-VBQ2vwPV.mjs";
2
+ import { a as renderJsonContent, c as renderViewContent, d as formatDuration, f as formatTokens, l as renderYamlContent, n as FILL_RECORD_STYLES, o as renderMarkdownContent, r as renderFillRecordContent, s as renderSourceContent, t as FILL_RECORD_SCRIPTS, u as escapeHtml } from "./fillRecordRenderer-BqRPHPmE.mjs";
3
3
 
4
4
  export { FILL_RECORD_SCRIPTS, FILL_RECORD_STYLES, escapeHtml, formatDuration, formatTokens, renderFillRecordContent, renderJsonContent, renderMarkdownContent, renderSourceContent, renderViewContent, renderYamlContent };
@@ -1,5 +1,5 @@
1
1
 
2
- import { G as SessionTranscriptSchema } from "./coreTypes-CctFK6uE.mjs";
2
+ import { G as SessionTranscriptSchema } from "./coreTypes-DIv9Aabl.mjs";
3
3
  import YAML from "yaml";
4
4
 
5
5
  //#region src/engine/session.ts
@@ -113,4 +113,4 @@ function toSnakeCaseDeep(obj, preserveKeys = false) {
113
113
 
114
114
  //#endregion
115
115
  export { serializeSession as n, parseSession as t };
116
- //# sourceMappingURL=session-BLjN3BkJ.mjs.map
116
+ //# sourceMappingURL=session-BW9jtYNV.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-BLjN3BkJ.mjs","names":[],"sources":["../src/engine/session.ts"],"sourcesContent":["/**\n * Session module - parsing and serializing session transcripts.\n *\n * Session transcripts are used for golden testing and session replay.\n * They capture the full interaction between the harness and agent.\n */\nimport YAML from 'yaml';\nimport type { SessionTranscript } from './coreTypes';\nimport { SessionTranscriptSchema } from './coreTypes';\n\n/**\n * Parse a session transcript from YAML string.\n *\n * Converts snake_case keys to camelCase for TypeScript consumption.\n *\n * @param yaml - YAML string containing session transcript\n * @returns Parsed and validated SessionTranscript\n * @throws Error if YAML is invalid or doesn't match schema\n */\nexport function parseSession(yaml: string): SessionTranscript {\n // Parse YAML\n let raw: unknown;\n try {\n raw = YAML.parse(yaml);\n } catch (err) {\n throw new Error(\n `Failed to parse session YAML: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Convert snake_case to camelCase\n const converted = toCamelCaseDeep(raw);\n\n // Validate against schema\n const result = SessionTranscriptSchema.safeParse(converted);\n if (!result.success) {\n const errors = result.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ');\n throw new Error(`Invalid session transcript: ${errors}`);\n }\n\n return result.data;\n}\n\n/**\n * Serialize a session transcript to YAML string.\n *\n * Converts camelCase keys to snake_case for YAML output.\n *\n * @param session - Session transcript to serialize\n * @returns YAML string\n */\nexport function serializeSession(session: SessionTranscript): string {\n // Convert camelCase to snake_case\n const snakeCased = toSnakeCaseDeep(session);\n\n // Serialize to YAML\n return YAML.stringify(snakeCased, {\n indent: 2,\n lineWidth: 0, // Don't wrap lines\n });\n}\n\n// =============================================================================\n// Key Case Conversion Helpers\n// =============================================================================\n\n/**\n * Convert a string from snake_case to camelCase.\n */\nfunction snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_match, letter: string) => letter.toUpperCase());\n}\n\n/**\n * Convert a string from camelCase to snake_case.\n */\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Recursively convert all object keys from snake_case to camelCase.\n *\n * Preserves keys that are user-defined identifiers (like option IDs in\n * checkboxes `values` objects).\n *\n * @param obj - Object to convert\n * @param preserveKeys - If true, don't convert keys in this object (but still recurse into values)\n */\nfunction toCamelCaseDeep(obj: unknown, preserveKeys = false): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n // Pass preserveKeys through to array items\n return obj.map((item) => toCamelCaseDeep(item, preserveKeys));\n }\n\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n const record = obj as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(record)) {\n // Determine the key to use\n const resultKey = preserveKeys ? key : snakeToCamel(key);\n\n // Check if this is a \"value\" key in a set_checkboxes patch\n // The \"value\" object contains option IDs as keys which should be preserved\n const isCheckboxValues = key === 'value' && record.op === 'set_checkboxes';\n\n // Check if this is a \"value\" key in a set_table patch\n // The \"value\" array contains objects with column IDs as keys which should be preserved\n const isTableRows = key === 'value' && record.op === 'set_table';\n\n // Check if this is a \"tools\" key in a wire format request\n // Tool names are identifiers that should be preserved\n const isWireTools = key === 'tools';\n\n result[resultKey] = toCamelCaseDeep(value, isCheckboxValues || isTableRows || isWireTools);\n }\n return result;\n }\n\n return obj;\n}\n\n/**\n * Recursively convert all object keys from camelCase to snake_case.\n *\n * Preserves keys that are user-defined identifiers (like option IDs in\n * checkboxes `values` objects).\n *\n * @param obj - Object to convert\n * @param preserveKeys - If true, don't convert keys in this object (but still recurse into values)\n */\nfunction toSnakeCaseDeep(obj: unknown, preserveKeys = false): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n // Pass preserveKeys through to array items\n return obj.map((item) => toSnakeCaseDeep(item, preserveKeys));\n }\n\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n const record = obj as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(record)) {\n // Determine the key to use\n const resultKey = preserveKeys ? key : camelToSnake(key);\n\n // Check if this is a \"value\" key in a set_checkboxes patch\n // The \"value\" object contains option IDs as keys which should be preserved\n const isCheckboxValues = key === 'value' && record.op === 'set_checkboxes';\n\n // Check if this is a \"value\" key in a set_table patch\n // The \"value\" array contains objects with column IDs as keys which should be preserved\n const isTableRows = key === 'value' && record.op === 'set_table';\n\n // Check if this is a \"tools\" key in a wire format request\n // Tool names are identifiers that should be preserved\n const isWireTools = key === 'tools';\n\n result[resultKey] = toSnakeCaseDeep(value, isCheckboxValues || isTableRows || isWireTools);\n }\n return result;\n }\n\n return obj;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,aAAa,MAAiC;CAE5D,IAAI;AACJ,KAAI;AACF,QAAM,KAAK,MAAM,KAAK;UACf,KAAK;AACZ,QAAM,IAAI,MACR,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAClF;;CAIH,MAAM,YAAY,gBAAgB,IAAI;CAGtC,MAAM,SAAS,wBAAwB,UAAU,UAAU;AAC3D,KAAI,CAAC,OAAO,SAAS;EACnB,MAAM,SAAS,OAAO,MAAM,OAAO,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,KAAK;AAC7F,QAAM,IAAI,MAAM,+BAA+B,SAAS;;AAG1D,QAAO,OAAO;;;;;;;;;;AAWhB,SAAgB,iBAAiB,SAAoC;CAEnE,MAAM,aAAa,gBAAgB,QAAQ;AAG3C,QAAO,KAAK,UAAU,YAAY;EAChC,QAAQ;EACR,WAAW;EACZ,CAAC;;;;;AAUJ,SAAS,aAAa,KAAqB;AACzC,QAAO,IAAI,QAAQ,cAAc,QAAQ,WAAmB,OAAO,aAAa,CAAC;;;;;AAMnF,SAAS,aAAa,KAAqB;AACzC,QAAO,IAAI,QAAQ,WAAW,WAAW,IAAI,OAAO,aAAa,GAAG;;;;;;;;;;;AAYtE,SAAS,gBAAgB,KAAc,eAAe,OAAgB;AACpE,KAAI,QAAQ,QAAQ,QAAQ,OAC1B,QAAO;AAGT,KAAI,MAAM,QAAQ,IAAI,CAEpB,QAAO,IAAI,KAAK,SAAS,gBAAgB,MAAM,aAAa,CAAC;AAG/D,KAAI,OAAO,QAAQ,UAAU;EAC3B,MAAM,SAAkC,EAAE;EAC1C,MAAM,SAAS;AAEf,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAAE;GAEjD,MAAM,YAAY,eAAe,MAAM,aAAa,IAAI;GAIxD,MAAM,mBAAmB,QAAQ,WAAW,OAAO,OAAO;GAI1D,MAAM,cAAc,QAAQ,WAAW,OAAO,OAAO;AAMrD,UAAO,aAAa,gBAAgB,OAAO,oBAAoB,eAF3C,QAAQ,QAE8D;;AAE5F,SAAO;;AAGT,QAAO;;;;;;;;;;;AAYT,SAAS,gBAAgB,KAAc,eAAe,OAAgB;AACpE,KAAI,QAAQ,QAAQ,QAAQ,OAC1B,QAAO;AAGT,KAAI,MAAM,QAAQ,IAAI,CAEpB,QAAO,IAAI,KAAK,SAAS,gBAAgB,MAAM,aAAa,CAAC;AAG/D,KAAI,OAAO,QAAQ,UAAU;EAC3B,MAAM,SAAkC,EAAE;EAC1C,MAAM,SAAS;AAEf,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAAE;GAEjD,MAAM,YAAY,eAAe,MAAM,aAAa,IAAI;GAIxD,MAAM,mBAAmB,QAAQ,WAAW,OAAO,OAAO;GAI1D,MAAM,cAAc,QAAQ,WAAW,OAAO,OAAO;AAMrD,UAAO,aAAa,gBAAgB,OAAO,oBAAoB,eAF3C,QAAQ,QAE8D;;AAE5F,SAAO;;AAGT,QAAO"}
1
+ {"version":3,"file":"session-BW9jtYNV.mjs","names":[],"sources":["../src/engine/session.ts"],"sourcesContent":["/**\n * Session module - parsing and serializing session transcripts.\n *\n * Session transcripts are used for golden testing and session replay.\n * They capture the full interaction between the harness and agent.\n */\nimport YAML from 'yaml';\nimport type { SessionTranscript } from './coreTypes';\nimport { SessionTranscriptSchema } from './coreTypes';\n\n/**\n * Parse a session transcript from YAML string.\n *\n * Converts snake_case keys to camelCase for TypeScript consumption.\n *\n * @param yaml - YAML string containing session transcript\n * @returns Parsed and validated SessionTranscript\n * @throws Error if YAML is invalid or doesn't match schema\n */\nexport function parseSession(yaml: string): SessionTranscript {\n // Parse YAML\n let raw: unknown;\n try {\n raw = YAML.parse(yaml);\n } catch (err) {\n throw new Error(\n `Failed to parse session YAML: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Convert snake_case to camelCase\n const converted = toCamelCaseDeep(raw);\n\n // Validate against schema\n const result = SessionTranscriptSchema.safeParse(converted);\n if (!result.success) {\n const errors = result.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ');\n throw new Error(`Invalid session transcript: ${errors}`);\n }\n\n return result.data;\n}\n\n/**\n * Serialize a session transcript to YAML string.\n *\n * Converts camelCase keys to snake_case for YAML output.\n *\n * @param session - Session transcript to serialize\n * @returns YAML string\n */\nexport function serializeSession(session: SessionTranscript): string {\n // Convert camelCase to snake_case\n const snakeCased = toSnakeCaseDeep(session);\n\n // Serialize to YAML\n return YAML.stringify(snakeCased, {\n indent: 2,\n lineWidth: 0, // Don't wrap lines\n });\n}\n\n// =============================================================================\n// Key Case Conversion Helpers\n// =============================================================================\n\n/**\n * Convert a string from snake_case to camelCase.\n */\nfunction snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_match, letter: string) => letter.toUpperCase());\n}\n\n/**\n * Convert a string from camelCase to snake_case.\n */\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Recursively convert all object keys from snake_case to camelCase.\n *\n * Preserves keys that are user-defined identifiers (like option IDs in\n * checkboxes `values` objects).\n *\n * @param obj - Object to convert\n * @param preserveKeys - If true, don't convert keys in this object (but still recurse into values)\n */\nfunction toCamelCaseDeep(obj: unknown, preserveKeys = false): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n // Pass preserveKeys through to array items\n return obj.map((item) => toCamelCaseDeep(item, preserveKeys));\n }\n\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n const record = obj as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(record)) {\n // Determine the key to use\n const resultKey = preserveKeys ? key : snakeToCamel(key);\n\n // Check if this is a \"value\" key in a set_checkboxes patch\n // The \"value\" object contains option IDs as keys which should be preserved\n const isCheckboxValues = key === 'value' && record.op === 'set_checkboxes';\n\n // Check if this is a \"value\" key in a set_table patch\n // The \"value\" array contains objects with column IDs as keys which should be preserved\n const isTableRows = key === 'value' && record.op === 'set_table';\n\n // Check if this is a \"tools\" key in a wire format request\n // Tool names are identifiers that should be preserved\n const isWireTools = key === 'tools';\n\n result[resultKey] = toCamelCaseDeep(value, isCheckboxValues || isTableRows || isWireTools);\n }\n return result;\n }\n\n return obj;\n}\n\n/**\n * Recursively convert all object keys from camelCase to snake_case.\n *\n * Preserves keys that are user-defined identifiers (like option IDs in\n * checkboxes `values` objects).\n *\n * @param obj - Object to convert\n * @param preserveKeys - If true, don't convert keys in this object (but still recurse into values)\n */\nfunction toSnakeCaseDeep(obj: unknown, preserveKeys = false): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n // Pass preserveKeys through to array items\n return obj.map((item) => toSnakeCaseDeep(item, preserveKeys));\n }\n\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n const record = obj as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(record)) {\n // Determine the key to use\n const resultKey = preserveKeys ? key : camelToSnake(key);\n\n // Check if this is a \"value\" key in a set_checkboxes patch\n // The \"value\" object contains option IDs as keys which should be preserved\n const isCheckboxValues = key === 'value' && record.op === 'set_checkboxes';\n\n // Check if this is a \"value\" key in a set_table patch\n // The \"value\" array contains objects with column IDs as keys which should be preserved\n const isTableRows = key === 'value' && record.op === 'set_table';\n\n // Check if this is a \"tools\" key in a wire format request\n // Tool names are identifiers that should be preserved\n const isWireTools = key === 'tools';\n\n result[resultKey] = toSnakeCaseDeep(value, isCheckboxValues || isTableRows || isWireTools);\n }\n return result;\n }\n\n return obj;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,aAAa,MAAiC;CAE5D,IAAI;AACJ,KAAI;AACF,QAAM,KAAK,MAAM,KAAK;UACf,KAAK;AACZ,QAAM,IAAI,MACR,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAClF;;CAIH,MAAM,YAAY,gBAAgB,IAAI;CAGtC,MAAM,SAAS,wBAAwB,UAAU,UAAU;AAC3D,KAAI,CAAC,OAAO,SAAS;EACnB,MAAM,SAAS,OAAO,MAAM,OAAO,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,KAAK;AAC7F,QAAM,IAAI,MAAM,+BAA+B,SAAS;;AAG1D,QAAO,OAAO;;;;;;;;;;AAWhB,SAAgB,iBAAiB,SAAoC;CAEnE,MAAM,aAAa,gBAAgB,QAAQ;AAG3C,QAAO,KAAK,UAAU,YAAY;EAChC,QAAQ;EACR,WAAW;EACZ,CAAC;;;;;AAUJ,SAAS,aAAa,KAAqB;AACzC,QAAO,IAAI,QAAQ,cAAc,QAAQ,WAAmB,OAAO,aAAa,CAAC;;;;;AAMnF,SAAS,aAAa,KAAqB;AACzC,QAAO,IAAI,QAAQ,WAAW,WAAW,IAAI,OAAO,aAAa,GAAG;;;;;;;;;;;AAYtE,SAAS,gBAAgB,KAAc,eAAe,OAAgB;AACpE,KAAI,QAAQ,QAAQ,QAAQ,OAC1B,QAAO;AAGT,KAAI,MAAM,QAAQ,IAAI,CAEpB,QAAO,IAAI,KAAK,SAAS,gBAAgB,MAAM,aAAa,CAAC;AAG/D,KAAI,OAAO,QAAQ,UAAU;EAC3B,MAAM,SAAkC,EAAE;EAC1C,MAAM,SAAS;AAEf,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAAE;GAEjD,MAAM,YAAY,eAAe,MAAM,aAAa,IAAI;GAIxD,MAAM,mBAAmB,QAAQ,WAAW,OAAO,OAAO;GAI1D,MAAM,cAAc,QAAQ,WAAW,OAAO,OAAO;AAMrD,UAAO,aAAa,gBAAgB,OAAO,oBAAoB,eAF3C,QAAQ,QAE8D;;AAE5F,SAAO;;AAGT,QAAO;;;;;;;;;;;AAYT,SAAS,gBAAgB,KAAc,eAAe,OAAgB;AACpE,KAAI,QAAQ,QAAQ,QAAQ,OAC1B,QAAO;AAGT,KAAI,MAAM,QAAQ,IAAI,CAEpB,QAAO,IAAI,KAAK,SAAS,gBAAgB,MAAM,aAAa,CAAC;AAG/D,KAAI,OAAO,QAAQ,UAAU;EAC3B,MAAM,SAAkC,EAAE;EAC1C,MAAM,SAAS;AAEf,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAAE;GAEjD,MAAM,YAAY,eAAe,MAAM,aAAa,IAAI;GAIxD,MAAM,mBAAmB,QAAQ,WAAW,OAAO,OAAO;GAI1D,MAAM,cAAc,QAAQ,WAAW,OAAO,OAAO;AAMrD,UAAO,aAAa,gBAAgB,OAAO,oBAAoB,eAF3C,QAAQ,QAE8D;;AAE5F,SAAO;;AAGT,QAAO"}
@@ -1,4 +1,4 @@
1
1
 
2
- import { n as serializeSession, t as parseSession } from "./session-BLjN3BkJ.mjs";
2
+ import { n as serializeSession, t as parseSession } from "./session-BW9jtYNV.mjs";
3
3
 
4
4
  export { serializeSession };
@@ -1,4 +1,4 @@
1
1
 
2
- import { _ as writeFile, a as formatPath, c as logError, d as logTiming, f as logVerbose, g as stripHtmlComments, h as shouldUseColors, i as formatOutput, l as logInfo, m as readFile, n as createSpinner, o as getCommandContext, p as logWarn, r as ensureFormsDir, s as logDryRun, t as OUTPUT_FORMATS, u as logSuccess } from "./shared-CuSRYcIB.mjs";
2
+ import { _ as writeFile, a as formatPath, c as logError, d as logTiming, f as logVerbose, g as stripHtmlComments, h as shouldUseColors, i as formatOutput, l as logInfo, m as readFile, n as createSpinner, o as getCommandContext, p as logWarn, r as ensureFormsDir, s as logDryRun, t as OUTPUT_FORMATS, u as logSuccess } from "./shared-BszoSkAO.mjs";
3
3
 
4
4
  export { writeFile };
@@ -174,20 +174,20 @@ function formatOutput(ctx, data, consoleFormatter) {
174
174
  * Log a dry-run message.
175
175
  */
176
176
  function logDryRun(message, details) {
177
- console.log(pc.yellow(`[DRY RUN] ${message}`));
178
- if (details) console.log(pc.dim(JSON.stringify(details, null, 2)));
177
+ console.error(pc.yellow(`[DRY RUN] ${message}`));
178
+ if (details) console.error(pc.dim(JSON.stringify(details, null, 2)));
179
179
  }
180
180
  /**
181
181
  * Log a verbose message (only shown if --verbose is set).
182
182
  */
183
183
  function logVerbose(ctx, message) {
184
- if (ctx.verbose) console.log(pc.dim(message));
184
+ if (ctx.verbose) console.error(pc.dim(message));
185
185
  }
186
186
  /**
187
187
  * Log an info message (hidden if --quiet is set).
188
188
  */
189
189
  function logInfo(ctx, message) {
190
- if (!ctx.quiet) console.log(message);
190
+ if (!ctx.quiet) console.error(message);
191
191
  }
192
192
  /**
193
193
  * Log an error message (always shown).
@@ -199,7 +199,7 @@ function logError(message) {
199
199
  * Log a success message (hidden if --quiet is set).
200
200
  */
201
201
  function logSuccess(ctx, message) {
202
- if (!ctx.quiet) console.log(pc.green(message));
202
+ if (!ctx.quiet) console.error(pc.green(message));
203
203
  }
204
204
  /**
205
205
  * Log a timing message (hidden if --quiet is set).
@@ -207,14 +207,14 @@ function logSuccess(ctx, message) {
207
207
  function logTiming(ctx, label, durationMs) {
208
208
  if (!ctx.quiet) {
209
209
  const seconds = (durationMs / 1e3).toFixed(1);
210
- console.log(pc.cyan(`⏰ ${label}: ${seconds}s`));
210
+ console.error(pc.cyan(`⏰ ${label}: ${seconds}s`));
211
211
  }
212
212
  }
213
213
  /**
214
214
  * Log a warning message (hidden if --quiet is set).
215
215
  */
216
216
  function logWarn(ctx, message) {
217
- if (!ctx.quiet) console.log(pc.yellow(`⚠️ ${message}`));
217
+ if (!ctx.quiet) console.error(pc.yellow(`⚠️ ${message}`));
218
218
  }
219
219
  /**
220
220
  * Strip HTML comments from markdown content.
@@ -262,4 +262,4 @@ async function ensureFormsDir(formsDir) {
262
262
 
263
263
  //#endregion
264
264
  export { writeFile$1 as _, formatPath as a, logError as c, logTiming as d, logVerbose as f, stripHtmlComments as g, shouldUseColors as h, formatOutput as i, logInfo as l, readFile$1 as m, createSpinner as n, getCommandContext as o, logWarn as p, ensureFormsDir as r, logDryRun as s, OUTPUT_FORMATS as t, logSuccess as u };
265
- //# sourceMappingURL=shared-CuSRYcIB.mjs.map
265
+ //# sourceMappingURL=shared-BszoSkAO.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-CuSRYcIB.mjs","names":["readFile","writeFile"],"sources":["../src/cli/lib/naming.ts","../src/cli/lib/shared.ts"],"sourcesContent":["/**\n * Naming convention utilities for JSON/YAML output.\n *\n * Converts between camelCase (TypeScript internal) and snake_case (JSON/YAML output).\n */\n\n/**\n * Convert a camelCase string to snake_case.\n *\n * @example\n * toSnakeCase(\"fieldCount\") // \"field_count\"\n * toSnakeCase(\"parentFieldId\") // \"parent_field_id\"\n * toSnakeCase(\"already_snake\") // \"already_snake\"\n */\nexport function toSnakeCase(str: string): string {\n return str.replace(/([A-Z])/g, '_$1').toLowerCase();\n}\n\n/**\n * Convert a snake_case string to camelCase.\n *\n * @example\n * toCamelCase(\"field_count\") // \"fieldCount\"\n * toCamelCase(\"parent_field_id\") // \"parentFieldId\"\n * toCamelCase(\"alreadyCamel\") // \"alreadyCamel\"\n */\nexport function toCamelCase(str: string): string {\n return str.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\n/**\n * Recursively convert all object keys from camelCase to snake_case.\n *\n * Handles nested objects and arrays. Primitives are returned unchanged.\n */\nexport function convertKeysToSnakeCase(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertKeysToSnakeCase);\n }\n\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n const snakeKey = toSnakeCase(key);\n result[snakeKey] = convertKeysToSnakeCase(value);\n }\n return result;\n }\n\n return obj;\n}\n\n/**\n * Recursively convert all object keys from snake_case to camelCase.\n *\n * Handles nested objects and arrays. Primitives are returned unchanged.\n */\nexport function convertKeysToCamelCase(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertKeysToCamelCase);\n }\n\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n const camelKey = toCamelCase(key);\n result[camelKey] = convertKeysToCamelCase(value);\n }\n return result;\n }\n\n return obj;\n}\n","/**\n * Shared CLI utilities for command context, debug, and dry-run helpers.\n */\n\nimport type { Command } from 'commander';\n\nimport { mkdir } from 'node:fs/promises';\nimport { relative } from 'node:path';\n\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport YAML from 'yaml';\n\nimport { convertKeysToSnakeCase } from './naming.js';\nimport type { CommandContext, OutputFormat } from './cliTypes.js';\n\n// =============================================================================\n// Spinner Utility Types\n// =============================================================================\n\n/**\n * Context type for spinner operations.\n * - 'api': For LLM/API calls (shows provider, model, turn info)\n * - 'compute': For local calculations\n */\nexport type SpinnerContextType = 'api' | 'compute';\n\n/**\n * API context for spinner - used when making LLM calls.\n */\nexport interface ApiSpinnerContext {\n type: 'api';\n provider: string;\n model: string;\n turnNumber?: number;\n}\n\n/**\n * Compute context for spinner - used for local calculations.\n */\nexport interface ComputeSpinnerContext {\n type: 'compute';\n operation: string;\n}\n\n/**\n * Union of spinner context types.\n */\nexport type SpinnerContext = ApiSpinnerContext | ComputeSpinnerContext;\n\n/**\n * Handle for controlling an active spinner.\n */\nexport interface SpinnerHandle {\n /** Update the spinner message. */\n message(msg: string): void;\n /** Update the spinner context (re-renders with elapsed time). */\n update(context: SpinnerContext): void;\n /** Stop the spinner with a success message. */\n stop(msg?: string): void;\n /** Stop the spinner with an error message. */\n error(msg: string): void;\n /** Get elapsed time in milliseconds since spinner started. */\n getElapsedMs(): number;\n}\n\n// Re-export types for backwards compatibility\nexport type { CommandContext, OutputFormat } from './cliTypes.js';\n\n// =============================================================================\n// Spinner Utility Functions\n// =============================================================================\n\n/**\n * Format elapsed time for display.\n */\nfunction formatElapsedTime(ms: number): string {\n const seconds = ms / 1000;\n if (seconds < 60) {\n return `${seconds.toFixed(1)}s`;\n }\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = seconds % 60;\n return `${minutes}m ${remainingSeconds.toFixed(0)}s`;\n}\n\n/**\n * Format spinner message based on context type.\n */\nfunction formatSpinnerMessage(context: SpinnerContext, elapsedMs: number): string {\n const elapsed = formatElapsedTime(elapsedMs);\n\n if (context.type === 'api') {\n const turnInfo = context.turnNumber !== undefined ? ` turn ${context.turnNumber}` : '';\n return `${context.provider}/${context.model}${turnInfo} ${pc.dim(`(${elapsed})`)}`;\n }\n\n return `${context.operation} ${pc.dim(`(${elapsed})`)}`;\n}\n\n/**\n * Create a context-aware spinner with elapsed time tracking.\n *\n * The spinner automatically updates its message with elapsed time.\n *\n * @example\n * ```ts\n * const spinner = createSpinner({\n * type: 'api',\n * provider: 'anthropic',\n * model: 'claude-sonnet-4',\n * turnNumber: 1,\n * });\n *\n * // Do async work...\n * const result = await agent.fillFormTool(...);\n *\n * spinner.stop('Done');\n * ```\n */\nexport function createSpinner(context: SpinnerContext): SpinnerHandle {\n const startTime = Date.now();\n const spinner = p.spinner();\n let currentContext = context;\n let intervalId: ReturnType<typeof setInterval> | null = null;\n\n // Start the spinner with initial message\n const initialMessage = formatSpinnerMessage(currentContext, 0);\n spinner.start(initialMessage);\n\n // Update elapsed time every second\n intervalId = setInterval(() => {\n const elapsed = Date.now() - startTime;\n spinner.message(formatSpinnerMessage(currentContext, elapsed));\n }, 1000);\n\n const cleanup = (): void => {\n if (intervalId) {\n clearInterval(intervalId);\n intervalId = null;\n }\n };\n\n return {\n message(msg: string): void {\n spinner.message(msg);\n },\n\n update(newContext: SpinnerContext): void {\n currentContext = newContext;\n const elapsed = Date.now() - startTime;\n spinner.message(formatSpinnerMessage(currentContext, elapsed));\n },\n\n stop(msg?: string): void {\n cleanup();\n const elapsed = Date.now() - startTime;\n const defaultMsg = formatSpinnerMessage(currentContext, elapsed);\n spinner.stop(msg ?? `✓ ${defaultMsg}`);\n },\n\n error(msg: string): void {\n cleanup();\n spinner.stop(pc.red(`✗ ${msg}`));\n },\n\n getElapsedMs(): number {\n return Date.now() - startTime;\n },\n };\n}\n\n/**\n * Create a no-op spinner handle for quiet mode or non-TTY environments.\n */\nexport function createNoOpSpinner(): SpinnerHandle {\n const startTime = Date.now();\n // Use explicit undefined returns to avoid empty-function lint errors\n const noop = (): void => undefined;\n return {\n message: noop,\n update: noop,\n stop: noop,\n error: noop,\n getElapsedMs: () => Date.now() - startTime,\n };\n}\n\n/**\n * Create a spinner if appropriate for the context.\n * Returns a no-op spinner in quiet mode or when stdout is not a TTY.\n */\nexport function createSpinnerIfTty(context: SpinnerContext, ctx: CommandContext): SpinnerHandle {\n if (ctx.quiet || !process.stdout.isTTY) {\n return createNoOpSpinner();\n }\n return createSpinner(context);\n}\n\n// =============================================================================\n// Output Format Utilities\n// =============================================================================\n\n/**\n * Valid format options for Commander choice validation.\n */\nexport const OUTPUT_FORMATS: OutputFormat[] = [\n 'console',\n 'plaintext',\n 'yaml',\n 'json',\n 'markform',\n 'markdown',\n];\n\n/**\n * Extract command context from Commander options.\n */\nexport function getCommandContext(command: Command): CommandContext {\n const opts = command.optsWithGlobals<{\n dryRun?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n format?: OutputFormat;\n formsDir?: string;\n overwrite?: boolean;\n }>();\n return {\n dryRun: opts.dryRun ?? false,\n verbose: opts.verbose ?? false,\n quiet: opts.quiet ?? false,\n format: opts.format ?? 'console',\n formsDir: opts.formsDir,\n overwrite: opts.overwrite ?? false,\n };\n}\n\n/**\n * Check if output should use colors.\n * Returns true for console format when stdout is a TTY.\n */\nexport function shouldUseColors(ctx: CommandContext): boolean {\n if (ctx.format === 'plaintext' || ctx.format === 'yaml' || ctx.format === 'json') {\n return false;\n }\n // console format: use colors if stdout is a TTY and NO_COLOR is not set\n return process.stdout.isTTY && !process.env.NO_COLOR;\n}\n\n/**\n * Format structured data according to output format.\n *\n * JSON and YAML outputs are converted to snake_case keys for consistency.\n */\nexport function formatOutput(\n ctx: CommandContext,\n data: unknown,\n consoleFormatter?: (data: unknown, useColors: boolean) => string,\n): string {\n switch (ctx.format) {\n case 'json':\n return JSON.stringify(convertKeysToSnakeCase(data), null, 2);\n case 'yaml':\n return YAML.stringify(convertKeysToSnakeCase(data));\n case 'plaintext':\n case 'console':\n default:\n if (consoleFormatter) {\n return consoleFormatter(data, shouldUseColors(ctx));\n }\n // Default: use YAML for readable console output\n return YAML.stringify(convertKeysToSnakeCase(data));\n }\n}\n\n/**\n * Log a dry-run message.\n */\nexport function logDryRun(message: string, details?: unknown): void {\n console.log(pc.yellow(`[DRY RUN] ${message}`));\n if (details) {\n console.log(pc.dim(JSON.stringify(details, null, 2)));\n }\n}\n\n/**\n * Log a verbose message (only shown if --verbose is set).\n */\nexport function logVerbose(ctx: CommandContext, message: string): void {\n if (ctx.verbose) {\n console.log(pc.dim(message));\n }\n}\n\n/**\n * Log an info message (hidden if --quiet is set).\n */\nexport function logInfo(ctx: CommandContext, message: string): void {\n if (!ctx.quiet) {\n console.log(message);\n }\n}\n\n/**\n * Log an error message (always shown).\n */\nexport function logError(message: string): void {\n console.error(pc.red(`Error: ${message}`));\n}\n\n/**\n * Log a success message (hidden if --quiet is set).\n */\nexport function logSuccess(ctx: CommandContext, message: string): void {\n if (!ctx.quiet) {\n console.log(pc.green(message));\n }\n}\n\n/**\n * Log a timing message (hidden if --quiet is set).\n */\nexport function logTiming(ctx: CommandContext, label: string, durationMs: number): void {\n if (!ctx.quiet) {\n const seconds = (durationMs / 1000).toFixed(1);\n console.log(pc.cyan(`⏰ ${label}: ${seconds}s`));\n }\n}\n\n/**\n * Log a warning message (hidden if --quiet is set).\n */\nexport function logWarn(ctx: CommandContext, message: string): void {\n if (!ctx.quiet) {\n console.log(pc.yellow(`⚠️ ${message}`));\n }\n}\n\n/**\n * Strip HTML comments from markdown content.\n * Removes <!-- ... --> blocks (including multiline) and trims leading whitespace.\n */\nexport function stripHtmlComments(content: string): string {\n // Remove HTML comments (multiline-safe)\n const stripped = content.replace(/<!--[\\s\\S]*?-->/g, '');\n // Trim leading whitespace that may remain after comment removal\n return stripped.replace(/^\\s+/, '');\n}\n\n/**\n * Format a file path for display: relative to cwd, colored green.\n * If the path is within the cwd, shows as relative (e.g., \"./simple-filled1.form.md\")\n * If outside cwd, shows the absolute path.\n */\nexport function formatPath(absolutePath: string, cwd: string = process.cwd()): string {\n const relativePath = relative(cwd, absolutePath);\n // If the relative path doesn't start with \"..\", it's within cwd\n const displayPath = relativePath.startsWith('..') ? absolutePath : `./${relativePath}`;\n return pc.green(displayPath);\n}\n\n/**\n * Read a file and return its contents.\n */\nexport async function readFile(filePath: string): Promise<string> {\n const { readFile: fsReadFile } = await import('node:fs/promises');\n return fsReadFile(filePath, 'utf-8');\n}\n\n/**\n * Write contents to a file atomically.\n *\n * Uses the atomically library to prevent partial or corrupted files\n * if the process crashes mid-write.\n */\nexport async function writeFile(filePath: string, contents: string): Promise<void> {\n const { writeFile: atomicWriteFile } = await import('atomically');\n await atomicWriteFile(filePath, contents);\n}\n\n/**\n * Ensure the forms directory exists, creating it if necessary.\n * Uses recursive mkdir so parent directories are created as needed.\n *\n * @param formsDir Absolute path to the forms directory\n */\nexport async function ensureFormsDir(formsDir: string): Promise<void> {\n await mkdir(formsDir, { recursive: true });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shared-BszoSkAO.mjs","names":["readFile","writeFile"],"sources":["../src/cli/lib/naming.ts","../src/cli/lib/shared.ts"],"sourcesContent":["/**\n * Naming convention utilities for JSON/YAML output.\n *\n * Converts between camelCase (TypeScript internal) and snake_case (JSON/YAML output).\n */\n\n/**\n * Convert a camelCase string to snake_case.\n *\n * @example\n * toSnakeCase(\"fieldCount\") // \"field_count\"\n * toSnakeCase(\"parentFieldId\") // \"parent_field_id\"\n * toSnakeCase(\"already_snake\") // \"already_snake\"\n */\nexport function toSnakeCase(str: string): string {\n return str.replace(/([A-Z])/g, '_$1').toLowerCase();\n}\n\n/**\n * Convert a snake_case string to camelCase.\n *\n * @example\n * toCamelCase(\"field_count\") // \"fieldCount\"\n * toCamelCase(\"parent_field_id\") // \"parentFieldId\"\n * toCamelCase(\"alreadyCamel\") // \"alreadyCamel\"\n */\nexport function toCamelCase(str: string): string {\n return str.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\n/**\n * Recursively convert all object keys from camelCase to snake_case.\n *\n * Handles nested objects and arrays. Primitives are returned unchanged.\n */\nexport function convertKeysToSnakeCase(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertKeysToSnakeCase);\n }\n\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n const snakeKey = toSnakeCase(key);\n result[snakeKey] = convertKeysToSnakeCase(value);\n }\n return result;\n }\n\n return obj;\n}\n\n/**\n * Recursively convert all object keys from snake_case to camelCase.\n *\n * Handles nested objects and arrays. Primitives are returned unchanged.\n */\nexport function convertKeysToCamelCase(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertKeysToCamelCase);\n }\n\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n const camelKey = toCamelCase(key);\n result[camelKey] = convertKeysToCamelCase(value);\n }\n return result;\n }\n\n return obj;\n}\n","/**\n * Shared CLI utilities for command context, debug, and dry-run helpers.\n */\n\nimport type { Command } from 'commander';\n\nimport { mkdir } from 'node:fs/promises';\nimport { relative } from 'node:path';\n\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport YAML from 'yaml';\n\nimport { convertKeysToSnakeCase } from './naming.js';\nimport type { CommandContext, OutputFormat } from './cliTypes.js';\n\n// =============================================================================\n// Spinner Utility Types\n// =============================================================================\n\n/**\n * Context type for spinner operations.\n * - 'api': For LLM/API calls (shows provider, model, turn info)\n * - 'compute': For local calculations\n */\nexport type SpinnerContextType = 'api' | 'compute';\n\n/**\n * API context for spinner - used when making LLM calls.\n */\nexport interface ApiSpinnerContext {\n type: 'api';\n provider: string;\n model: string;\n turnNumber?: number;\n}\n\n/**\n * Compute context for spinner - used for local calculations.\n */\nexport interface ComputeSpinnerContext {\n type: 'compute';\n operation: string;\n}\n\n/**\n * Union of spinner context types.\n */\nexport type SpinnerContext = ApiSpinnerContext | ComputeSpinnerContext;\n\n/**\n * Handle for controlling an active spinner.\n */\nexport interface SpinnerHandle {\n /** Update the spinner message. */\n message(msg: string): void;\n /** Update the spinner context (re-renders with elapsed time). */\n update(context: SpinnerContext): void;\n /** Stop the spinner with a success message. */\n stop(msg?: string): void;\n /** Stop the spinner with an error message. */\n error(msg: string): void;\n /** Get elapsed time in milliseconds since spinner started. */\n getElapsedMs(): number;\n}\n\n// Re-export types for backwards compatibility\nexport type { CommandContext, OutputFormat } from './cliTypes.js';\n\n// =============================================================================\n// Spinner Utility Functions\n// =============================================================================\n\n/**\n * Format elapsed time for display.\n */\nfunction formatElapsedTime(ms: number): string {\n const seconds = ms / 1000;\n if (seconds < 60) {\n return `${seconds.toFixed(1)}s`;\n }\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = seconds % 60;\n return `${minutes}m ${remainingSeconds.toFixed(0)}s`;\n}\n\n/**\n * Format spinner message based on context type.\n */\nfunction formatSpinnerMessage(context: SpinnerContext, elapsedMs: number): string {\n const elapsed = formatElapsedTime(elapsedMs);\n\n if (context.type === 'api') {\n const turnInfo = context.turnNumber !== undefined ? ` turn ${context.turnNumber}` : '';\n return `${context.provider}/${context.model}${turnInfo} ${pc.dim(`(${elapsed})`)}`;\n }\n\n return `${context.operation} ${pc.dim(`(${elapsed})`)}`;\n}\n\n/**\n * Create a context-aware spinner with elapsed time tracking.\n *\n * The spinner automatically updates its message with elapsed time.\n *\n * @example\n * ```ts\n * const spinner = createSpinner({\n * type: 'api',\n * provider: 'anthropic',\n * model: 'claude-sonnet-4',\n * turnNumber: 1,\n * });\n *\n * // Do async work...\n * const result = await agent.fillFormTool(...);\n *\n * spinner.stop('Done');\n * ```\n */\nexport function createSpinner(context: SpinnerContext): SpinnerHandle {\n const startTime = Date.now();\n const spinner = p.spinner();\n let currentContext = context;\n let intervalId: ReturnType<typeof setInterval> | null = null;\n\n // Start the spinner with initial message\n const initialMessage = formatSpinnerMessage(currentContext, 0);\n spinner.start(initialMessage);\n\n // Update elapsed time every second\n intervalId = setInterval(() => {\n const elapsed = Date.now() - startTime;\n spinner.message(formatSpinnerMessage(currentContext, elapsed));\n }, 1000);\n\n const cleanup = (): void => {\n if (intervalId) {\n clearInterval(intervalId);\n intervalId = null;\n }\n };\n\n return {\n message(msg: string): void {\n spinner.message(msg);\n },\n\n update(newContext: SpinnerContext): void {\n currentContext = newContext;\n const elapsed = Date.now() - startTime;\n spinner.message(formatSpinnerMessage(currentContext, elapsed));\n },\n\n stop(msg?: string): void {\n cleanup();\n const elapsed = Date.now() - startTime;\n const defaultMsg = formatSpinnerMessage(currentContext, elapsed);\n spinner.stop(msg ?? `✓ ${defaultMsg}`);\n },\n\n error(msg: string): void {\n cleanup();\n spinner.stop(pc.red(`✗ ${msg}`));\n },\n\n getElapsedMs(): number {\n return Date.now() - startTime;\n },\n };\n}\n\n/**\n * Create a no-op spinner handle for quiet mode or non-TTY environments.\n */\nexport function createNoOpSpinner(): SpinnerHandle {\n const startTime = Date.now();\n // Use explicit undefined returns to avoid empty-function lint errors\n const noop = (): void => undefined;\n return {\n message: noop,\n update: noop,\n stop: noop,\n error: noop,\n getElapsedMs: () => Date.now() - startTime,\n };\n}\n\n/**\n * Create a spinner if appropriate for the context.\n * Returns a no-op spinner in quiet mode or when stdout is not a TTY.\n */\nexport function createSpinnerIfTty(context: SpinnerContext, ctx: CommandContext): SpinnerHandle {\n if (ctx.quiet || !process.stdout.isTTY) {\n return createNoOpSpinner();\n }\n return createSpinner(context);\n}\n\n// =============================================================================\n// Output Format Utilities\n// =============================================================================\n\n/**\n * Valid format options for Commander choice validation.\n */\nexport const OUTPUT_FORMATS: OutputFormat[] = [\n 'console',\n 'plaintext',\n 'yaml',\n 'json',\n 'markform',\n 'markdown',\n];\n\n/**\n * Extract command context from Commander options.\n */\nexport function getCommandContext(command: Command): CommandContext {\n const opts = command.optsWithGlobals<{\n dryRun?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n format?: OutputFormat;\n formsDir?: string;\n overwrite?: boolean;\n }>();\n return {\n dryRun: opts.dryRun ?? false,\n verbose: opts.verbose ?? false,\n quiet: opts.quiet ?? false,\n format: opts.format ?? 'console',\n formsDir: opts.formsDir,\n overwrite: opts.overwrite ?? false,\n };\n}\n\n/**\n * Check if output should use colors.\n * Returns true for console format when stdout is a TTY.\n */\nexport function shouldUseColors(ctx: CommandContext): boolean {\n if (ctx.format === 'plaintext' || ctx.format === 'yaml' || ctx.format === 'json') {\n return false;\n }\n // console format: use colors if stdout is a TTY and NO_COLOR is not set\n return process.stdout.isTTY && !process.env.NO_COLOR;\n}\n\n/**\n * Format structured data according to output format.\n *\n * JSON and YAML outputs are converted to snake_case keys for consistency.\n */\nexport function formatOutput(\n ctx: CommandContext,\n data: unknown,\n consoleFormatter?: (data: unknown, useColors: boolean) => string,\n): string {\n switch (ctx.format) {\n case 'json':\n return JSON.stringify(convertKeysToSnakeCase(data), null, 2);\n case 'yaml':\n return YAML.stringify(convertKeysToSnakeCase(data));\n case 'plaintext':\n case 'console':\n default:\n if (consoleFormatter) {\n return consoleFormatter(data, shouldUseColors(ctx));\n }\n // Default: use YAML for readable console output\n return YAML.stringify(convertKeysToSnakeCase(data));\n }\n}\n\n/**\n * Log a dry-run message.\n */\nexport function logDryRun(message: string, details?: unknown): void {\n console.error(pc.yellow(`[DRY RUN] ${message}`));\n if (details) {\n console.error(pc.dim(JSON.stringify(details, null, 2)));\n }\n}\n\n/**\n * Log a verbose message (only shown if --verbose is set).\n */\nexport function logVerbose(ctx: CommandContext, message: string): void {\n if (ctx.verbose) {\n console.error(pc.dim(message));\n }\n}\n\n/**\n * Log an info message (hidden if --quiet is set).\n */\nexport function logInfo(ctx: CommandContext, message: string): void {\n if (!ctx.quiet) {\n console.error(message);\n }\n}\n\n/**\n * Log an error message (always shown).\n */\nexport function logError(message: string): void {\n console.error(pc.red(`Error: ${message}`));\n}\n\n/**\n * Log a success message (hidden if --quiet is set).\n */\nexport function logSuccess(ctx: CommandContext, message: string): void {\n if (!ctx.quiet) {\n console.error(pc.green(message));\n }\n}\n\n/**\n * Log a timing message (hidden if --quiet is set).\n */\nexport function logTiming(ctx: CommandContext, label: string, durationMs: number): void {\n if (!ctx.quiet) {\n const seconds = (durationMs / 1000).toFixed(1);\n console.error(pc.cyan(`⏰ ${label}: ${seconds}s`));\n }\n}\n\n/**\n * Log a warning message (hidden if --quiet is set).\n */\nexport function logWarn(ctx: CommandContext, message: string): void {\n if (!ctx.quiet) {\n console.error(pc.yellow(`⚠️ ${message}`));\n }\n}\n\n/**\n * Strip HTML comments from markdown content.\n * Removes <!-- ... --> blocks (including multiline) and trims leading whitespace.\n */\nexport function stripHtmlComments(content: string): string {\n // Remove HTML comments (multiline-safe)\n const stripped = content.replace(/<!--[\\s\\S]*?-->/g, '');\n // Trim leading whitespace that may remain after comment removal\n return stripped.replace(/^\\s+/, '');\n}\n\n/**\n * Format a file path for display: relative to cwd, colored green.\n * If the path is within the cwd, shows as relative (e.g., \"./simple-filled1.form.md\")\n * If outside cwd, shows the absolute path.\n */\nexport function formatPath(absolutePath: string, cwd: string = process.cwd()): string {\n const relativePath = relative(cwd, absolutePath);\n // If the relative path doesn't start with \"..\", it's within cwd\n const displayPath = relativePath.startsWith('..') ? absolutePath : `./${relativePath}`;\n return pc.green(displayPath);\n}\n\n/**\n * Read a file and return its contents.\n */\nexport async function readFile(filePath: string): Promise<string> {\n const { readFile: fsReadFile } = await import('node:fs/promises');\n return fsReadFile(filePath, 'utf-8');\n}\n\n/**\n * Write contents to a file atomically.\n *\n * Uses the atomically library to prevent partial or corrupted files\n * if the process crashes mid-write.\n */\nexport async function writeFile(filePath: string, contents: string): Promise<void> {\n const { writeFile: atomicWriteFile } = await import('atomically');\n await atomicWriteFile(filePath, contents);\n}\n\n/**\n * Ensure the forms directory exists, creating it if necessary.\n * Uses recursive mkdir so parent directories are created as needed.\n *\n * @param formsDir Absolute path to the forms directory\n */\nexport async function ensureFormsDir(formsDir: string): Promise<void> {\n await mkdir(formsDir, { recursive: true });\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
 
2
- import { A as MarkformSectionInputSchema, B as ProgressCountsSchema, R as PatchSchema, ht as StructureSummarySchema, z as PatchWarningSchema } from "./coreTypes-CctFK6uE.mjs";
3
- import { $ as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN, A as tryParseSentinelResponse, B as isTagNode, D as detectSyntaxStyle, F as getBooleanAttr, G as DEFAULT_MAX_PARALLEL_AGENTS, H as AGENT_ROLE, I as getNumberAttr, J as DEFAULT_MAX_STEPS_PER_TURN, K as DEFAULT_MAX_PATCHES_PER_TURN, L as getStringArrayAttr, M as extractFenceValue, N as extractOptionItems, O as preprocessCommentSyntax, P as extractTableContent, Pt as wrapApiError, Q as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, R as getStringAttr, S as computeStructureSummary, St as MarkformParseError, V as parseOptionText, W as DEFAULT_MAX_ISSUES_PER_TURN, Y as DEFAULT_MAX_TURNS, Z as DEFAULT_PRIORITY, _ as inspect, a as WEB_SEARCH_INSTRUCTIONS, c as filterIssuesByOrder, d as coerceInputContext, dt as transformHarnessConfigToTs, et as DEFAULT_ROLES, g as getFieldsForRoles, ht as getWebSearchConfig, i as SECTION_HEADERS, j as CHECKBOX_MARKERS, l as filterIssuesByScope, m as applyPatches, n as GENERAL_INSTRUCTIONS, o as getIssuesIntro, q as DEFAULT_MAX_RETRIES, r as ISSUES_HEADER, s as getPatchFormatHint, t as DEFAULT_SYSTEM_PROMPT, tt as DEFAULT_ROLE_INSTRUCTIONS, w as serializeForm, x as computeProgressSummary, yt as MarkformConfigError, z as getValidateAttr } from "./prompts-BCnYaH4_.mjs";
2
+ import { A as MarkformSectionInputSchema, B as ProgressCountsSchema, R as PatchSchema, ht as StructureSummarySchema, z as PatchWarningSchema } from "./coreTypes-DIv9Aabl.mjs";
3
+ import { $ as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN, A as tryParseSentinelResponse, B as isTagNode, D as detectSyntaxStyle, F as getBooleanAttr, G as DEFAULT_MAX_PARALLEL_AGENTS, H as AGENT_ROLE, I as getNumberAttr, J as DEFAULT_MAX_STEPS_PER_TURN, K as DEFAULT_MAX_PATCHES_PER_TURN, L as getStringArrayAttr, M as extractFenceValue, N as extractOptionItems, O as preprocessCommentSyntax, P as extractTableContent, Pt as wrapApiError, Q as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, R as getStringAttr, S as computeStructureSummary, St as MarkformParseError, V as parseOptionText, W as DEFAULT_MAX_ISSUES_PER_TURN, Y as DEFAULT_MAX_TURNS, Z as DEFAULT_PRIORITY, _ as inspect, a as WEB_SEARCH_INSTRUCTIONS, c as filterIssuesByOrder, d as coerceInputContext, dt as transformHarnessConfigToTs, et as DEFAULT_ROLES, g as getFieldsForRoles, ht as getWebSearchConfig, i as SECTION_HEADERS, j as CHECKBOX_MARKERS, l as filterIssuesByScope, m as applyPatches, n as GENERAL_INSTRUCTIONS, o as getIssuesIntro, q as DEFAULT_MAX_RETRIES, r as ISSUES_HEADER, s as getPatchFormatHint, t as DEFAULT_SYSTEM_PROMPT, tt as DEFAULT_ROLE_INSTRUCTIONS, w as serializeForm, x as computeProgressSummary, yt as MarkformConfigError, z as getValidateAttr } from "./prompts-DaPKumGY.mjs";
4
4
  import { z } from "zod";
5
5
  import Markdoc from "@markdoc/markdoc";
6
6
  import YAML from "yaml";
@@ -80,10 +80,11 @@ function parseCellValue(rawValue, columnType) {
80
80
  state: sentinel.type === "skip" ? "skipped" : "aborted",
81
81
  reason: sentinel.reason
82
82
  };
83
+ const unescaped = trimmed.replace(/\\[|]/g, "|").replace(/<br\s*\/?>/gi, "\n");
83
84
  switch (columnType) {
84
85
  case "string": return {
85
86
  state: "answered",
86
- value: trimmed
87
+ value: unescaped
87
88
  };
88
89
  case "number": {
89
90
  const num = parseFloat(trimmed);
@@ -799,6 +800,13 @@ function parseColumnsFromAttributes(node, fieldId, tableHeaderLabels) {
799
800
  const typeSpec = columnTypesRaw?.[i];
800
801
  let type = "string";
801
802
  let required = false;
803
+ let minLength;
804
+ let maxLength;
805
+ let pattern;
806
+ let enumValues;
807
+ let min;
808
+ let max;
809
+ let integer;
802
810
  if (typeSpec !== void 0) {
803
811
  if (typeof typeSpec === "string") {
804
812
  if (!isValidColumnType(typeSpec)) throw new MarkformParseError(`table-field '${fieldId}' has invalid column type '${String(typeSpec)}' for column '${id}'. Valid types: string, number, url, date, year`);
@@ -808,17 +816,68 @@ function parseColumnsFromAttributes(node, fieldId, tableHeaderLabels) {
808
816
  if (!isValidColumnType(typeObj.type)) throw new MarkformParseError(`table-field '${fieldId}' has invalid column type '${String(typeObj.type)}' for column '${id}'. Valid types: string, number, url, date, year`);
809
817
  type = typeObj.type;
810
818
  required = typeObj.required ?? false;
819
+ if (typeof typeObj.minLength === "number") minLength = typeObj.minLength;
820
+ if (typeof typeObj.maxLength === "number") maxLength = typeObj.maxLength;
821
+ if (typeof typeObj.pattern === "string") pattern = typeObj.pattern;
822
+ if (Array.isArray(typeObj.enum)) enumValues = typeObj.enum;
823
+ if (typeObj.min !== void 0) min = typeObj.min;
824
+ if (typeObj.max !== void 0) max = typeObj.max;
825
+ if (typeof typeObj.integer === "boolean") integer = typeObj.integer;
826
+ validateColumnConstraints(fieldId, id, type, typeObj);
811
827
  }
812
828
  }
813
- columns.push({
829
+ const col = {
814
830
  id,
815
831
  label,
816
832
  type,
817
833
  required
818
- });
834
+ };
835
+ if (minLength !== void 0) col.minLength = minLength;
836
+ if (maxLength !== void 0) col.maxLength = maxLength;
837
+ if (pattern !== void 0) col.pattern = pattern;
838
+ if (enumValues !== void 0) col.enum = enumValues;
839
+ if (min !== void 0) col.min = min;
840
+ if (max !== void 0) col.max = max;
841
+ if (integer !== void 0) col.integer = integer;
842
+ columns.push(col);
819
843
  }
820
844
  return columns;
821
845
  }
846
+ /** String-only constraints. */
847
+ const STRING_ONLY_CONSTRAINTS = [
848
+ "minLength",
849
+ "maxLength",
850
+ "pattern",
851
+ "enum"
852
+ ];
853
+ /** Number-only constraints. */
854
+ const NUMBER_ONLY_CONSTRAINTS = ["integer"];
855
+ /** Constraints valid per column type. */
856
+ const VALID_CONSTRAINTS_BY_TYPE = {
857
+ string: [...STRING_ONLY_CONSTRAINTS],
858
+ number: [
859
+ "min",
860
+ "max",
861
+ ...NUMBER_ONLY_CONSTRAINTS
862
+ ],
863
+ date: ["min", "max"],
864
+ year: ["min", "max"],
865
+ url: []
866
+ };
867
+ /**
868
+ * Validate that per-column constraints are appropriate for the column type.
869
+ * Throws MarkformParseError for mismatched constraints (e.g. minLength on a number column).
870
+ */
871
+ function validateColumnConstraints(fieldId, columnId, type, typeObj) {
872
+ const allConstraintKeys = [
873
+ ...STRING_ONLY_CONSTRAINTS,
874
+ ...NUMBER_ONLY_CONSTRAINTS,
875
+ "min",
876
+ "max"
877
+ ];
878
+ const validKeys = VALID_CONSTRAINTS_BY_TYPE[type];
879
+ for (const key of allConstraintKeys) if (typeObj[key] !== void 0 && !validKeys.includes(key)) throw new MarkformParseError(`table-field '${fieldId}' column '${columnId}': constraint '${key}' is not valid for type '${type}'. Valid constraints for '${type}': ${validKeys.length > 0 ? validKeys.join(", ") : "none"}`);
880
+ }
822
881
  /**
823
882
  * Parse a table-field tag.
824
883
  *
@@ -1645,7 +1704,11 @@ function extractDocBlocks(ast, idIndex) {
1645
1704
  else if (n.type === "softbreak" || n.type === "hardbreak") bodyMarkdown += "\n";
1646
1705
  if (n.children && Array.isArray(n.children)) for (const c of n.children) extractText(c);
1647
1706
  }
1648
- if (node.children && Array.isArray(node.children)) for (const child of node.children) extractText(child);
1707
+ if (node.children && Array.isArray(node.children)) for (let ci = 0; ci < node.children.length; ci++) {
1708
+ const child = node.children[ci];
1709
+ if (ci > 0 && child.type === "paragraph") bodyMarkdown += "\n\n";
1710
+ extractText(child);
1711
+ }
1649
1712
  docs.push({
1650
1713
  tag,
1651
1714
  ref,
@@ -1900,7 +1963,7 @@ function tableFieldToJsonSchema(field, docs, options, groupId) {
1900
1963
  const rowProperties = {};
1901
1964
  const requiredColumns = [];
1902
1965
  for (const col of field.columns) {
1903
- rowProperties[col.id] = columnToJsonSchema(col);
1966
+ rowProperties[col.id] = columnToJsonSchema(col, options);
1904
1967
  if (col.required) requiredColumns.push(col.id);
1905
1968
  }
1906
1969
  const rowSchema = {
@@ -1920,14 +1983,21 @@ function tableFieldToJsonSchema(field, docs, options, groupId) {
1920
1983
  if (options.includeExtensions) schema["x-markform"] = buildFieldExtension(field, groupId);
1921
1984
  return schema;
1922
1985
  }
1923
- function columnToJsonSchema(col) {
1986
+ function columnToJsonSchema(col, options) {
1924
1987
  const schema = { title: col.label };
1925
1988
  switch (col.type) {
1926
1989
  case "string":
1927
1990
  schema.type = "string";
1991
+ if (col.minLength !== void 0) schema.minLength = col.minLength;
1992
+ if (col.maxLength !== void 0) schema.maxLength = col.maxLength;
1993
+ if (col.pattern !== void 0) schema.pattern = col.pattern;
1994
+ if (col.enum !== void 0 && col.enum.length > 0) schema.enum = col.enum;
1928
1995
  break;
1929
1996
  case "number":
1930
1997
  schema.type = "number";
1998
+ if (col.integer) schema.type = "integer";
1999
+ if (typeof col.min === "number") schema.minimum = col.min;
2000
+ if (typeof col.max === "number") schema.maximum = col.max;
1931
2001
  break;
1932
2002
  case "url":
1933
2003
  schema.type = "string";
@@ -1936,9 +2006,15 @@ function columnToJsonSchema(col) {
1936
2006
  case "date":
1937
2007
  schema.type = "string";
1938
2008
  schema.format = "date";
2009
+ if (options.draft !== "draft-07") {
2010
+ if (typeof col.min === "string") schema.formatMinimum = col.min;
2011
+ if (typeof col.max === "string") schema.formatMaximum = col.max;
2012
+ }
1939
2013
  break;
1940
2014
  case "year":
1941
2015
  schema.type = "integer";
2016
+ if (typeof col.min === "number") schema.minimum = col.min;
2017
+ if (typeof col.max === "number") schema.maximum = col.max;
1942
2018
  break;
1943
2019
  }
1944
2020
  return schema;
@@ -3009,6 +3085,7 @@ var FillRecordCollector = class {
3009
3085
  failedCalls,
3010
3086
  successRate: totalCalls > 0 ? successfulCalls / totalCalls * 100 : 0,
3011
3087
  totalDurationMs,
3088
+ avgDurationMs: totalCalls > 0 ? totalDurationMs / totalCalls : 0,
3012
3089
  byTool
3013
3090
  };
3014
3091
  }
@@ -3030,7 +3107,7 @@ var FillRecordCollector = class {
3030
3107
  return Math.round(sorted[lower] * (1 - weight) + sorted[upper] * weight);
3031
3108
  }
3032
3109
  calculateTimingBreakdown(totalMs, llmTimeMs, toolTimeMs) {
3033
- const overheadMs = Math.max(0, totalMs - llmTimeMs - toolTimeMs);
3110
+ const overheadMs = Math.max(0, totalMs - llmTimeMs);
3034
3111
  return {
3035
3112
  totalMs,
3036
3113
  llmTimeMs,
@@ -3055,7 +3132,8 @@ var FillRecordCollector = class {
3055
3132
  ms: overheadMs,
3056
3133
  percentage: totalMs > 0 ? overheadMs / totalMs * 100 : 0
3057
3134
  }
3058
- ]
3135
+ ],
3136
+ llmParallelism: totalMs > 0 ? llmTimeMs / totalMs : 0
3059
3137
  };
3060
3138
  }
3061
3139
  buildExecutionMetadata(timeline) {
@@ -9426,17 +9504,25 @@ function mergeCallbacks(userCallbacks, collector) {
9426
9504
  } catch (e) {
9427
9505
  warnCallbackError("onWebSearch", e);
9428
9506
  }
9429
- }
9507
+ },
9508
+ onError: userCallbacks.onError ? (error, context) => {
9509
+ try {
9510
+ userCallbacks.onError?.(error, context);
9511
+ } catch (e) {
9512
+ warnCallbackError("onError", e);
9513
+ }
9514
+ } : void 0
9430
9515
  };
9431
9516
  }
9432
- function buildErrorResult(form, errors, warnings, record) {
9517
+ function buildErrorResult(form, errors, warnings, record, sourceError) {
9433
9518
  const values = {};
9434
9519
  for (const [fieldId, response] of Object.entries(form.responsesByFieldId)) if (response.state === "answered" && response.value) values[fieldId] = response.value;
9435
9520
  const result = {
9436
9521
  status: {
9437
9522
  ok: false,
9438
9523
  reason: "error",
9439
- message: errors.join("; ")
9524
+ message: errors.join("; "),
9525
+ error: sourceError
9440
9526
  },
9441
9527
  markdown: serializeForm(form),
9442
9528
  values,
@@ -9515,7 +9601,8 @@ async function fillForm(options) {
9515
9601
  status: {
9516
9602
  ok: false,
9517
9603
  reason: "error",
9518
- message: `Form parse error: ${error instanceof Error ? error.message : String(error)}`
9604
+ message: `Form parse error: ${error instanceof Error ? error.message : String(error)}`,
9605
+ error: error instanceof Error ? error : void 0
9519
9606
  },
9520
9607
  markdown: typeof options.form === "string" ? options.form : "",
9521
9608
  values: {},
@@ -9546,7 +9633,7 @@ async function fillForm(options) {
9546
9633
  } else model = options.model;
9547
9634
  } catch (error) {
9548
9635
  const message = error instanceof Error ? error.message : String(error);
9549
- return buildErrorResult(form, [`Model resolution error: ${message}`], []);
9636
+ return buildErrorResult(form, [`Model resolution error: ${message}`], [], void 0, error instanceof Error ? error : void 0);
9550
9637
  }
9551
9638
  else if (typeof options.model === "string" && options.model.includes("/")) provider = options.model.split("/")[0];
9552
9639
  const modelString = typeof options.model === "string" ? options.model : "custom";
@@ -9639,15 +9726,22 @@ async function fillForm(options) {
9639
9726
  response = await agent.fillFormTool(turnIssues, form, maxPatchesPerTurn, previousRejections);
9640
9727
  } catch (error) {
9641
9728
  const errorMessage = error instanceof Error ? error.message : String(error);
9729
+ const errorObj = error instanceof Error ? error : void 0;
9642
9730
  let record;
9643
9731
  if (collector) {
9644
9732
  collector.setStatus("failed", errorMessage);
9645
9733
  record = collector.getRecord(getProgressCounts(form, targetRoles));
9646
9734
  }
9735
+ if (errorObj && mergedCallbacks?.onError) try {
9736
+ mergedCallbacks.onError(errorObj, { turnNumber: turnCount + 1 });
9737
+ } catch (cbError) {
9738
+ warnCallbackError("onError", cbError);
9739
+ }
9647
9740
  return buildResult(form, turnCount, totalPatches, {
9648
9741
  ok: false,
9649
9742
  reason: "error",
9650
- message: errorMessage
9743
+ message: errorMessage,
9744
+ error: errorObj
9651
9745
  }, inputContextWarnings, turnIssues, record);
9652
9746
  }
9653
9747
  const { patches, stats } = response;
@@ -9919,6 +10013,12 @@ async function runMultiTurnForItems(form, agent, items, targetRoles, maxPatchesP
9919
10013
  response = await agent.fillFormTool(scopedIssues, form, maxPatchesPerTurn, previousRejections);
9920
10014
  } catch (error) {
9921
10015
  const errorMessage = error instanceof Error ? error.message : String(error);
10016
+ const errorObj = error instanceof Error ? error : void 0;
10017
+ if (errorObj && mergedCallbacks?.onError) try {
10018
+ mergedCallbacks.onError(errorObj, { turnNumber: startTurn + turnsUsed + 1 });
10019
+ } catch (cbError) {
10020
+ warnCallbackError("onError", cbError);
10021
+ }
9922
10022
  return {
9923
10023
  patchesApplied,
9924
10024
  turnsUsed,
@@ -9926,7 +10026,8 @@ async function runMultiTurnForItems(form, agent, items, targetRoles, maxPatchesP
9926
10026
  status: {
9927
10027
  ok: false,
9928
10028
  reason: "error",
9929
- message: errorMessage
10029
+ message: errorMessage,
10030
+ error: errorObj
9930
10031
  }
9931
10032
  };
9932
10033
  }
@@ -10001,12 +10102,24 @@ function formatNumber(n) {
10001
10102
  * Format milliseconds as a human-readable duration.
10002
10103
  */
10003
10104
  function formatDuration(ms) {
10004
- if (ms < 1e3) return `${ms}ms`;
10105
+ if (ms < 1e3) return `${Math.round(ms)}ms`;
10005
10106
  const seconds = ms / 1e3;
10006
10107
  if (seconds < 60) return `${seconds.toFixed(1)}s`;
10007
10108
  return `${Math.floor(seconds / 60)}m ${(seconds % 60).toFixed(0)}s`;
10008
10109
  }
10009
10110
  /**
10111
+ * Format a rate value (like s/field or s/turn) with appropriate significant figures.
10112
+ * >= 10s: 1 decimal (e.g., 12.3s/field)
10113
+ * >= 1s: 2 decimals (e.g., 3.45s/field)
10114
+ * < 1s: show as ms (e.g., 450ms/field)
10115
+ */
10116
+ function formatRate(ms, unit) {
10117
+ const seconds = ms / 1e3;
10118
+ if (seconds >= 10) return `${seconds.toFixed(1)}s/${unit}`;
10119
+ if (seconds >= 1) return `${seconds.toFixed(2)}s/${unit}`;
10120
+ return `${Math.round(ms)}ms/${unit}`;
10121
+ }
10122
+ /**
10010
10123
  * Format a percentage.
10011
10124
  */
10012
10125
  function formatPercent(value, total) {
@@ -10033,7 +10146,11 @@ function formatFillRecordSummary(record, options = {}) {
10033
10146
  const lines = [];
10034
10147
  const statusText = record.status === "completed" ? "Fill completed" : "Fill incomplete";
10035
10148
  const turnsText = `${record.execution.totalTurns} turn${record.execution.totalTurns !== 1 ? "s" : ""}`;
10036
- let statusLine = `${statusText} in ${formatDuration(record.durationMs)} (${turnsText})`;
10149
+ const rateParts = [];
10150
+ if (record.execution.totalTurns > 0) rateParts.push(formatRate(record.durationMs / record.execution.totalTurns, "turn"));
10151
+ if (record.formProgress.answeredFields > 0) rateParts.push(formatRate(record.durationMs / record.formProgress.answeredFields, "field"));
10152
+ const ratesText = rateParts.length > 0 ? `, ${rateParts.join(", ")}` : "";
10153
+ let statusLine = `${statusText} in ${formatDuration(record.durationMs)} (${turnsText}${ratesText})`;
10037
10154
  if (record.status !== "completed" && record.statusDetail) statusLine += ` - ${record.statusDetail}`;
10038
10155
  lines.push(statusLine);
10039
10156
  const timelineEmpty = record.timeline.length === 0;
@@ -10049,6 +10166,7 @@ function formatFillRecordSummary(record, options = {}) {
10049
10166
  toolLine += ` (${formatNumber(toolSummary.successfulCalls)} succeeded`;
10050
10167
  if (toolSummary.failedCalls > 0) toolLine += `, ${formatNumber(toolSummary.failedCalls)} failed`;
10051
10168
  toolLine += ")";
10169
+ toolLine += `, avg ${formatDuration(toolSummary.avgDurationMs)} each`;
10052
10170
  }
10053
10171
  lines.push(toolLine);
10054
10172
  if (verbose && toolSummary.byTool.length > 0) for (const tool of toolSummary.byTool) {
@@ -10057,14 +10175,22 @@ function formatFillRecordSummary(record, options = {}) {
10057
10175
  if (tool.timing.p95Ms !== void 0 && tool.callCount > 1) toolDetail += `, p95 ${formatDuration(tool.timing.p95Ms)}`;
10058
10176
  lines.push(toolDetail);
10059
10177
  }
10178
+ const { timingBreakdown } = record;
10179
+ const llmPct = Math.round(timingBreakdown.breakdown.find((b) => b.category === "llm")?.percentage ?? 0);
10180
+ const toolPct = Math.round(timingBreakdown.breakdown.find((b) => b.category === "tools")?.percentage ?? 0);
10181
+ const overheadPct = Math.round(timingBreakdown.breakdown.find((b) => b.category === "overhead")?.percentage ?? 0);
10060
10182
  if (verbose) {
10061
- lines.push("");
10062
- const { timingBreakdown } = record;
10063
- const llmPct = timingBreakdown.breakdown.find((b) => b.category === "llm")?.percentage ?? 0;
10064
- const toolPct = timingBreakdown.breakdown.find((b) => b.category === "tools")?.percentage ?? 0;
10065
- const overheadPct = timingBreakdown.breakdown.find((b) => b.category === "overhead")?.percentage ?? 0;
10066
10183
  const timingLine = `Timing: ${llmPct}% LLM (${formatDuration(timingBreakdown.llmTimeMs)}) | ${toolPct}% tools (${formatDuration(timingBreakdown.toolTimeMs)}) | ${overheadPct}% overhead (${formatDuration(timingBreakdown.overheadMs)})`;
10067
10184
  lines.push(timingLine);
10185
+ const ep = timingBreakdown.llmParallelism;
10186
+ if (record.execution.parallelEnabled) {
10187
+ const threadCount = record.execution.executionThreads.length;
10188
+ const orderCount = record.execution.orderLevels.length;
10189
+ lines.push(` Effective parallelism: ${ep.toFixed(1)}x (${threadCount} threads, ${orderCount} order level${orderCount !== 1 ? "s" : ""})`);
10190
+ } else if (ep < .8) lines.push(` Effective parallelism: ${ep.toFixed(1)}x`);
10191
+ } else {
10192
+ const timingLine = `Timing: ${llmPct}% LLM | ${toolPct}% tools | ${overheadPct}% overhead`;
10193
+ lines.push(timingLine);
10068
10194
  }
10069
10195
  lines.push("");
10070
10196
  const { formProgress } = record;
@@ -10169,7 +10295,8 @@ const TimingBreakdownSchema = z.object({
10169
10295
  llmTimeMs: z.number().int().nonnegative(),
10170
10296
  toolTimeMs: z.number().int().nonnegative(),
10171
10297
  overheadMs: z.number().int().nonnegative(),
10172
- breakdown: z.array(TimingBreakdownItemSchema)
10298
+ breakdown: z.array(TimingBreakdownItemSchema),
10299
+ llmParallelism: z.number().nonnegative()
10173
10300
  });
10174
10301
  /**
10175
10302
  * Aggregated tool usage statistics.
@@ -10180,6 +10307,7 @@ const ToolSummarySchema = z.object({
10180
10307
  failedCalls: z.number().int().nonnegative(),
10181
10308
  successRate: z.number().nonnegative(),
10182
10309
  totalDurationMs: z.number().int().nonnegative(),
10310
+ avgDurationMs: z.number().nonnegative(),
10183
10311
  byTool: z.array(ToolStatsSchema)
10184
10312
  });
10185
10313
  /**
@@ -10399,8 +10527,8 @@ function validateResearchForm(form) {
10399
10527
  //#endregion
10400
10528
  //#region src/index.ts
10401
10529
  /** Markform version (injected at build time). */
10402
- const VERSION = "0.1.24";
10530
+ const VERSION = "0.1.25";
10403
10531
 
10404
10532
  //#endregion
10405
10533
  export { MockAgent as A, fieldToJsonSchema as B, getProviderInfo as C, createLiveAgent as D, buildMockWireFormat as E, isCellRef as F, injectHeaderIds as G, parseForm as H, isFieldRef as I, parseCellValue as J, findAllHeadings as K, isQualifiedRef as L, FormHarness as M, createHarness as N, FillRecordCollector as O, getFieldId as P, parseScopeRef as R, BUILT_IN_PROVIDERS as S, resolveModel as T, findAllCheckboxes as U, formToJsonSchema as V, injectCheckboxIds as W, parseRawTable as X, parseMarkdownTable as Y, resolveHarnessConfig as _, ExecutionMetadataSchema as a, createParallelHarness as b, TimelineEntrySchema as c, ToolCallRecordSchema as d, ToolStatsSchema as f, formatFillRecordSummary as g, stripUnstableFillRecordFields as h, runResearch as i, createMockAgent as j, computeExecutionPlan as k, TimingBreakdownItemSchema as l, isEmptyFillRecord as m, isResearchForm as n, FillRecordSchema as o, ToolSummarySchema as p, findEnclosingHeadings as q, validateResearchForm as r, FillRecordStatusSchema as s, VERSION as t, TimingBreakdownSchema as u, fillForm as v, getProviderNames as w, scopeIssuesForItem as x, ParallelHarness as y, serializeScopeRef as z };
10406
- //# sourceMappingURL=src-C5OWf1dL.mjs.map
10534
+ //# sourceMappingURL=src-DrXmaOWl.mjs.map