markform 0.1.20 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -12
- package/dist/ai-sdk.d.mts +1 -1
- package/dist/ai-sdk.mjs +2 -2
- package/dist/{apply-DIvm1b1s.mjs → apply-C7mO7VkZ.mjs} +158 -95
- package/dist/apply-C7mO7VkZ.mjs.map +1 -0
- package/dist/bin.mjs +1 -1
- package/dist/{cli-FFMoEhFS.mjs → cli-C8F9yDsv.mjs} +102 -1225
- package/dist/cli-C8F9yDsv.mjs.map +1 -0
- package/dist/cli.mjs +1 -1
- package/dist/{coreTypes-CkxML8g2.d.mts → coreTypes-BlsJkU1w.d.mts} +28 -2
- package/dist/{coreTypes-CPKXf2dc.mjs → coreTypes-CTLr-NGd.mjs} +24 -3
- package/dist/coreTypes-CTLr-NGd.mjs.map +1 -0
- package/dist/fillRecord-DTl5lnK0.d.mts +345 -0
- package/dist/fillRecordRenderer-CruJrLkj.mjs +1256 -0
- package/dist/fillRecordRenderer-CruJrLkj.mjs.map +1 -0
- package/dist/index.d.mts +22 -342
- package/dist/index.mjs +5 -5
- package/dist/render.d.mts +74 -0
- package/dist/render.mjs +4 -0
- package/dist/{session-CK0x28RO.mjs → session-BCcltrLA.mjs} +2 -2
- package/dist/{session-CK0x28RO.mjs.map → session-BCcltrLA.mjs.map} +1 -1
- package/dist/{session-ZHBi3LVQ.mjs → session-VeSkVrck.mjs} +1 -1
- package/dist/{shared-DwdyWmvE.mjs → shared-CsdT2T7k.mjs} +1 -1
- package/dist/{shared-DwdyWmvE.mjs.map → shared-CsdT2T7k.mjs.map} +1 -1
- package/dist/{shared-BTR35aMz.mjs → shared-fb0nkzQi.mjs} +1 -1
- package/dist/{src-wR7GoftB.mjs → src-CbRnGzMK.mjs} +205 -138
- package/dist/src-CbRnGzMK.mjs.map +1 -0
- package/dist/urlFormat-lls7CsEP.mjs +71 -0
- package/dist/urlFormat-lls7CsEP.mjs.map +1 -0
- package/docs/markform-apis.md +53 -0
- package/examples/movie-research/movie-deep-research-mock-filled.form.md +320 -343
- package/examples/movie-research/movie-deep-research.form.md +273 -308
- package/examples/movie-research/movie-research-demo.form.md +27 -41
- package/examples/parallel/parallel-research.form.md +33 -29
- package/examples/parallel/parallel-research.mock.filled.form.md +88 -0
- package/examples/rejection-test/rejection-test-mock-filled.form.md +21 -16
- package/examples/rejection-test/rejection-test-mock-filled.schema.json +1 -1
- package/examples/rejection-test/rejection-test.form.md +17 -15
- package/examples/rejection-test/rejection-test.session.yaml +88 -60
- package/examples/simple/simple-mock-filled.form.md +113 -126
- package/examples/simple/simple-mock-filled.schema.json +2 -3
- package/examples/simple/simple-skipped-filled.form.md +112 -129
- package/examples/simple/simple-skipped-filled.report.md +8 -8
- package/examples/simple/simple-skipped-filled.schema.json +2 -3
- package/examples/simple/simple-tags-syntax.form.md +32 -0
- package/examples/simple/simple-with-skips.session.yaml +663 -627
- package/examples/simple/simple.form.md +97 -113
- package/examples/simple/simple.schema.json +2 -3
- package/examples/simple/simple.session.yaml +663 -627
- package/examples/startup-deep-research/startup-deep-research.form.md +191 -235
- package/examples/startup-research/startup-research-mock-filled.form.md +128 -147
- package/examples/startup-research/startup-research.form.md +90 -129
- package/examples/twitter-thread/twitter-thread.form.md +373 -0
- package/package.json +5 -1
- package/dist/apply-DIvm1b1s.mjs.map +0 -1
- package/dist/cli-FFMoEhFS.mjs.map +0 -1
- package/dist/coreTypes-CPKXf2dc.mjs.map +0 -1
- package/dist/src-wR7GoftB.mjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { A as MarkformSectionInputSchema, R as PatchSchema, mt as StructureSummarySchema, z as ProgressCountsSchema } from "./coreTypes-CTLr-NGd.mjs";
|
|
3
|
+
import { B as DEFAULT_ROLES, C as getNumberAttr, D as isTagNode, E as getValidateAttr, F as DEFAULT_MAX_TURNS, L as DEFAULT_PRIORITY, M as DEFAULT_MAX_PARALLEL_AGENTS, N as DEFAULT_MAX_PATCHES_PER_TURN, O as parseOptionText, P as DEFAULT_MAX_STEPS_PER_TURN, R as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, S as getBooleanAttr, T as getStringAttr, V as DEFAULT_ROLE_INSTRUCTIONS, Z as transformHarnessConfigToTs, _ as tryParseSentinelResponse, at as MarkformConfigError, b as extractOptionItems, bt as wrapApiError, c as computeProgressSummary, ct as MarkformParseError, d as serializeForm, h as preprocessCommentSyntax, i as inspect, j as DEFAULT_MAX_ISSUES_PER_TURN, k as AGENT_ROLE, l as computeStructureSummary, m as detectSyntaxStyle, r as getFieldsForRoles, t as applyPatches, tt as getWebSearchConfig, v as CHECKBOX_MARKERS, w as getStringArrayAttr, x as extractTableContent, y as extractFenceValue, z as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN } from "./apply-C7mO7VkZ.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import Markdoc from "@markdoc/markdoc";
|
|
6
6
|
import YAML from "yaml";
|
|
@@ -1214,58 +1214,42 @@ const VALID_FORM_TAGS = new Set([
|
|
|
1214
1214
|
"documentation"
|
|
1215
1215
|
]);
|
|
1216
1216
|
/**
|
|
1217
|
-
*
|
|
1218
|
-
* YAML keys must be snake_case; they are mapped to camelCase internally.
|
|
1219
|
-
* Unrecognized keys produce a parse error.
|
|
1217
|
+
* Format Zod validation errors for user-friendly display.
|
|
1220
1218
|
*/
|
|
1221
|
-
function
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
max_turns: "maxTurns",
|
|
1227
|
-
max_patches_per_turn: "maxPatchesPerTurn",
|
|
1228
|
-
max_issues_per_turn: "maxIssuesPerTurn",
|
|
1229
|
-
max_parallel_agents: "maxParallelAgents"
|
|
1230
|
-
};
|
|
1231
|
-
for (const [key, value] of Object.entries(config)) {
|
|
1232
|
-
const camelKey = keyMap[key];
|
|
1233
|
-
if (!camelKey) throw new MarkformParseError(`Unknown harness config key '${key}'. Valid keys: ${Object.keys(keyMap).join(", ")}`);
|
|
1234
|
-
if (typeof value !== "number") throw new MarkformParseError(`Harness config key '${key}' must be a number, got ${typeof value}`);
|
|
1235
|
-
result[camelKey] = value;
|
|
1236
|
-
}
|
|
1237
|
-
return Object.keys(result).length > 0 ? result : void 0;
|
|
1219
|
+
function formatZodError(error) {
|
|
1220
|
+
return error.issues.map((issue) => {
|
|
1221
|
+
const path = issue.path.map(String).join(".");
|
|
1222
|
+
return path ? `${path}: ${issue.message}` : issue.message;
|
|
1223
|
+
}).join("; ");
|
|
1238
1224
|
}
|
|
1239
1225
|
/**
|
|
1240
1226
|
* Extract YAML frontmatter from Markdoc AST.
|
|
1241
1227
|
* Uses Markdoc's native frontmatter extraction and parses the YAML.
|
|
1228
|
+
* Validates the markform section using Zod schema.
|
|
1242
1229
|
*/
|
|
1243
1230
|
function extractFrontmatter(ast) {
|
|
1244
1231
|
const rawFrontmatter = ast.attributes.frontmatter;
|
|
1245
1232
|
if (!rawFrontmatter) return { frontmatter: {} };
|
|
1246
1233
|
try {
|
|
1247
1234
|
const frontmatter = YAML.parse(rawFrontmatter) ?? {};
|
|
1248
|
-
const
|
|
1249
|
-
if (!
|
|
1250
|
-
const
|
|
1251
|
-
|
|
1252
|
-
const
|
|
1253
|
-
|
|
1254
|
-
const parsed = RunModeSchema.safeParse(rawRunMode);
|
|
1255
|
-
if (!parsed.success) throw new MarkformParseError(`Invalid run_mode: '${typeof rawRunMode === "string" ? rawRunMode : JSON.stringify(rawRunMode)}'. Must be one of: interactive, fill, research`);
|
|
1256
|
-
runMode = parsed.data;
|
|
1257
|
-
}
|
|
1258
|
-
const description = typeof markformSection.description === "string" ? markformSection.description : void 0;
|
|
1235
|
+
const rawMarkformSection = frontmatter.markform;
|
|
1236
|
+
if (!rawMarkformSection) return { frontmatter };
|
|
1237
|
+
const validationResult = MarkformSectionInputSchema.safeParse(rawMarkformSection);
|
|
1238
|
+
if (!validationResult.success) throw new MarkformParseError(`Invalid markform frontmatter: ${formatZodError(validationResult.error)}`);
|
|
1239
|
+
const markformSection = validationResult.data;
|
|
1240
|
+
const harnessConfig = markformSection.harness && Object.keys(markformSection.harness).length > 0 ? transformHarnessConfigToTs(markformSection.harness) : void 0;
|
|
1259
1241
|
return {
|
|
1260
1242
|
frontmatter,
|
|
1261
1243
|
metadata: {
|
|
1262
1244
|
markformVersion: markformSection.spec ?? "MF/0.1",
|
|
1263
|
-
|
|
1264
|
-
|
|
1245
|
+
...markformSection.title && { title: markformSection.title },
|
|
1246
|
+
...markformSection.description && { description: markformSection.description },
|
|
1247
|
+
roles: markformSection.roles ?? frontmatter.roles ?? [...DEFAULT_ROLES],
|
|
1248
|
+
roleInstructions: markformSection.role_instructions ?? frontmatter.role_instructions ?? DEFAULT_ROLE_INSTRUCTIONS,
|
|
1265
1249
|
...harnessConfig && { harnessConfig },
|
|
1266
|
-
...
|
|
1250
|
+
...markformSection.run_mode && { runMode: markformSection.run_mode }
|
|
1267
1251
|
},
|
|
1268
|
-
description
|
|
1252
|
+
description: markformSection.description
|
|
1269
1253
|
};
|
|
1270
1254
|
} catch (error) {
|
|
1271
1255
|
if (error instanceof MarkformParseError) throw error;
|
|
@@ -3285,10 +3269,11 @@ function generateSessionId() {
|
|
|
3285
3269
|
//#endregion
|
|
3286
3270
|
//#region src/harness/fillRecordCollector.ts
|
|
3287
3271
|
/**
|
|
3288
|
-
*
|
|
3272
|
+
* Collector for FillRecord data from async form fill operations.
|
|
3289
3273
|
*
|
|
3290
|
-
* Uses an append-only event log pattern
|
|
3291
|
-
* Events are aggregated when
|
|
3274
|
+
* Uses an append-only event log pattern that safely handles interleaved
|
|
3275
|
+
* async callbacks from parallel execution. Events are aggregated when
|
|
3276
|
+
* getRecord() is called.
|
|
3292
3277
|
*/
|
|
3293
3278
|
var FillRecordCollector = class {
|
|
3294
3279
|
startedAt;
|
|
@@ -3331,7 +3316,8 @@ var FillRecordCollector = class {
|
|
|
3331
3316
|
turnNumber: progress.turnNumber,
|
|
3332
3317
|
patchesApplied: progress.patchesApplied,
|
|
3333
3318
|
patchesRejected: progress.rejectedPatches?.length ?? 0,
|
|
3334
|
-
issuesAddressed: progress.issuesShown
|
|
3319
|
+
issuesAddressed: progress.issuesShown,
|
|
3320
|
+
executionId: progress.executionId
|
|
3335
3321
|
});
|
|
3336
3322
|
}
|
|
3337
3323
|
onLlmCallStart(call) {
|
|
@@ -3439,93 +3425,120 @@ var FillRecordCollector = class {
|
|
|
3439
3425
|
};
|
|
3440
3426
|
}
|
|
3441
3427
|
buildTimeline() {
|
|
3428
|
+
const turnKey = (execId, turnNum) => `${execId}:${turnNum}`;
|
|
3429
|
+
const fillStartMs = new Date(this.startedAt).getTime();
|
|
3442
3430
|
const turns = /* @__PURE__ */ new Map();
|
|
3443
3431
|
const turnStartEvents = /* @__PURE__ */ new Map();
|
|
3444
3432
|
const turnToolCalls = /* @__PURE__ */ new Map();
|
|
3445
3433
|
const turnTokens = /* @__PURE__ */ new Map();
|
|
3446
3434
|
for (const event of this.events) if (event.type === "turn_start") {
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3435
|
+
const key = turnKey(event.executionId, event.turnNumber);
|
|
3436
|
+
turnStartEvents.set(key, event);
|
|
3437
|
+
turnToolCalls.set(key, []);
|
|
3438
|
+
turnTokens.set(key, {
|
|
3450
3439
|
input: 0,
|
|
3451
3440
|
output: 0
|
|
3452
3441
|
});
|
|
3453
3442
|
}
|
|
3454
3443
|
const activeToolsByTurn = /* @__PURE__ */ new Map();
|
|
3455
|
-
|
|
3444
|
+
const currentTurnKeyByExecutionId = /* @__PURE__ */ new Map();
|
|
3456
3445
|
for (const event of this.events) if (event.type === "turn_start") {
|
|
3457
|
-
|
|
3458
|
-
|
|
3446
|
+
const key = turnKey(event.executionId, event.turnNumber);
|
|
3447
|
+
currentTurnKeyByExecutionId.set(event.executionId, key);
|
|
3448
|
+
activeToolsByTurn.set(key, /* @__PURE__ */ new Map());
|
|
3459
3449
|
} else if (event.type === "tool_start") {
|
|
3460
|
-
const
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3450
|
+
const activeTurnKey = currentTurnKeyByExecutionId.get(event.executionId);
|
|
3451
|
+
if (activeTurnKey) {
|
|
3452
|
+
const activeTools = activeToolsByTurn.get(activeTurnKey);
|
|
3453
|
+
if (activeTools) {
|
|
3454
|
+
const toolKey = `${event.executionId}:${event.name}`;
|
|
3455
|
+
activeTools.set(toolKey, {
|
|
3456
|
+
start: event,
|
|
3457
|
+
turnKey: activeTurnKey
|
|
3458
|
+
});
|
|
3459
|
+
}
|
|
3468
3460
|
}
|
|
3469
3461
|
} else if (event.type === "tool_end") {
|
|
3470
|
-
const
|
|
3471
|
-
let
|
|
3472
|
-
for (const [
|
|
3473
|
-
|
|
3462
|
+
const toolKey = `${event.executionId}:${event.name}`;
|
|
3463
|
+
let foundTurnKey;
|
|
3464
|
+
for (const [tk, activeTools] of activeToolsByTurn) if (activeTools.has(toolKey)) {
|
|
3465
|
+
foundTurnKey = tk;
|
|
3474
3466
|
break;
|
|
3475
3467
|
}
|
|
3476
|
-
if (
|
|
3477
|
-
const activeTools = activeToolsByTurn.get(
|
|
3478
|
-
const startInfo = activeTools.get(
|
|
3468
|
+
if (foundTurnKey !== void 0) {
|
|
3469
|
+
const activeTools = activeToolsByTurn.get(foundTurnKey);
|
|
3470
|
+
const startInfo = activeTools.get(toolKey);
|
|
3479
3471
|
if (startInfo) {
|
|
3480
3472
|
const toolCall = {
|
|
3481
3473
|
tool: event.name,
|
|
3482
3474
|
startedAt: startInfo.start.timestamp,
|
|
3483
3475
|
completedAt: event.timestamp,
|
|
3476
|
+
startMs: new Date(startInfo.start.timestamp).getTime() - fillStartMs,
|
|
3484
3477
|
durationMs: event.durationMs,
|
|
3485
3478
|
success: !event.error,
|
|
3486
3479
|
input: this.normalizeInput(startInfo.start.input),
|
|
3487
3480
|
result: event.error ? { error: event.error } : this.extractResultCount(event.output)
|
|
3488
3481
|
};
|
|
3489
|
-
turnToolCalls.get(
|
|
3490
|
-
activeTools.delete(
|
|
3482
|
+
turnToolCalls.get(foundTurnKey)?.push(toolCall);
|
|
3483
|
+
activeTools.delete(toolKey);
|
|
3491
3484
|
}
|
|
3492
3485
|
}
|
|
3493
3486
|
} else if (event.type === "llm_call_end") {
|
|
3494
|
-
const
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
tokens
|
|
3498
|
-
|
|
3487
|
+
const tk = currentTurnKeyByExecutionId.get(event.executionId);
|
|
3488
|
+
if (tk) {
|
|
3489
|
+
const tokens = turnTokens.get(tk);
|
|
3490
|
+
if (tokens) {
|
|
3491
|
+
tokens.input += event.inputTokens;
|
|
3492
|
+
tokens.output += event.outputTokens;
|
|
3493
|
+
}
|
|
3499
3494
|
}
|
|
3500
3495
|
}
|
|
3496
|
+
const turnCompleteByKey = /* @__PURE__ */ new Map();
|
|
3501
3497
|
for (const event of this.events) if (event.type === "turn_complete") {
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3498
|
+
if (event.executionId) {
|
|
3499
|
+
const key = turnKey(event.executionId, event.turnNumber);
|
|
3500
|
+
turnCompleteByKey.set(key, event);
|
|
3501
|
+
} else for (const [key, startEvent] of turnStartEvents) if (startEvent.turnNumber === event.turnNumber && !turnCompleteByKey.has(key)) {
|
|
3502
|
+
turnCompleteByKey.set(key, event);
|
|
3503
|
+
break;
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
for (const [key, startEvent] of turnStartEvents) {
|
|
3507
|
+
const completeEvent = turnCompleteByKey.get(key);
|
|
3508
|
+
if (completeEvent) {
|
|
3509
|
+
const tokens = turnTokens.get(key) ?? {
|
|
3505
3510
|
input: 0,
|
|
3506
3511
|
output: 0
|
|
3507
3512
|
};
|
|
3508
|
-
const toolCalls = turnToolCalls.get(
|
|
3513
|
+
const toolCalls = turnToolCalls.get(key) ?? [];
|
|
3514
|
+
const turnStartMs = new Date(startEvent.timestamp).getTime();
|
|
3509
3515
|
const entry = {
|
|
3510
|
-
turnNumber:
|
|
3516
|
+
turnNumber: startEvent.turnNumber,
|
|
3511
3517
|
order: startEvent.order,
|
|
3512
3518
|
executionId: startEvent.executionId,
|
|
3513
3519
|
startedAt: startEvent.timestamp,
|
|
3514
|
-
completedAt:
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3520
|
+
completedAt: completeEvent.timestamp,
|
|
3521
|
+
startMs: turnStartMs - fillStartMs,
|
|
3522
|
+
durationMs: new Date(completeEvent.timestamp).getTime() - turnStartMs,
|
|
3523
|
+
issuesAddressed: completeEvent.issuesAddressed,
|
|
3524
|
+
patchesApplied: completeEvent.patchesApplied,
|
|
3525
|
+
patchesRejected: completeEvent.patchesRejected,
|
|
3519
3526
|
tokens,
|
|
3520
3527
|
toolCalls
|
|
3521
3528
|
};
|
|
3522
|
-
turns.set(
|
|
3529
|
+
turns.set(key, entry);
|
|
3523
3530
|
}
|
|
3524
3531
|
}
|
|
3525
|
-
return Array.from(turns.values()).sort((a, b) => a.
|
|
3532
|
+
return Array.from(turns.values()).sort((a, b) => new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime());
|
|
3526
3533
|
}
|
|
3527
|
-
|
|
3528
|
-
|
|
3534
|
+
findTurnKeyForExecutionId(executionId, turnStartEvents) {
|
|
3535
|
+
let latestKey;
|
|
3536
|
+
let latestTime = "";
|
|
3537
|
+
for (const [key, event] of turnStartEvents) if (event.executionId === executionId && event.timestamp > latestTime) {
|
|
3538
|
+
latestKey = key;
|
|
3539
|
+
latestTime = event.timestamp;
|
|
3540
|
+
}
|
|
3541
|
+
return latestKey;
|
|
3529
3542
|
}
|
|
3530
3543
|
normalizeInput(input) {
|
|
3531
3544
|
if (input && typeof input === "object" && !Array.isArray(input)) return input;
|
|
@@ -9120,6 +9133,8 @@ var LiveAgent = class {
|
|
|
9120
9133
|
webSearchTools = null;
|
|
9121
9134
|
additionalTools;
|
|
9122
9135
|
callbacks;
|
|
9136
|
+
executionId;
|
|
9137
|
+
toolChoice;
|
|
9123
9138
|
constructor(config) {
|
|
9124
9139
|
this.model = config.model;
|
|
9125
9140
|
this.maxStepsPerTurn = config.maxStepsPerTurn ?? DEFAULT_MAX_STEPS_PER_TURN;
|
|
@@ -9129,6 +9144,8 @@ var LiveAgent = class {
|
|
|
9129
9144
|
this.enableWebSearch = config.enableWebSearch;
|
|
9130
9145
|
this.additionalTools = config.additionalTools ?? {};
|
|
9131
9146
|
this.callbacks = config.callbacks;
|
|
9147
|
+
this.executionId = config.executionId ?? "0-serial";
|
|
9148
|
+
this.toolChoice = config.toolChoice ?? "required";
|
|
9132
9149
|
if (this.enableWebSearch && this.provider) this.webSearchTools = loadWebSearchTools(this.provider);
|
|
9133
9150
|
}
|
|
9134
9151
|
/**
|
|
@@ -9168,32 +9185,37 @@ var LiveAgent = class {
|
|
|
9168
9185
|
...this.webSearchTools,
|
|
9169
9186
|
...this.additionalTools
|
|
9170
9187
|
};
|
|
9171
|
-
const tools = wrapToolsWithCallbacks(rawTools, this.callbacks, this.provider);
|
|
9188
|
+
const tools = wrapToolsWithCallbacks(rawTools, this.callbacks, this.provider, this.executionId);
|
|
9172
9189
|
const modelId = this.model.modelId ?? "unknown";
|
|
9173
9190
|
if (this.callbacks?.onLlmCallStart) try {
|
|
9174
9191
|
this.callbacks.onLlmCallStart({
|
|
9175
9192
|
model: modelId,
|
|
9176
|
-
executionId:
|
|
9193
|
+
executionId: this.executionId
|
|
9177
9194
|
});
|
|
9178
9195
|
} catch {}
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9196
|
+
let result;
|
|
9197
|
+
try {
|
|
9198
|
+
result = await generateText({
|
|
9199
|
+
model: this.model,
|
|
9200
|
+
system: systemPrompt,
|
|
9201
|
+
prompt: contextPrompt,
|
|
9202
|
+
tools,
|
|
9203
|
+
toolChoice: this.toolChoice,
|
|
9204
|
+
stopWhen: stepCountIs(this.maxStepsPerTurn)
|
|
9205
|
+
});
|
|
9206
|
+
} catch (error) {
|
|
9207
|
+
throw wrapApiError(error, this.provider ?? "unknown", modelId);
|
|
9208
|
+
}
|
|
9186
9209
|
if (this.callbacks?.onLlmCallEnd) try {
|
|
9187
9210
|
this.callbacks.onLlmCallEnd({
|
|
9188
9211
|
model: modelId,
|
|
9189
9212
|
inputTokens: result.usage?.inputTokens ?? 0,
|
|
9190
9213
|
outputTokens: result.usage?.outputTokens ?? 0,
|
|
9191
|
-
executionId:
|
|
9214
|
+
executionId: this.executionId
|
|
9192
9215
|
});
|
|
9193
9216
|
} catch {}
|
|
9194
9217
|
const patches = [];
|
|
9195
9218
|
const toolCallCounts = /* @__PURE__ */ new Map();
|
|
9196
|
-
const executionId = "0-serial";
|
|
9197
9219
|
for (const step of result.steps) for (const toolCall of step.toolCalls) {
|
|
9198
9220
|
const count = toolCallCounts.get(toolCall.toolName) ?? 0;
|
|
9199
9221
|
toolCallCounts.set(toolCall.toolName, count + 1);
|
|
@@ -9204,7 +9226,7 @@ var LiveAgent = class {
|
|
|
9204
9226
|
this.callbacks.onToolStart({
|
|
9205
9227
|
name: FILL_FORM_TOOL_NAME,
|
|
9206
9228
|
input,
|
|
9207
|
-
executionId
|
|
9229
|
+
executionId: this.executionId
|
|
9208
9230
|
});
|
|
9209
9231
|
} catch {}
|
|
9210
9232
|
patches.push(...input.patches);
|
|
@@ -9213,7 +9235,7 @@ var LiveAgent = class {
|
|
|
9213
9235
|
name: FILL_FORM_TOOL_NAME,
|
|
9214
9236
|
output: { patchCount: input.patches.length },
|
|
9215
9237
|
durationMs: Date.now() - startTime,
|
|
9216
|
-
executionId,
|
|
9238
|
+
executionId: this.executionId,
|
|
9217
9239
|
error: void 0
|
|
9218
9240
|
});
|
|
9219
9241
|
} catch {}
|
|
@@ -9458,12 +9480,12 @@ function findField(form, fieldId) {
|
|
|
9458
9480
|
* Only wraps tools that have an execute function.
|
|
9459
9481
|
* Declarative tools (schema only) are passed through unchanged.
|
|
9460
9482
|
*/
|
|
9461
|
-
function wrapToolsWithCallbacks(tools, callbacks, provider) {
|
|
9483
|
+
function wrapToolsWithCallbacks(tools, callbacks, provider, executionId = "0-serial") {
|
|
9462
9484
|
if (!callbacks?.onToolStart && !callbacks?.onToolEnd && !callbacks?.onWebSearch) return tools;
|
|
9463
9485
|
const wrapped = {};
|
|
9464
9486
|
for (const [name, tool] of Object.entries(tools)) {
|
|
9465
9487
|
const execute = tool.execute;
|
|
9466
|
-
if (typeof execute === "function") wrapped[name] = wrapTool(name, tool, execute, callbacks, provider);
|
|
9488
|
+
if (typeof execute === "function") wrapped[name] = wrapTool(name, tool, execute, callbacks, provider, executionId);
|
|
9467
9489
|
else wrapped[name] = tool;
|
|
9468
9490
|
}
|
|
9469
9491
|
return wrapped;
|
|
@@ -9471,12 +9493,11 @@ function wrapToolsWithCallbacks(tools, callbacks, provider) {
|
|
|
9471
9493
|
/**
|
|
9472
9494
|
* Wrap a single tool with callbacks.
|
|
9473
9495
|
*/
|
|
9474
|
-
function wrapTool(name, tool, originalExecute, callbacks, provider) {
|
|
9496
|
+
function wrapTool(name, tool, originalExecute, callbacks, provider, executionId) {
|
|
9475
9497
|
return {
|
|
9476
9498
|
...tool,
|
|
9477
9499
|
execute: async (input) => {
|
|
9478
9500
|
const startTime = Date.now();
|
|
9479
|
-
const executionId = "0-serial";
|
|
9480
9501
|
if (callbacks.onToolStart) try {
|
|
9481
9502
|
callbacks.onToolStart({
|
|
9482
9503
|
name,
|
|
@@ -9853,7 +9874,7 @@ var ParallelHarness = class {
|
|
|
9853
9874
|
this.config.onBatchStart?.(batch.batchId);
|
|
9854
9875
|
const batchIssues = inspect(this.form).issues;
|
|
9855
9876
|
const maxConcurrent = this.config.maxParallelAgents ?? DEFAULT_MAX_PARALLEL_AGENTS;
|
|
9856
|
-
const
|
|
9877
|
+
const agentFactories = [];
|
|
9857
9878
|
const itemFieldIds = /* @__PURE__ */ new Map();
|
|
9858
9879
|
for (let i = 0; i < batchItems.length; i++) {
|
|
9859
9880
|
const item = batchItems[i];
|
|
@@ -9861,7 +9882,7 @@ var ParallelHarness = class {
|
|
|
9861
9882
|
const targetFieldIds = getFieldIdsForItem(this.form, item);
|
|
9862
9883
|
itemFieldIds.set(i, targetFieldIds);
|
|
9863
9884
|
if (scopedIssues.length === 0) {
|
|
9864
|
-
|
|
9885
|
+
agentFactories.push(() => Promise.resolve({ patches: [] }));
|
|
9865
9886
|
continue;
|
|
9866
9887
|
}
|
|
9867
9888
|
const request = {
|
|
@@ -9871,9 +9892,9 @@ var ParallelHarness = class {
|
|
|
9871
9892
|
issues: scopedIssues
|
|
9872
9893
|
};
|
|
9873
9894
|
const agent = this.config.agentFactory ? this.config.agentFactory(request) : primaryAgent;
|
|
9874
|
-
|
|
9895
|
+
agentFactories.push(() => agent.fillFormTool(scopedIssues, this.form, maxPatches));
|
|
9875
9896
|
}
|
|
9876
|
-
const results = await runWithConcurrency(
|
|
9897
|
+
const results = await runWithConcurrency(agentFactories, maxConcurrent);
|
|
9877
9898
|
const allPatches = [];
|
|
9878
9899
|
for (const result of results) if (result.status === "fulfilled") allPatches.push(...result.value.patches);
|
|
9879
9900
|
else errors.push(`Parallel agent error: ${result.reason}`);
|
|
@@ -9912,20 +9933,25 @@ var ParallelHarness = class {
|
|
|
9912
9933
|
}
|
|
9913
9934
|
};
|
|
9914
9935
|
/**
|
|
9915
|
-
* Run
|
|
9936
|
+
* Run promise factories with a concurrency limit.
|
|
9937
|
+
* Takes an array of functions that create promises (factories), not already-started promises.
|
|
9938
|
+
* This ensures concurrency limiting actually works - promises are started lazily.
|
|
9916
9939
|
* Returns results in the same order as input.
|
|
9917
9940
|
*/
|
|
9918
|
-
async function runWithConcurrency(
|
|
9919
|
-
if (
|
|
9920
|
-
|
|
9941
|
+
async function runWithConcurrency(factories, maxConcurrent) {
|
|
9942
|
+
if (factories.length === 0) return [];
|
|
9943
|
+
if (maxConcurrent >= factories.length) return Promise.allSettled(factories.map(async (f) => f()));
|
|
9944
|
+
const results = new Array(factories.length);
|
|
9921
9945
|
let nextIndex = 0;
|
|
9922
9946
|
async function runNext() {
|
|
9923
|
-
while (nextIndex <
|
|
9947
|
+
while (nextIndex < factories.length) {
|
|
9924
9948
|
const idx = nextIndex++;
|
|
9949
|
+
const factory = factories[idx];
|
|
9950
|
+
if (!factory) continue;
|
|
9925
9951
|
try {
|
|
9926
9952
|
results[idx] = {
|
|
9927
9953
|
status: "fulfilled",
|
|
9928
|
-
value: await
|
|
9954
|
+
value: await factory()
|
|
9929
9955
|
};
|
|
9930
9956
|
} catch (reason) {
|
|
9931
9957
|
results[idx] = {
|
|
@@ -9935,7 +9961,7 @@ async function runWithConcurrency(promises, maxConcurrent) {
|
|
|
9935
9961
|
}
|
|
9936
9962
|
}
|
|
9937
9963
|
}
|
|
9938
|
-
const workers = Array.from({ length: Math.min(maxConcurrent,
|
|
9964
|
+
const workers = Array.from({ length: Math.min(maxConcurrent, factories.length) }, () => runNext());
|
|
9939
9965
|
await Promise.all(workers);
|
|
9940
9966
|
return results;
|
|
9941
9967
|
}
|
|
@@ -9949,6 +9975,43 @@ function createParallelHarness(form, config) {
|
|
|
9949
9975
|
//#endregion
|
|
9950
9976
|
//#region src/harness/programmaticFill.ts
|
|
9951
9977
|
/**
|
|
9978
|
+
* Execution ID format for tracking parallel and serial execution threads.
|
|
9979
|
+
*
|
|
9980
|
+
* Format: `eid:{type}:o{order}[:{batchId}:i{index}]`
|
|
9981
|
+
*
|
|
9982
|
+
* Components:
|
|
9983
|
+
* - `eid:` - Prefix identifying this as an execution ID
|
|
9984
|
+
* - `{type}` - Either `serial` or `batch`
|
|
9985
|
+
* - `o{order}` - Order level (e.g., `o0`, `o10`)
|
|
9986
|
+
* - For batch only: `:{batchId}:i{index}` - Batch name and item index
|
|
9987
|
+
*
|
|
9988
|
+
* Examples:
|
|
9989
|
+
* - `eid:serial:o0` - Serial execution at order level 0
|
|
9990
|
+
* - `eid:batch:o0:research:i0` - First item in "research" batch at order 0
|
|
9991
|
+
* - `eid:batch:o0:research:i3` - Fourth item in "research" batch at order 0
|
|
9992
|
+
* - `eid:serial:o10` - Serial execution at order level 10
|
|
9993
|
+
*
|
|
9994
|
+
* Design principles:
|
|
9995
|
+
* - Self-identifying: Clear `eid:` prefix
|
|
9996
|
+
* - Structured: Type comes first for easy filtering
|
|
9997
|
+
* - Explicit: Each component has a prefix (`o` for order, `i` for index)
|
|
9998
|
+
* - Parseable: Can be split on `:` to extract components
|
|
9999
|
+
*/
|
|
10000
|
+
/** Prefix for all execution IDs */
|
|
10001
|
+
const EXECUTION_ID_PREFIX = "eid";
|
|
10002
|
+
/**
|
|
10003
|
+
* Create an execution ID for serial execution at an order level.
|
|
10004
|
+
*/
|
|
10005
|
+
function serialExecutionId(order) {
|
|
10006
|
+
return `${EXECUTION_ID_PREFIX}:serial:o${order}`;
|
|
10007
|
+
}
|
|
10008
|
+
/**
|
|
10009
|
+
* Create an execution ID for a batch item at an order level.
|
|
10010
|
+
*/
|
|
10011
|
+
function batchExecutionId(order, batchId, itemIndex) {
|
|
10012
|
+
return `${EXECUTION_ID_PREFIX}:batch:o${order}:${batchId}:i${itemIndex}`;
|
|
10013
|
+
}
|
|
10014
|
+
/**
|
|
9952
10015
|
* Get current progress counts for a form.
|
|
9953
10016
|
* Runs inspect to get issues, then computes progress summary.
|
|
9954
10017
|
*/
|
|
@@ -10250,7 +10313,8 @@ async function fillForm(options) {
|
|
|
10250
10313
|
enableWebSearch: options.enableWebSearch,
|
|
10251
10314
|
additionalTools: options.additionalTools,
|
|
10252
10315
|
callbacks: mergedCallbacks,
|
|
10253
|
-
maxStepsPerTurn: options.maxStepsPerTurn
|
|
10316
|
+
maxStepsPerTurn: options.maxStepsPerTurn,
|
|
10317
|
+
toolChoice: options.toolChoice
|
|
10254
10318
|
});
|
|
10255
10319
|
let turnCount = startingTurnNumber;
|
|
10256
10320
|
let turnsThisCall = 0;
|
|
@@ -10361,7 +10425,8 @@ async function fillForm(options) {
|
|
|
10361
10425
|
stats,
|
|
10362
10426
|
issues: turnIssues,
|
|
10363
10427
|
patches,
|
|
10364
|
-
rejectedPatches: stepResult.rejectedPatches ?? []
|
|
10428
|
+
rejectedPatches: stepResult.rejectedPatches ?? [],
|
|
10429
|
+
executionId: "0-serial"
|
|
10365
10430
|
});
|
|
10366
10431
|
} catch {}
|
|
10367
10432
|
if (!stepResult.isComplete && !harness.hasReachedMaxTurns()) stepResult = harness.step();
|
|
@@ -10402,16 +10467,20 @@ async function fillFormParallel(form, model, provider, options, initialPatches,
|
|
|
10402
10467
|
const targetRoles = options.targetRoles ?? [AGENT_ROLE];
|
|
10403
10468
|
let totalPatches = initialPatches;
|
|
10404
10469
|
let turnCount = startingTurnNumber;
|
|
10405
|
-
const
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
|
|
10409
|
-
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
|
|
10470
|
+
const createAgentForExecution = (executionId) => {
|
|
10471
|
+
return options._testAgent ?? createLiveAgent({
|
|
10472
|
+
model,
|
|
10473
|
+
systemPromptAddition: options.systemPromptAddition,
|
|
10474
|
+
targetRole: targetRoles[0] ?? AGENT_ROLE,
|
|
10475
|
+
provider,
|
|
10476
|
+
enableWebSearch: options.enableWebSearch,
|
|
10477
|
+
additionalTools: options.additionalTools,
|
|
10478
|
+
callbacks: mergedCallbacks,
|
|
10479
|
+
maxStepsPerTurn: options.maxStepsPerTurn,
|
|
10480
|
+
executionId,
|
|
10481
|
+
toolChoice: options.toolChoice
|
|
10482
|
+
});
|
|
10483
|
+
};
|
|
10415
10484
|
for (const order of plan.orderLevels) {
|
|
10416
10485
|
if (options.signal?.aborted) {
|
|
10417
10486
|
let record;
|
|
@@ -10441,7 +10510,8 @@ async function fillFormParallel(form, model, provider, options, initialPatches,
|
|
|
10441
10510
|
} catch {}
|
|
10442
10511
|
const serialItems = plan.looseSerial.filter((i) => i.order === order);
|
|
10443
10512
|
if (serialItems.length > 0) {
|
|
10444
|
-
const
|
|
10513
|
+
const serialExecId = serialExecutionId(order);
|
|
10514
|
+
const result = await runMultiTurnForItems(form, createAgentForExecution(serialExecId), serialItems, targetRoles, maxPatchesPerTurn, maxIssuesPerTurn, maxTurnsTotal, turnCount, options, order, serialExecId, mergedCallbacks);
|
|
10445
10515
|
totalPatches += result.patchesApplied;
|
|
10446
10516
|
turnCount += result.turnsUsed;
|
|
10447
10517
|
if (result.aborted && result.status) {
|
|
@@ -10466,17 +10536,11 @@ async function fillFormParallel(form, model, provider, options, initialPatches,
|
|
|
10466
10536
|
});
|
|
10467
10537
|
} catch {}
|
|
10468
10538
|
const results = await runWithConcurrency(batchItems.map((item, itemIndex) => {
|
|
10469
|
-
return
|
|
10470
|
-
|
|
10471
|
-
|
|
10472
|
-
|
|
10473
|
-
|
|
10474
|
-
enableWebSearch: options.enableWebSearch,
|
|
10475
|
-
additionalTools: options.additionalTools,
|
|
10476
|
-
callbacks: mergedCallbacks,
|
|
10477
|
-
maxStepsPerTurn: options.maxStepsPerTurn
|
|
10478
|
-
}), [item], targetRoles, maxPatchesPerTurn, maxIssuesPerTurn, maxTurnsTotal, turnCount, options, order, `${order}-batch-${batch.batchId}-${itemIndex}`, mergedCallbacks);
|
|
10479
|
-
}).map((p) => p), maxParallelAgents);
|
|
10539
|
+
return () => {
|
|
10540
|
+
const batchExecId = batchExecutionId(order, batch.batchId, itemIndex);
|
|
10541
|
+
return runMultiTurnForItems(form, createAgentForExecution(batchExecId), [item], targetRoles, maxPatchesPerTurn, maxIssuesPerTurn, maxTurnsTotal, turnCount, options, order, batchExecId, mergedCallbacks);
|
|
10542
|
+
};
|
|
10543
|
+
}), maxParallelAgents);
|
|
10480
10544
|
let batchPatches = 0;
|
|
10481
10545
|
const batchErrors = [];
|
|
10482
10546
|
for (const result of results) if (result.status === "fulfilled") {
|
|
@@ -10608,7 +10672,8 @@ async function runMultiTurnForItems(form, agent, items, targetRoles, maxPatchesP
|
|
|
10608
10672
|
stats: response.stats,
|
|
10609
10673
|
issues: scopedIssues,
|
|
10610
10674
|
patches: response.patches,
|
|
10611
|
-
rejectedPatches: previousRejections ?? []
|
|
10675
|
+
rejectedPatches: previousRejections ?? [],
|
|
10676
|
+
executionId
|
|
10612
10677
|
});
|
|
10613
10678
|
} catch {}
|
|
10614
10679
|
}
|
|
@@ -10774,6 +10839,7 @@ const ToolCallRecordSchema = z.object({
|
|
|
10774
10839
|
tool: z.string(),
|
|
10775
10840
|
startedAt: z.string().datetime(),
|
|
10776
10841
|
completedAt: z.string().datetime(),
|
|
10842
|
+
startMs: z.number().int().nonnegative(),
|
|
10777
10843
|
durationMs: z.number().int().nonnegative(),
|
|
10778
10844
|
success: z.boolean(),
|
|
10779
10845
|
input: z.record(z.string(), z.unknown()),
|
|
@@ -10791,6 +10857,7 @@ const TimelineEntrySchema = z.object({
|
|
|
10791
10857
|
executionId: z.string(),
|
|
10792
10858
|
startedAt: z.string().datetime(),
|
|
10793
10859
|
completedAt: z.string().datetime(),
|
|
10860
|
+
startMs: z.number().int().nonnegative(),
|
|
10794
10861
|
durationMs: z.number().int().nonnegative(),
|
|
10795
10862
|
issuesAddressed: z.number().int().nonnegative(),
|
|
10796
10863
|
patchesApplied: z.number().int().nonnegative(),
|
|
@@ -11044,8 +11111,8 @@ function validateResearchForm(form) {
|
|
|
11044
11111
|
//#endregion
|
|
11045
11112
|
//#region src/index.ts
|
|
11046
11113
|
/** Markform version (injected at build time). */
|
|
11047
|
-
const VERSION = "0.1.
|
|
11114
|
+
const VERSION = "0.1.22";
|
|
11048
11115
|
|
|
11049
11116
|
//#endregion
|
|
11050
11117
|
export { FormHarness as A, serializeScopeRef as B, resolveModel as C, computeExecutionPlan as D, FillRecordCollector as E, getFieldId as F, injectCheckboxIds as G, formToJsonSchema as H, isCellRef as I, findEnclosingHeadings as J, injectHeaderIds as K, isFieldRef as L, coerceInputContext as M, coerceToFieldPatch as N, MockAgent as O, findFieldById as P, isQualifiedRef as R, getProviderNames as S, createLiveAgent as T, parseForm as U, fieldToJsonSchema as V, findAllCheckboxes as W, parseMarkdownTable as X, parseCellValue as Y, parseRawTable as Z, fillForm as _, ExecutionMetadataSchema as a, scopeIssuesForItem as b, TimelineEntrySchema as c, ToolCallRecordSchema as d, ToolStatsSchema as f, resolveHarnessConfig as g, formatFillRecordSummary as h, runResearch as i, createHarness as j, createMockAgent as k, TimingBreakdownItemSchema as l, stripUnstableFillRecordFields as m, isResearchForm as n, FillRecordSchema as o, ToolSummarySchema as p, findAllHeadings as q, validateResearchForm as r, FillRecordStatusSchema as s, VERSION as t, TimingBreakdownSchema as u, ParallelHarness as v, buildMockWireFormat as w, getProviderInfo as x, createParallelHarness as y, parseScopeRef as z };
|
|
11051
|
-
//# sourceMappingURL=src-
|
|
11118
|
+
//# sourceMappingURL=src-CbRnGzMK.mjs.map
|