markform 0.0.1 → 0.1.1
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/LICENSE +664 -0
- package/README.md +216 -44
- package/dist/ai-sdk.d.mts +2 -3
- package/dist/ai-sdk.mjs +2 -3
- package/dist/{apply-C0vjijlP.mjs → apply-BQdd-fdx.mjs} +381 -38
- package/dist/bin.d.mts +0 -0
- package/dist/bin.mjs +4 -5
- package/dist/{cli-9fvFySww.mjs → cli-pjOiHgCW.mjs} +506 -94
- package/dist/cli.d.mts +1 -2
- package/dist/cli.mjs +3 -3
- package/dist/{coreTypes-T7dAuewt.d.mts → coreTypes--6etkcwb.d.mts} +1088 -131
- package/dist/index.d.mts +90 -10
- package/dist/index.mjs +2 -2
- package/dist/{src-DBD3Dt4f.mjs → src-Cs4_9lWP.mjs} +461 -96
- package/examples/simple/simple-mock-filled.form.md +36 -0
- package/examples/simple/simple-skipped-filled.form.md +147 -0
- package/examples/simple/simple-with-skips.session.yaml +230 -0
- package/examples/simple/simple.form.md +22 -0
- package/examples/simple/simple.session.yaml +60 -28
- package/examples/startup-deep-research/startup-deep-research.form.md +404 -0
- package/examples/startup-research/startup-research-mock-filled.form.md +307 -0
- package/examples/startup-research/startup-research.form.md +211 -0
- package/package.json +17 -16
- package/dist/ai-sdk.mjs.map +0 -1
- package/dist/apply-C0vjijlP.mjs.map +0 -1
- package/dist/bin.mjs.map +0 -1
- package/dist/cli-9fvFySww.mjs.map +0 -1
- package/dist/src-DBD3Dt4f.mjs.map +0 -1
|
@@ -30,6 +30,7 @@ const CheckboxModeSchema = z.enum([
|
|
|
30
30
|
"explicit"
|
|
31
31
|
]);
|
|
32
32
|
const FillModeSchema = z.enum(["continue", "overwrite"]);
|
|
33
|
+
const MockModeSchema = z.enum(["mock", "live"]);
|
|
33
34
|
const ApprovalModeSchema = z.enum(["none", "blocking"]);
|
|
34
35
|
const FieldKindSchema = z.enum([
|
|
35
36
|
"string",
|
|
@@ -37,7 +38,9 @@ const FieldKindSchema = z.enum([
|
|
|
37
38
|
"string_list",
|
|
38
39
|
"checkboxes",
|
|
39
40
|
"single_select",
|
|
40
|
-
"multi_select"
|
|
41
|
+
"multi_select",
|
|
42
|
+
"url",
|
|
43
|
+
"url_list"
|
|
41
44
|
]);
|
|
42
45
|
const FieldPriorityLevelSchema = z.enum([
|
|
43
46
|
"high",
|
|
@@ -100,13 +103,26 @@ const MultiSelectFieldSchema = z.object({
|
|
|
100
103
|
minSelections: z.number().int().nonnegative().optional(),
|
|
101
104
|
maxSelections: z.number().int().nonnegative().optional()
|
|
102
105
|
});
|
|
106
|
+
const UrlFieldSchema = z.object({
|
|
107
|
+
...FieldBaseSchemaPartial,
|
|
108
|
+
kind: z.literal("url")
|
|
109
|
+
});
|
|
110
|
+
const UrlListFieldSchema = z.object({
|
|
111
|
+
...FieldBaseSchemaPartial,
|
|
112
|
+
kind: z.literal("url_list"),
|
|
113
|
+
minItems: z.number().int().nonnegative().optional(),
|
|
114
|
+
maxItems: z.number().int().nonnegative().optional(),
|
|
115
|
+
uniqueItems: z.boolean().optional()
|
|
116
|
+
});
|
|
103
117
|
const FieldSchema = z.discriminatedUnion("kind", [
|
|
104
118
|
StringFieldSchema,
|
|
105
119
|
NumberFieldSchema,
|
|
106
120
|
StringListFieldSchema,
|
|
107
121
|
CheckboxesFieldSchema,
|
|
108
122
|
SingleSelectFieldSchema,
|
|
109
|
-
MultiSelectFieldSchema
|
|
123
|
+
MultiSelectFieldSchema,
|
|
124
|
+
UrlFieldSchema,
|
|
125
|
+
UrlListFieldSchema
|
|
110
126
|
]);
|
|
111
127
|
const FieldGroupSchema = z.object({
|
|
112
128
|
kind: z.literal("field_group"),
|
|
@@ -144,13 +160,23 @@ const MultiSelectValueSchema = z.object({
|
|
|
144
160
|
kind: z.literal("multi_select"),
|
|
145
161
|
selected: z.array(OptionIdSchema)
|
|
146
162
|
});
|
|
163
|
+
const UrlValueSchema = z.object({
|
|
164
|
+
kind: z.literal("url"),
|
|
165
|
+
value: z.string().nullable()
|
|
166
|
+
});
|
|
167
|
+
const UrlListValueSchema = z.object({
|
|
168
|
+
kind: z.literal("url_list"),
|
|
169
|
+
items: z.array(z.string())
|
|
170
|
+
});
|
|
147
171
|
const FieldValueSchema = z.discriminatedUnion("kind", [
|
|
148
172
|
StringValueSchema,
|
|
149
173
|
NumberValueSchema,
|
|
150
174
|
StringListValueSchema,
|
|
151
175
|
CheckboxesValueSchema,
|
|
152
176
|
SingleSelectValueSchema,
|
|
153
|
-
MultiSelectValueSchema
|
|
177
|
+
MultiSelectValueSchema,
|
|
178
|
+
UrlValueSchema,
|
|
179
|
+
UrlListValueSchema
|
|
154
180
|
]);
|
|
155
181
|
const DocumentationTagSchema = z.enum([
|
|
156
182
|
"description",
|
|
@@ -240,7 +266,9 @@ const FieldProgressSchema = z.object({
|
|
|
240
266
|
state: ProgressStateSchema,
|
|
241
267
|
valid: z.boolean(),
|
|
242
268
|
issueCount: z.number().int().nonnegative(),
|
|
243
|
-
checkboxProgress: CheckboxProgressCountsSchema.optional()
|
|
269
|
+
checkboxProgress: CheckboxProgressCountsSchema.optional(),
|
|
270
|
+
skipped: z.boolean(),
|
|
271
|
+
skipReason: z.string().optional()
|
|
244
272
|
});
|
|
245
273
|
const ProgressCountsSchema = z.object({
|
|
246
274
|
totalFields: z.number().int().nonnegative(),
|
|
@@ -250,7 +278,9 @@ const ProgressCountsSchema = z.object({
|
|
|
250
278
|
incompleteFields: z.number().int().nonnegative(),
|
|
251
279
|
invalidFields: z.number().int().nonnegative(),
|
|
252
280
|
emptyRequiredFields: z.number().int().nonnegative(),
|
|
253
|
-
emptyOptionalFields: z.number().int().nonnegative()
|
|
281
|
+
emptyOptionalFields: z.number().int().nonnegative(),
|
|
282
|
+
answeredFields: z.number().int().nonnegative(),
|
|
283
|
+
skippedFields: z.number().int().nonnegative()
|
|
254
284
|
});
|
|
255
285
|
const ProgressSummarySchema = z.object({
|
|
256
286
|
counts: ProgressCountsSchema,
|
|
@@ -313,10 +343,25 @@ const SetMultiSelectPatchSchema = z.object({
|
|
|
313
343
|
fieldId: IdSchema,
|
|
314
344
|
selected: z.array(OptionIdSchema)
|
|
315
345
|
});
|
|
346
|
+
const SetUrlPatchSchema = z.object({
|
|
347
|
+
op: z.literal("set_url"),
|
|
348
|
+
fieldId: IdSchema,
|
|
349
|
+
value: z.string().nullable()
|
|
350
|
+
});
|
|
351
|
+
const SetUrlListPatchSchema = z.object({
|
|
352
|
+
op: z.literal("set_url_list"),
|
|
353
|
+
fieldId: IdSchema,
|
|
354
|
+
items: z.array(z.string())
|
|
355
|
+
});
|
|
316
356
|
const ClearFieldPatchSchema = z.object({
|
|
317
357
|
op: z.literal("clear_field"),
|
|
318
358
|
fieldId: IdSchema
|
|
319
359
|
});
|
|
360
|
+
const SkipFieldPatchSchema = z.object({
|
|
361
|
+
op: z.literal("skip_field"),
|
|
362
|
+
fieldId: IdSchema,
|
|
363
|
+
reason: z.string().optional()
|
|
364
|
+
});
|
|
320
365
|
const PatchSchema = z.discriminatedUnion("op", [
|
|
321
366
|
SetStringPatchSchema,
|
|
322
367
|
SetNumberPatchSchema,
|
|
@@ -324,7 +369,10 @@ const PatchSchema = z.discriminatedUnion("op", [
|
|
|
324
369
|
SetCheckboxesPatchSchema,
|
|
325
370
|
SetSingleSelectPatchSchema,
|
|
326
371
|
SetMultiSelectPatchSchema,
|
|
327
|
-
|
|
372
|
+
SetUrlPatchSchema,
|
|
373
|
+
SetUrlListPatchSchema,
|
|
374
|
+
ClearFieldPatchSchema,
|
|
375
|
+
SkipFieldPatchSchema
|
|
328
376
|
]);
|
|
329
377
|
const StepResultSchema = z.object({
|
|
330
378
|
structureSummary: StructureSummarySchema,
|
|
@@ -343,14 +391,25 @@ const HarnessConfigSchema = z.object({
|
|
|
343
391
|
targetRoles: z.array(z.string()).optional(),
|
|
344
392
|
fillMode: FillModeSchema.optional()
|
|
345
393
|
});
|
|
394
|
+
const SessionTurnStatsSchema = z.object({
|
|
395
|
+
inputTokens: z.number().int().nonnegative().optional(),
|
|
396
|
+
outputTokens: z.number().int().nonnegative().optional(),
|
|
397
|
+
toolCalls: z.array(z.object({
|
|
398
|
+
name: z.string(),
|
|
399
|
+
count: z.number().int().positive()
|
|
400
|
+
})).optional()
|
|
401
|
+
});
|
|
346
402
|
const SessionTurnSchema = z.object({
|
|
347
403
|
turn: z.number().int().positive(),
|
|
348
404
|
inspect: z.object({ issues: z.array(InspectIssueSchema) }),
|
|
349
405
|
apply: z.object({ patches: z.array(PatchSchema) }),
|
|
350
406
|
after: z.object({
|
|
351
407
|
requiredIssueCount: z.number().int().nonnegative(),
|
|
352
|
-
markdownSha256: z.string()
|
|
353
|
-
|
|
408
|
+
markdownSha256: z.string(),
|
|
409
|
+
answeredFieldCount: z.number().int().nonnegative(),
|
|
410
|
+
skippedFieldCount: z.number().int().nonnegative()
|
|
411
|
+
}),
|
|
412
|
+
llm: SessionTurnStatsSchema.optional()
|
|
354
413
|
});
|
|
355
414
|
const SessionFinalSchema = z.object({
|
|
356
415
|
expectComplete: z.boolean(),
|
|
@@ -358,7 +417,7 @@ const SessionFinalSchema = z.object({
|
|
|
358
417
|
});
|
|
359
418
|
const SessionTranscriptSchema = z.object({
|
|
360
419
|
sessionVersion: z.string(),
|
|
361
|
-
mode:
|
|
420
|
+
mode: MockModeSchema,
|
|
362
421
|
form: z.object({ path: z.string() }),
|
|
363
422
|
validators: z.object({ code: z.string().optional() }).optional(),
|
|
364
423
|
mock: z.object({ completedMock: z.string() }).optional(),
|
|
@@ -472,6 +531,35 @@ function formatSuggestedLlms() {
|
|
|
472
531
|
}
|
|
473
532
|
return lines.join("\n");
|
|
474
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* Web search configuration per provider.
|
|
536
|
+
*/
|
|
537
|
+
const WEB_SEARCH_CONFIG = {
|
|
538
|
+
openai: {
|
|
539
|
+
supported: true,
|
|
540
|
+
toolName: "web_search_preview",
|
|
541
|
+
exportName: "openaiTools"
|
|
542
|
+
},
|
|
543
|
+
google: {
|
|
544
|
+
supported: true,
|
|
545
|
+
toolName: "googleSearch",
|
|
546
|
+
exportName: "googleTools"
|
|
547
|
+
},
|
|
548
|
+
xai: {
|
|
549
|
+
supported: true,
|
|
550
|
+
toolName: "xai_search"
|
|
551
|
+
},
|
|
552
|
+
anthropic: { supported: false },
|
|
553
|
+
deepseek: { supported: false }
|
|
554
|
+
};
|
|
555
|
+
/**
|
|
556
|
+
* Get web search tool configuration for a provider.
|
|
557
|
+
* Returns undefined if provider doesn't support web search.
|
|
558
|
+
*/
|
|
559
|
+
function getWebSearchConfig(provider) {
|
|
560
|
+
const config = WEB_SEARCH_CONFIG[provider];
|
|
561
|
+
return config?.supported ? config : void 0;
|
|
562
|
+
}
|
|
475
563
|
|
|
476
564
|
//#endregion
|
|
477
565
|
//#region src/engine/serialize.ts
|
|
@@ -647,6 +735,43 @@ function serializeCheckboxesField(field, value) {
|
|
|
647
735
|
return `{% checkboxes ${serializeAttrs(attrs)} %}\n${serializeOptions(field.options, value?.values ?? {})}\n{% /checkboxes %}`;
|
|
648
736
|
}
|
|
649
737
|
/**
|
|
738
|
+
* Serialize a url-field.
|
|
739
|
+
*/
|
|
740
|
+
function serializeUrlField(field, value) {
|
|
741
|
+
const attrs = {
|
|
742
|
+
id: field.id,
|
|
743
|
+
label: field.label
|
|
744
|
+
};
|
|
745
|
+
if (field.required) attrs.required = field.required;
|
|
746
|
+
if (field.priority !== DEFAULT_PRIORITY) attrs.priority = field.priority;
|
|
747
|
+
if (field.role !== AGENT_ROLE) attrs.role = field.role;
|
|
748
|
+
if (field.validate) attrs.validate = field.validate;
|
|
749
|
+
const attrStr = serializeAttrs(attrs);
|
|
750
|
+
let content = "";
|
|
751
|
+
if (value?.value) content = `\n\`\`\`value\n${value.value}\n\`\`\`\n`;
|
|
752
|
+
return `{% url-field ${attrStr} %}${content}{% /url-field %}`;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Serialize a url-list field.
|
|
756
|
+
*/
|
|
757
|
+
function serializeUrlListField(field, value) {
|
|
758
|
+
const attrs = {
|
|
759
|
+
id: field.id,
|
|
760
|
+
label: field.label
|
|
761
|
+
};
|
|
762
|
+
if (field.required) attrs.required = field.required;
|
|
763
|
+
if (field.priority !== DEFAULT_PRIORITY) attrs.priority = field.priority;
|
|
764
|
+
if (field.role !== AGENT_ROLE) attrs.role = field.role;
|
|
765
|
+
if (field.minItems !== void 0) attrs.minItems = field.minItems;
|
|
766
|
+
if (field.maxItems !== void 0) attrs.maxItems = field.maxItems;
|
|
767
|
+
if (field.uniqueItems) attrs.uniqueItems = field.uniqueItems;
|
|
768
|
+
if (field.validate) attrs.validate = field.validate;
|
|
769
|
+
const attrStr = serializeAttrs(attrs);
|
|
770
|
+
let content = "";
|
|
771
|
+
if (value?.items && value.items.length > 0) content = `\n\`\`\`value\n${value.items.join("\n")}\n\`\`\`\n`;
|
|
772
|
+
return `{% url-list ${attrStr} %}${content}{% /url-list %}`;
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
650
775
|
* Serialize a field to Markdoc format.
|
|
651
776
|
*/
|
|
652
777
|
function serializeField(field, values) {
|
|
@@ -658,6 +783,8 @@ function serializeField(field, values) {
|
|
|
658
783
|
case "single_select": return serializeSingleSelectField(field, value);
|
|
659
784
|
case "multi_select": return serializeMultiSelectField(field, value);
|
|
660
785
|
case "checkboxes": return serializeCheckboxesField(field, value);
|
|
786
|
+
case "url": return serializeUrlField(field, value);
|
|
787
|
+
case "url_list": return serializeUrlListField(field, value);
|
|
661
788
|
}
|
|
662
789
|
}
|
|
663
790
|
/**
|
|
@@ -794,6 +921,18 @@ function serializeFieldRaw(field, values) {
|
|
|
794
921
|
}
|
|
795
922
|
break;
|
|
796
923
|
}
|
|
924
|
+
case "url": {
|
|
925
|
+
const urlValue = value;
|
|
926
|
+
if (urlValue?.value) lines.push(urlValue.value);
|
|
927
|
+
else lines.push("_(empty)_");
|
|
928
|
+
break;
|
|
929
|
+
}
|
|
930
|
+
case "url_list": {
|
|
931
|
+
const urlListValue = value;
|
|
932
|
+
if (urlListValue?.items && urlListValue.items.length > 0) for (const item of urlListValue.items) lines.push(`- ${item}`);
|
|
933
|
+
else lines.push("_(empty)_");
|
|
934
|
+
break;
|
|
935
|
+
}
|
|
797
936
|
}
|
|
798
937
|
return lines.join("\n");
|
|
799
938
|
}
|
|
@@ -861,7 +1000,9 @@ function computeStructureSummary(schema) {
|
|
|
861
1000
|
string_list: 0,
|
|
862
1001
|
checkboxes: 0,
|
|
863
1002
|
single_select: 0,
|
|
864
|
-
multi_select: 0
|
|
1003
|
+
multi_select: 0,
|
|
1004
|
+
url: 0,
|
|
1005
|
+
url_list: 0
|
|
865
1006
|
};
|
|
866
1007
|
const groupsById = {};
|
|
867
1008
|
const fieldsById = {};
|
|
@@ -922,6 +1063,11 @@ function isFieldSubmitted(field, value) {
|
|
|
922
1063
|
}
|
|
923
1064
|
return false;
|
|
924
1065
|
}
|
|
1066
|
+
case "url": {
|
|
1067
|
+
const v = value;
|
|
1068
|
+
return v.value !== null && v.value.trim() !== "";
|
|
1069
|
+
}
|
|
1070
|
+
case "url_list": return value.items.length > 0;
|
|
925
1071
|
}
|
|
926
1072
|
}
|
|
927
1073
|
/**
|
|
@@ -980,18 +1126,21 @@ function computeFieldState(field, value, issueCount) {
|
|
|
980
1126
|
/**
|
|
981
1127
|
* Compute progress for a single field.
|
|
982
1128
|
*/
|
|
983
|
-
function computeFieldProgress(field, value, issues) {
|
|
1129
|
+
function computeFieldProgress(field, value, issues, skipInfo) {
|
|
984
1130
|
const issueCount = issues.filter((i) => i.ref === field.id).length;
|
|
985
1131
|
const submitted = isFieldSubmitted(field, value);
|
|
986
1132
|
const valid = issueCount === 0;
|
|
987
1133
|
const state = computeFieldState(field, value, issueCount);
|
|
1134
|
+
const skipped = skipInfo?.skipped ?? false;
|
|
988
1135
|
const progress = {
|
|
989
1136
|
kind: field.kind,
|
|
990
1137
|
required: field.required,
|
|
991
1138
|
submitted,
|
|
992
1139
|
state,
|
|
993
1140
|
valid,
|
|
994
|
-
issueCount
|
|
1141
|
+
issueCount,
|
|
1142
|
+
skipped,
|
|
1143
|
+
skipReason: skipInfo?.reason
|
|
995
1144
|
};
|
|
996
1145
|
if (field.kind === "checkboxes") progress.checkboxProgress = computeCheckboxProgress(field, value);
|
|
997
1146
|
return progress;
|
|
@@ -1002,9 +1151,10 @@ function computeFieldProgress(field, value, issues) {
|
|
|
1002
1151
|
* @param schema - The form schema
|
|
1003
1152
|
* @param values - Current field values
|
|
1004
1153
|
* @param issues - Validation issues (from inspect)
|
|
1154
|
+
* @param skips - Skip state per field (from skip_field patches)
|
|
1005
1155
|
* @returns Progress summary with field states and counts
|
|
1006
1156
|
*/
|
|
1007
|
-
function computeProgressSummary(schema, values, issues) {
|
|
1157
|
+
function computeProgressSummary(schema, values, issues, skips = {}) {
|
|
1008
1158
|
const fields = {};
|
|
1009
1159
|
const counts = {
|
|
1010
1160
|
totalFields: 0,
|
|
@@ -1014,15 +1164,22 @@ function computeProgressSummary(schema, values, issues) {
|
|
|
1014
1164
|
incompleteFields: 0,
|
|
1015
1165
|
invalidFields: 0,
|
|
1016
1166
|
emptyRequiredFields: 0,
|
|
1017
|
-
emptyOptionalFields: 0
|
|
1167
|
+
emptyOptionalFields: 0,
|
|
1168
|
+
answeredFields: 0,
|
|
1169
|
+
skippedFields: 0
|
|
1018
1170
|
};
|
|
1019
1171
|
for (const group of schema.groups) for (const field of group.children) {
|
|
1020
1172
|
const value = values[field.id];
|
|
1021
|
-
const
|
|
1173
|
+
const skipInfo = skips[field.id];
|
|
1174
|
+
const progress = computeFieldProgress(field, value, issues, skipInfo);
|
|
1022
1175
|
fields[field.id] = progress;
|
|
1023
1176
|
counts.totalFields++;
|
|
1024
1177
|
if (progress.required) counts.requiredFields++;
|
|
1025
|
-
if (progress.submitted)
|
|
1178
|
+
if (progress.submitted) {
|
|
1179
|
+
counts.submittedFields++;
|
|
1180
|
+
counts.answeredFields++;
|
|
1181
|
+
}
|
|
1182
|
+
if (progress.skipped) counts.skippedFields++;
|
|
1026
1183
|
if (progress.state === "complete") counts.completeFields++;
|
|
1027
1184
|
if (progress.state === "incomplete") counts.incompleteFields++;
|
|
1028
1185
|
if (progress.state === "invalid") counts.invalidFields++;
|
|
@@ -1050,11 +1207,23 @@ function computeFormState(progress) {
|
|
|
1050
1207
|
/**
|
|
1051
1208
|
* Determine if the form is complete (ready for submission).
|
|
1052
1209
|
*
|
|
1210
|
+
* A form is complete when:
|
|
1211
|
+
* 1. No required fields are empty
|
|
1212
|
+
* 2. No fields have validation errors
|
|
1213
|
+
* 3. No fields are in incomplete state (e.g., partial checkbox completion)
|
|
1214
|
+
* 4. All fields must be addressed (answered + skipped == total)
|
|
1215
|
+
*
|
|
1216
|
+
* Every field must be explicitly addressed - either filled with a value or
|
|
1217
|
+
* skipped with a reason. This ensures agents fully process all fields.
|
|
1218
|
+
*
|
|
1053
1219
|
* @param progress - The progress summary
|
|
1054
1220
|
* @returns True if the form is complete
|
|
1055
1221
|
*/
|
|
1056
1222
|
function isFormComplete(progress) {
|
|
1057
|
-
|
|
1223
|
+
const { counts } = progress;
|
|
1224
|
+
const baseComplete = counts.invalidFields === 0 && counts.incompleteFields === 0 && counts.emptyRequiredFields === 0;
|
|
1225
|
+
const allFieldsAccountedFor = counts.answeredFields + counts.skippedFields === counts.totalFields;
|
|
1226
|
+
return baseComplete && allFieldsAccountedFor;
|
|
1058
1227
|
}
|
|
1059
1228
|
/**
|
|
1060
1229
|
* Compute all summaries for a parsed form.
|
|
@@ -1062,11 +1231,12 @@ function isFormComplete(progress) {
|
|
|
1062
1231
|
* @param schema - The form schema
|
|
1063
1232
|
* @param values - Current field values
|
|
1064
1233
|
* @param issues - Validation issues
|
|
1234
|
+
* @param skips - Skip state per field (from skip_field patches)
|
|
1065
1235
|
* @returns All computed summaries
|
|
1066
1236
|
*/
|
|
1067
|
-
function computeAllSummaries(schema, values, issues) {
|
|
1237
|
+
function computeAllSummaries(schema, values, issues, skips = {}) {
|
|
1068
1238
|
const structureSummary = computeStructureSummary(schema);
|
|
1069
|
-
const progressSummary = computeProgressSummary(schema, values, issues);
|
|
1239
|
+
const progressSummary = computeProgressSummary(schema, values, issues, skips);
|
|
1070
1240
|
return {
|
|
1071
1241
|
structureSummary,
|
|
1072
1242
|
progressSummary,
|
|
@@ -1332,6 +1502,96 @@ function validateCheckboxesField(field, value) {
|
|
|
1332
1502
|
return issues;
|
|
1333
1503
|
}
|
|
1334
1504
|
/**
|
|
1505
|
+
* Check if a string is a valid URL.
|
|
1506
|
+
* Uses URL constructor for validation (RFC 3986 compliant).
|
|
1507
|
+
*/
|
|
1508
|
+
function isValidUrl(str) {
|
|
1509
|
+
try {
|
|
1510
|
+
const url = new URL(str);
|
|
1511
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
1512
|
+
} catch {
|
|
1513
|
+
return false;
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
/**
|
|
1517
|
+
* Validate a URL field.
|
|
1518
|
+
*/
|
|
1519
|
+
function validateUrlField(field, value) {
|
|
1520
|
+
const issues = [];
|
|
1521
|
+
const urlValue = value?.value ?? null;
|
|
1522
|
+
if (field.required && (urlValue === null || urlValue.trim() === "")) {
|
|
1523
|
+
issues.push({
|
|
1524
|
+
severity: "error",
|
|
1525
|
+
message: `Required field "${field.label}" is empty`,
|
|
1526
|
+
ref: field.id,
|
|
1527
|
+
source: "builtin"
|
|
1528
|
+
});
|
|
1529
|
+
return issues;
|
|
1530
|
+
}
|
|
1531
|
+
if (urlValue === null || urlValue === "") return issues;
|
|
1532
|
+
if (!isValidUrl(urlValue)) issues.push({
|
|
1533
|
+
severity: "error",
|
|
1534
|
+
message: `"${field.label}" is not a valid URL`,
|
|
1535
|
+
ref: field.id,
|
|
1536
|
+
source: "builtin"
|
|
1537
|
+
});
|
|
1538
|
+
return issues;
|
|
1539
|
+
}
|
|
1540
|
+
/**
|
|
1541
|
+
* Validate a URL list field.
|
|
1542
|
+
*/
|
|
1543
|
+
function validateUrlListField(field, value) {
|
|
1544
|
+
const issues = [];
|
|
1545
|
+
const items = value?.items ?? [];
|
|
1546
|
+
if (field.required && items.length === 0) {
|
|
1547
|
+
issues.push({
|
|
1548
|
+
severity: "error",
|
|
1549
|
+
message: `Required field "${field.label}" is empty`,
|
|
1550
|
+
ref: field.id,
|
|
1551
|
+
source: "builtin"
|
|
1552
|
+
});
|
|
1553
|
+
return issues;
|
|
1554
|
+
}
|
|
1555
|
+
if (items.length === 0) return issues;
|
|
1556
|
+
if (field.minItems !== void 0 && items.length < field.minItems) issues.push({
|
|
1557
|
+
severity: "error",
|
|
1558
|
+
message: `"${field.label}" must have at least ${field.minItems} items (got ${items.length})`,
|
|
1559
|
+
ref: field.id,
|
|
1560
|
+
source: "builtin"
|
|
1561
|
+
});
|
|
1562
|
+
if (field.maxItems !== void 0 && items.length > field.maxItems) issues.push({
|
|
1563
|
+
severity: "error",
|
|
1564
|
+
message: `"${field.label}" must have at most ${field.maxItems} items (got ${items.length})`,
|
|
1565
|
+
ref: field.id,
|
|
1566
|
+
source: "builtin"
|
|
1567
|
+
});
|
|
1568
|
+
for (let i = 0; i < items.length; i++) {
|
|
1569
|
+
const item = items[i];
|
|
1570
|
+
if (item !== void 0 && !isValidUrl(item)) issues.push({
|
|
1571
|
+
severity: "error",
|
|
1572
|
+
message: `Item ${i + 1} in "${field.label}" is not a valid URL`,
|
|
1573
|
+
ref: field.id,
|
|
1574
|
+
source: "builtin"
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
if (field.uniqueItems) {
|
|
1578
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1579
|
+
for (const item of items) {
|
|
1580
|
+
if (seen.has(item)) {
|
|
1581
|
+
issues.push({
|
|
1582
|
+
severity: "error",
|
|
1583
|
+
message: `Duplicate URL "${item}" in "${field.label}"`,
|
|
1584
|
+
ref: field.id,
|
|
1585
|
+
source: "builtin"
|
|
1586
|
+
});
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1589
|
+
seen.add(item);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
return issues;
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1335
1595
|
* Validate a single field.
|
|
1336
1596
|
*/
|
|
1337
1597
|
function validateField(field, values) {
|
|
@@ -1343,6 +1603,8 @@ function validateField(field, values) {
|
|
|
1343
1603
|
case "single_select": return validateSingleSelectField(field, value);
|
|
1344
1604
|
case "multi_select": return validateMultiSelectField(field, value);
|
|
1345
1605
|
case "checkboxes": return validateCheckboxesField(field, value);
|
|
1606
|
+
case "url": return validateUrlField(field, value);
|
|
1607
|
+
case "url_list": return validateUrlListField(field, value);
|
|
1346
1608
|
}
|
|
1347
1609
|
}
|
|
1348
1610
|
/**
|
|
@@ -1485,14 +1747,14 @@ function validate(form, opts) {
|
|
|
1485
1747
|
function inspect(form, options = {}) {
|
|
1486
1748
|
const validationInspectIssues = convertValidationIssues(validate(form, { skipCodeValidators: options.skipCodeValidators }).issues, form);
|
|
1487
1749
|
const structureSummary = computeStructureSummary(form.schema);
|
|
1488
|
-
const progressSummary = computeProgressSummary(form.schema, form.valuesByFieldId, validationInspectIssues);
|
|
1750
|
+
const progressSummary = computeProgressSummary(form.schema, form.valuesByFieldId, validationInspectIssues, form.skipsByFieldId);
|
|
1489
1751
|
const formState = computeFormState(progressSummary);
|
|
1490
|
-
const
|
|
1752
|
+
const issues = filterIssuesByRole(sortAndAssignPriorities(addOptionalEmptyIssues(validationInspectIssues, form, progressSummary.fields), form), form, options.targetRoles);
|
|
1491
1753
|
return {
|
|
1492
1754
|
structureSummary,
|
|
1493
1755
|
progressSummary,
|
|
1494
|
-
issues
|
|
1495
|
-
isComplete:
|
|
1756
|
+
issues,
|
|
1757
|
+
isComplete: issues.length === 0,
|
|
1496
1758
|
formState
|
|
1497
1759
|
};
|
|
1498
1760
|
}
|
|
@@ -1511,18 +1773,22 @@ function convertValidationIssues(validationIssues, form) {
|
|
|
1511
1773
|
}
|
|
1512
1774
|
/**
|
|
1513
1775
|
* Add issues for empty optional fields that don't already have issues.
|
|
1776
|
+
* Fields that have been explicitly skipped do not get optional_empty issues.
|
|
1514
1777
|
*/
|
|
1515
1778
|
function addOptionalEmptyIssues(existingIssues, form, fieldProgress) {
|
|
1516
1779
|
const issues = [...existingIssues];
|
|
1517
1780
|
const fieldsWithIssues = new Set(existingIssues.map((i) => i.ref));
|
|
1518
|
-
for (const [fieldId, progress] of Object.entries(fieldProgress))
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1781
|
+
for (const [fieldId, progress] of Object.entries(fieldProgress)) {
|
|
1782
|
+
if (progress.skipped) continue;
|
|
1783
|
+
if (progress.state === "empty" && !fieldsWithIssues.has(fieldId) && !isRequiredField(fieldId, form)) issues.push({
|
|
1784
|
+
ref: fieldId,
|
|
1785
|
+
scope: "field",
|
|
1786
|
+
reason: "optional_empty",
|
|
1787
|
+
message: "Optional field has no value",
|
|
1788
|
+
severity: "recommended",
|
|
1789
|
+
priority: 0
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1526
1792
|
return issues;
|
|
1527
1793
|
}
|
|
1528
1794
|
/**
|
|
@@ -1812,7 +2078,25 @@ function validatePatch(form, patch, index) {
|
|
|
1812
2078
|
};
|
|
1813
2079
|
break;
|
|
1814
2080
|
}
|
|
2081
|
+
case "set_url":
|
|
2082
|
+
if (field.kind !== "url") return {
|
|
2083
|
+
patchIndex: index,
|
|
2084
|
+
message: `Cannot apply set_url to ${field.kind} field "${field.id}"`
|
|
2085
|
+
};
|
|
2086
|
+
break;
|
|
2087
|
+
case "set_url_list":
|
|
2088
|
+
if (field.kind !== "url_list") return {
|
|
2089
|
+
patchIndex: index,
|
|
2090
|
+
message: `Cannot apply set_url_list to ${field.kind} field "${field.id}"`
|
|
2091
|
+
};
|
|
2092
|
+
break;
|
|
1815
2093
|
case "clear_field": break;
|
|
2094
|
+
case "skip_field":
|
|
2095
|
+
if (field.required) return {
|
|
2096
|
+
patchIndex: index,
|
|
2097
|
+
message: `Cannot skip required field "${field.id}"`
|
|
2098
|
+
};
|
|
2099
|
+
break;
|
|
1816
2100
|
}
|
|
1817
2101
|
return null;
|
|
1818
2102
|
}
|
|
@@ -1889,6 +2173,24 @@ function applySetCheckboxes(values, patch) {
|
|
|
1889
2173
|
};
|
|
1890
2174
|
}
|
|
1891
2175
|
/**
|
|
2176
|
+
* Apply a set_url patch.
|
|
2177
|
+
*/
|
|
2178
|
+
function applySetUrl(values, patch) {
|
|
2179
|
+
values[patch.fieldId] = {
|
|
2180
|
+
kind: "url",
|
|
2181
|
+
value: patch.value
|
|
2182
|
+
};
|
|
2183
|
+
}
|
|
2184
|
+
/**
|
|
2185
|
+
* Apply a set_url_list patch.
|
|
2186
|
+
*/
|
|
2187
|
+
function applySetUrlList(values, patch) {
|
|
2188
|
+
values[patch.fieldId] = {
|
|
2189
|
+
kind: "url_list",
|
|
2190
|
+
items: patch.items
|
|
2191
|
+
};
|
|
2192
|
+
}
|
|
2193
|
+
/**
|
|
1892
2194
|
* Apply a clear_field patch.
|
|
1893
2195
|
*/
|
|
1894
2196
|
function applyClearField(form, values, patch) {
|
|
@@ -1931,33 +2233,73 @@ function applyClearField(form, values, patch) {
|
|
|
1931
2233
|
values: {}
|
|
1932
2234
|
};
|
|
1933
2235
|
break;
|
|
2236
|
+
case "url":
|
|
2237
|
+
values[patch.fieldId] = {
|
|
2238
|
+
kind: "url",
|
|
2239
|
+
value: null
|
|
2240
|
+
};
|
|
2241
|
+
break;
|
|
2242
|
+
case "url_list":
|
|
2243
|
+
values[patch.fieldId] = {
|
|
2244
|
+
kind: "url_list",
|
|
2245
|
+
items: []
|
|
2246
|
+
};
|
|
2247
|
+
break;
|
|
1934
2248
|
}
|
|
1935
2249
|
}
|
|
1936
2250
|
/**
|
|
1937
|
-
* Apply a
|
|
2251
|
+
* Apply a skip_field patch.
|
|
2252
|
+
* Marks the field as skipped and clears any existing value.
|
|
1938
2253
|
*/
|
|
1939
|
-
function
|
|
2254
|
+
function applySkipField(form, values, skips, patch) {
|
|
2255
|
+
if (!findField(form, patch.fieldId)) return;
|
|
2256
|
+
skips[patch.fieldId] = {
|
|
2257
|
+
skipped: true,
|
|
2258
|
+
reason: patch.reason
|
|
2259
|
+
};
|
|
2260
|
+
delete values[patch.fieldId];
|
|
2261
|
+
}
|
|
2262
|
+
/**
|
|
2263
|
+
* Apply a single patch to the values and skips.
|
|
2264
|
+
*/
|
|
2265
|
+
function applyPatch(form, values, skips, patch) {
|
|
1940
2266
|
switch (patch.op) {
|
|
1941
2267
|
case "set_string":
|
|
1942
2268
|
applySetString(values, patch);
|
|
2269
|
+
delete skips[patch.fieldId];
|
|
1943
2270
|
break;
|
|
1944
2271
|
case "set_number":
|
|
1945
2272
|
applySetNumber(values, patch);
|
|
2273
|
+
delete skips[patch.fieldId];
|
|
1946
2274
|
break;
|
|
1947
2275
|
case "set_string_list":
|
|
1948
2276
|
applySetStringList(values, patch);
|
|
2277
|
+
delete skips[patch.fieldId];
|
|
1949
2278
|
break;
|
|
1950
2279
|
case "set_single_select":
|
|
1951
2280
|
applySetSingleSelect(values, patch);
|
|
2281
|
+
delete skips[patch.fieldId];
|
|
1952
2282
|
break;
|
|
1953
2283
|
case "set_multi_select":
|
|
1954
2284
|
applySetMultiSelect(values, patch);
|
|
2285
|
+
delete skips[patch.fieldId];
|
|
1955
2286
|
break;
|
|
1956
2287
|
case "set_checkboxes":
|
|
1957
2288
|
applySetCheckboxes(values, patch);
|
|
2289
|
+
delete skips[patch.fieldId];
|
|
2290
|
+
break;
|
|
2291
|
+
case "set_url":
|
|
2292
|
+
applySetUrl(values, patch);
|
|
2293
|
+
break;
|
|
2294
|
+
case "set_url_list":
|
|
2295
|
+
applySetUrlList(values, patch);
|
|
1958
2296
|
break;
|
|
1959
2297
|
case "clear_field":
|
|
1960
2298
|
applyClearField(form, values, patch);
|
|
2299
|
+
delete skips[patch.fieldId];
|
|
2300
|
+
break;
|
|
2301
|
+
case "skip_field":
|
|
2302
|
+
applySkipField(form, values, skips, patch);
|
|
1961
2303
|
break;
|
|
1962
2304
|
}
|
|
1963
2305
|
}
|
|
@@ -1989,7 +2331,7 @@ function convertToInspectIssues(form) {
|
|
|
1989
2331
|
*/
|
|
1990
2332
|
function applyPatches(form, patches) {
|
|
1991
2333
|
if (validatePatches(form, patches).length > 0) {
|
|
1992
|
-
const summaries$1 = computeAllSummaries(form.schema, form.valuesByFieldId, []);
|
|
2334
|
+
const summaries$1 = computeAllSummaries(form.schema, form.valuesByFieldId, [], form.skipsByFieldId);
|
|
1993
2335
|
const issues$1 = convertToInspectIssues(form);
|
|
1994
2336
|
return {
|
|
1995
2337
|
applyStatus: "rejected",
|
|
@@ -2001,10 +2343,12 @@ function applyPatches(form, patches) {
|
|
|
2001
2343
|
};
|
|
2002
2344
|
}
|
|
2003
2345
|
const newValues = { ...form.valuesByFieldId };
|
|
2004
|
-
|
|
2346
|
+
const newSkips = { ...form.skipsByFieldId };
|
|
2347
|
+
for (const patch of patches) applyPatch(form, newValues, newSkips, patch);
|
|
2005
2348
|
form.valuesByFieldId = newValues;
|
|
2349
|
+
form.skipsByFieldId = newSkips;
|
|
2006
2350
|
const issues = convertToInspectIssues(form);
|
|
2007
|
-
const summaries = computeAllSummaries(form.schema, newValues, issues);
|
|
2351
|
+
const summaries = computeAllSummaries(form.schema, newValues, issues, newSkips);
|
|
2008
2352
|
return {
|
|
2009
2353
|
applyStatus: "applied",
|
|
2010
2354
|
structureSummary: summaries.structureSummary,
|
|
@@ -2016,5 +2360,4 @@ function applyPatches(form, patches) {
|
|
|
2016
2360
|
}
|
|
2017
2361
|
|
|
2018
2362
|
//#endregion
|
|
2019
|
-
export {
|
|
2020
|
-
//# sourceMappingURL=apply-C0vjijlP.mjs.map
|
|
2363
|
+
export { OptionSchema as $, ClearFieldPatchSchema as A, HarnessConfigSchema as B, parseRolesFlag as C, StringValueSchema as Ct, CheckboxValueSchema as D, CheckboxProgressCountsSchema as E, ValidatorRefSchema as Et, FieldKindSchema as F, IssueScopeSchema as G, InspectIssueSchema as H, FieldProgressSchema as I, MultiSelectFieldSchema as J, MarkformFrontmatterSchema as K, FieldSchema as L, DocumentationTagSchema as M, ExplicitCheckboxValueSchema as N, CheckboxesFieldSchema as O, FieldGroupSchema as P, OptionIdSchema as Q, FieldValueSchema as R, getWebSearchConfig as S, StringListValueSchema as St, CheckboxModeSchema as T, ValidationIssueSchema as Tt, InspectResultSchema as U, IdSchema as V, IssueReasonSchema as W, NumberFieldSchema as X, MultiSelectValueSchema as Y, NumberValueSchema as Z, DEFAULT_PRIORITY as _, SourcePositionSchema as _t, computeAllSummaries as a, SessionTranscriptSchema as at, USER_ROLE as b, StringFieldSchema as bt, computeStructureSummary as c, SetMultiSelectPatchSchema as ct, serializeRawMarkdown as d, SetStringListPatchSchema as dt, PatchSchema as et, AGENT_ROLE as f, SetStringPatchSchema as ft, DEFAULT_PORT as g, SingleSelectValueSchema as gt, DEFAULT_MAX_TURNS as h, SingleSelectFieldSchema as ht, validate as i, SessionFinalSchema as it, DocumentationBlockSchema as j, CheckboxesValueSchema as k, isFormComplete as l, SetNumberPatchSchema as lt, DEFAULT_MAX_PATCHES_PER_TURN as m, SimpleCheckboxStateSchema as mt, getFieldsForRoles as n, ProgressStateSchema as nt, computeFormState as o, SessionTurnSchema as ot, DEFAULT_MAX_ISSUES as p, SeveritySchema as pt, MultiCheckboxStateSchema as q, inspect as r, ProgressSummarySchema as rt, computeProgressSummary as s, SetCheckboxesPatchSchema as st, applyPatches as t, ProgressCountsSchema as tt, serialize as u, SetSingleSelectPatchSchema as ut, DEFAULT_ROLE_INSTRUCTIONS as v, SourceRangeSchema as vt, ApplyResultSchema as w, StructureSummarySchema as wt, formatSuggestedLlms as x, StringListFieldSchema as xt, SUGGESTED_LLMS as y, StepResultSchema as yt, FormSchemaSchema as z };
|