pulseed 0.1.0 → 0.1.2
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 +9 -62
- package/dist/cli/commands/config.d.ts.map +1 -1
- package/dist/cli/commands/config.js +2 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/goal-utils.d.ts.map +1 -1
- package/dist/cli/commands/goal-utils.js +18 -6
- package/dist/cli/commands/goal-utils.js.map +1 -1
- package/dist/cli/commands/goal-write.d.ts.map +1 -1
- package/dist/cli/commands/goal-write.js +34 -1
- package/dist/cli/commands/goal-write.js.map +1 -1
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +18 -0
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/suggest-normalizer.d.ts.map +1 -1
- package/dist/cli/commands/suggest-normalizer.js +5 -0
- package/dist/cli/commands/suggest-normalizer.js.map +1 -1
- package/dist/cli/commands/suggest.d.ts.map +1 -1
- package/dist/cli/commands/suggest.js +13 -3
- package/dist/cli/commands/suggest.js.map +1 -1
- package/dist/cli/commands/task-read 2.d.ts +4 -0
- package/dist/cli/commands/task-read 2.d.ts.map +1 -0
- package/dist/cli/commands/task-read 2.js +195 -0
- package/dist/cli/commands/task-read 2.js.map +1 -0
- package/dist/cli/commands/task-read.d.ts +4 -0
- package/dist/cli/commands/task-read.d.ts.map +1 -0
- package/dist/cli/commands/task-read.js +195 -0
- package/dist/cli/commands/task-read.js.map +1 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +4 -2
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli-runner.d.ts.map +1 -1
- package/dist/cli-runner.js +19 -0
- package/dist/cli-runner.js.map +1 -1
- package/dist/core-loop.d.ts.map +1 -1
- package/dist/core-loop.js +1 -0
- package/dist/core-loop.js.map +1 -1
- package/dist/drive/progress-predictor.d.ts +24 -0
- package/dist/drive/progress-predictor.d.ts.map +1 -0
- package/dist/drive/progress-predictor.js +93 -0
- package/dist/drive/progress-predictor.js.map +1 -0
- package/dist/drive/stall-detector.d.ts +8 -1
- package/dist/drive/stall-detector.d.ts.map +1 -1
- package/dist/drive/stall-detector.js +42 -2
- package/dist/drive/stall-detector.js.map +1 -1
- package/dist/execution/reflection-generator.d.ts +1 -1
- package/dist/execution/reflection-generator.d.ts.map +1 -1
- package/dist/execution/reflection-generator.js +3 -3
- package/dist/execution/reflection-generator.js.map +1 -1
- package/dist/execution/task-executor.d.ts.map +1 -1
- package/dist/execution/task-executor.js +1 -0
- package/dist/execution/task-executor.js.map +1 -1
- package/dist/execution/task-generation.js +1 -1
- package/dist/execution/task-generation.js.map +1 -1
- package/dist/execution/task-lifecycle.js +1 -1
- package/dist/execution/task-lifecycle.js.map +1 -1
- package/dist/execution/task-verifier.d.ts.map +1 -1
- package/dist/execution/task-verifier.js +11 -2
- package/dist/execution/task-verifier.js.map +1 -1
- package/dist/goal/goal-dependency-graph.d.ts +6 -1
- package/dist/goal/goal-dependency-graph.d.ts.map +1 -1
- package/dist/goal/goal-dependency-graph.js +6 -3
- package/dist/goal/goal-dependency-graph.js.map +1 -1
- package/dist/goal/goal-negotiator.d.ts.map +1 -1
- package/dist/goal/goal-negotiator.js +36 -14
- package/dist/goal/goal-negotiator.js.map +1 -1
- package/dist/goal/goal-refiner.d.ts.map +1 -1
- package/dist/goal/goal-refiner.js +6 -8
- package/dist/goal/goal-refiner.js.map +1 -1
- package/dist/goal/goal-suggest.d.ts +9 -2
- package/dist/goal/goal-suggest.d.ts.map +1 -1
- package/dist/goal/goal-suggest.js +74 -17
- package/dist/goal/goal-suggest.js.map +1 -1
- package/dist/goal/goal-tree-manager.d.ts.map +1 -1
- package/dist/goal/goal-tree-manager.js +8 -10
- package/dist/goal/goal-tree-manager.js.map +1 -1
- package/dist/goal/negotiator-steps.d.ts.map +1 -1
- package/dist/goal/negotiator-steps.js +1 -3
- package/dist/goal/negotiator-steps.js.map +1 -1
- package/dist/goal/refiner-prompts.d.ts +1 -17
- package/dist/goal/refiner-prompts.d.ts.map +1 -1
- package/dist/goal/refiner-prompts.js +1 -65
- package/dist/goal/refiner-prompts.js.map +1 -1
- package/dist/goal/subgoal-curriculum.d.ts +30 -0
- package/dist/goal/subgoal-curriculum.d.ts.map +1 -0
- package/dist/goal/subgoal-curriculum.js +53 -0
- package/dist/goal/subgoal-curriculum.js.map +1 -0
- package/dist/goal/tree-loop-orchestrator.d.ts.map +1 -1
- package/dist/goal/tree-loop-orchestrator.js +3 -2
- package/dist/goal/tree-loop-orchestrator.js.map +1 -1
- package/dist/llm/base-llm-client.d.ts +38 -6
- package/dist/llm/base-llm-client.d.ts.map +1 -1
- package/dist/llm/base-llm-client.js +120 -14
- package/dist/llm/base-llm-client.js.map +1 -1
- package/dist/llm/json-sanitizer.d.ts +34 -0
- package/dist/llm/json-sanitizer.d.ts.map +1 -0
- package/dist/llm/json-sanitizer.js +110 -0
- package/dist/llm/json-sanitizer.js.map +1 -0
- package/dist/llm/llm-client.d.ts +10 -2
- package/dist/llm/llm-client.d.ts.map +1 -1
- package/dist/llm/llm-client.js +19 -2
- package/dist/llm/llm-client.js.map +1 -1
- package/dist/llm/provider-factory.js +1 -1
- package/dist/llm/provider-factory.js.map +1 -1
- package/dist/loop/core-loop-phases-b.d.ts.map +1 -1
- package/dist/loop/core-loop-phases-b.js +6 -0
- package/dist/loop/core-loop-phases-b.js.map +1 -1
- package/dist/observation/capability-detector.d.ts.map +1 -1
- package/dist/observation/capability-detector.js +2 -1
- package/dist/observation/capability-detector.js.map +1 -1
- package/dist/observation/observation-llm.d.ts.map +1 -1
- package/dist/observation/observation-llm.js +3 -1
- package/dist/observation/observation-llm.js.map +1 -1
- package/dist/runtime/daemon-runner.d.ts.map +1 -1
- package/dist/runtime/daemon-runner.js +8 -4
- package/dist/runtime/daemon-runner.js.map +1 -1
- package/dist/tui/entry.d.ts.map +1 -1
- package/dist/tui/entry.js +4 -2
- package/dist/tui/entry.js.map +1 -1
- package/dist/types/core.d.ts +1 -1
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/core.js +2 -0
- package/dist/types/core.js.map +1 -1
- package/dist/types/stall.d.ts +3 -3
- package/dist/types/task-group.d.ts +15 -0
- package/dist/types/task-group.d.ts.map +1 -1
- package/dist/types/task.d.ts +9 -0
- package/dist/types/task.d.ts.map +1 -1
- package/dist/types/task.js +4 -0
- package/dist/types/task.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,21 +1,5 @@
|
|
|
1
1
|
import type { Goal } from "../types/goal.js";
|
|
2
|
-
|
|
3
|
-
* Sanitizes LLM-returned threshold_type strings to valid enum values.
|
|
4
|
-
* Handles the union of all known non-standard values from both
|
|
5
|
-
* GoalRefiner (leaf test) and GoalTreeManager (subgoal decomposition).
|
|
6
|
-
*
|
|
7
|
-
* Uses regex replacement so it works on raw JSON strings before parsing.
|
|
8
|
-
*/
|
|
9
|
-
export declare function sanitizeThresholdTypes(raw: string): string;
|
|
10
|
-
/**
|
|
11
|
-
* Sanitizes LLM-returned threshold_value when threshold_type is "present".
|
|
12
|
-
* When the LLM returns an object (e.g. `{"type":"present"}`) as the value for
|
|
13
|
-
* a present threshold, replace it with null so downstream Zod schemas accept it.
|
|
14
|
-
*
|
|
15
|
-
* Operates on the raw JSON string before parsing to avoid any type-safety issues
|
|
16
|
-
* with the un-parsed LLM output.
|
|
17
|
-
*/
|
|
18
|
-
export declare function sanitizeThresholdValues(raw: string): string;
|
|
2
|
+
export { sanitizeThresholdTypes, sanitizeThresholdValues } from "../llm/json-sanitizer.js";
|
|
19
3
|
/**
|
|
20
4
|
* Builds the leaf test prompt for the GoalRefiner.
|
|
21
5
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refiner-prompts.d.ts","sourceRoot":"","sources":["../../src/goal/refiner-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"refiner-prompts.d.ts","sourceRoot":"","sources":["../../src/goal/refiner-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAE3F;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,oBAAoB,EAAE,MAAM,EAAE,GAC7B,MAAM,CAkDR"}
|
|
@@ -1,68 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const THRESHOLD_TYPE_MAP = {
|
|
3
|
-
exact: "match",
|
|
4
|
-
scale: "min",
|
|
5
|
-
qualitative: "min",
|
|
6
|
-
boolean: "present",
|
|
7
|
-
percentage: "min",
|
|
8
|
-
count: "min",
|
|
9
|
-
};
|
|
10
|
-
const VALID_THRESHOLD_TYPES = new Set(["min", "max", "range", "present", "match"]);
|
|
11
|
-
/**
|
|
12
|
-
* Sanitizes LLM-returned threshold_type strings to valid enum values.
|
|
13
|
-
* Handles the union of all known non-standard values from both
|
|
14
|
-
* GoalRefiner (leaf test) and GoalTreeManager (subgoal decomposition).
|
|
15
|
-
*
|
|
16
|
-
* Uses regex replacement so it works on raw JSON strings before parsing.
|
|
17
|
-
*/
|
|
18
|
-
export function sanitizeThresholdTypes(raw) {
|
|
19
|
-
return raw.replace(/"threshold_type"\s*:\s*"([^"]+)"/g, (_match, val) => {
|
|
20
|
-
if (VALID_THRESHOLD_TYPES.has(val))
|
|
21
|
-
return `"threshold_type": "${val}"`;
|
|
22
|
-
const mapped = THRESHOLD_TYPE_MAP[val] ?? "min";
|
|
23
|
-
return `"threshold_type": "${mapped}"`;
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Sanitizes LLM-returned threshold_value when threshold_type is "present".
|
|
28
|
-
* When the LLM returns an object (e.g. `{"type":"present"}`) as the value for
|
|
29
|
-
* a present threshold, replace it with null so downstream Zod schemas accept it.
|
|
30
|
-
*
|
|
31
|
-
* Operates on the raw JSON string before parsing to avoid any type-safety issues
|
|
32
|
-
* with the un-parsed LLM output.
|
|
33
|
-
*/
|
|
34
|
-
export function sanitizeThresholdValues(raw) {
|
|
35
|
-
// Find any "threshold_value": <object> that immediately follows a "present" threshold_type.
|
|
36
|
-
// Strategy: parse and re-serialize only the threshold_value fields for present dimensions.
|
|
37
|
-
// We use a two-pass approach on the raw string to avoid fragile regex on nested JSON.
|
|
38
|
-
try {
|
|
39
|
-
const parsed = JSON.parse(raw);
|
|
40
|
-
const sanitized = sanitizePresentThresholdValues(parsed);
|
|
41
|
-
return JSON.stringify(sanitized);
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// If JSON parsing fails, return as-is and let downstream parsers handle it.
|
|
45
|
-
return raw;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function sanitizePresentThresholdValues(value) {
|
|
49
|
-
if (Array.isArray(value)) {
|
|
50
|
-
return value.map(sanitizePresentThresholdValues);
|
|
51
|
-
}
|
|
52
|
-
if (value !== null && typeof value === "object") {
|
|
53
|
-
const record = value;
|
|
54
|
-
const result = {};
|
|
55
|
-
for (const [k, v] of Object.entries(record)) {
|
|
56
|
-
result[k] = sanitizePresentThresholdValues(v);
|
|
57
|
-
}
|
|
58
|
-
// If this object has threshold_type === "present" and threshold_value is an object, null it out.
|
|
59
|
-
if (result["threshold_type"] === "present" && typeof result["threshold_value"] === "object" && result["threshold_value"] !== null) {
|
|
60
|
-
result["threshold_value"] = null;
|
|
61
|
-
}
|
|
62
|
-
return result;
|
|
63
|
-
}
|
|
64
|
-
return value;
|
|
65
|
-
}
|
|
1
|
+
export { sanitizeThresholdTypes, sanitizeThresholdValues } from "../llm/json-sanitizer.js";
|
|
66
2
|
/**
|
|
67
3
|
* Builds the leaf test prompt for the GoalRefiner.
|
|
68
4
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refiner-prompts.js","sourceRoot":"","sources":["../../src/goal/refiner-prompts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"refiner-prompts.js","sourceRoot":"","sources":["../../src/goal/refiner-prompts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAE3F;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAU,EACV,oBAA8B;IAE9B,MAAM,kBAAkB,GACtB,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QACzB,CAAC,CAAC,gBAAgB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC/C,CAAC,CAAC,mBAAmB,CAAC;IAE1B,MAAM,kBAAkB,GACtB,oBAAoB,CAAC,MAAM,GAAG,CAAC;QAC7B,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC;QACjC,CAAC,CAAC,uBAAuB,CAAC;IAE9B,OAAO;;SAEA,IAAI,CAAC,WAAW;EACvB,kBAAkB;0BACM,kBAAkB;SACnC,IAAI,CAAC,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oEAiCmC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Difficulty-based curriculum ordering for subgoal selection.
|
|
3
|
+
* Prioritizes medium-complexity (0.3-0.7) subgoals using gap × (1 - confidence).
|
|
4
|
+
*/
|
|
5
|
+
import type { Goal } from "../types/goal.js";
|
|
6
|
+
/** Preferred difficulty band for curriculum-based selection. */
|
|
7
|
+
export declare const MEDIUM_BAND: {
|
|
8
|
+
min: number;
|
|
9
|
+
max: number;
|
|
10
|
+
};
|
|
11
|
+
/** Goals with aggregated gap below this threshold are treated as medium difficulty to avoid starvation. */
|
|
12
|
+
export declare const NEAR_COMPLETE_GAP_THRESHOLD = 0.1;
|
|
13
|
+
/**
|
|
14
|
+
* Estimate difficulty for a single goal.
|
|
15
|
+
* difficulty = aggregatedGap × (1 - minConfidence), clamped to [0, 1].
|
|
16
|
+
* Uses calculateDimensionGap for consistent gap computation, aggregateGaps for aggregation.
|
|
17
|
+
* Returns 0.5 (medium) when dimensions is empty or goal is near-complete.
|
|
18
|
+
*/
|
|
19
|
+
export declare function estimateDifficulty(goal: Goal): number;
|
|
20
|
+
/**
|
|
21
|
+
* Sort subgoal entries in-place using center-biased curriculum ordering.
|
|
22
|
+
* Primary: |difficulty - 0.5| ascending (closest to medium first).
|
|
23
|
+
* Tiebreaker: depth descending (deeper first).
|
|
24
|
+
*/
|
|
25
|
+
export declare function curriculumSort(entries: Array<{
|
|
26
|
+
id: string;
|
|
27
|
+
depth: number;
|
|
28
|
+
difficulty: number;
|
|
29
|
+
}>): void;
|
|
30
|
+
//# sourceMappingURL=subgoal-curriculum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subgoal-curriculum.d.ts","sourceRoot":"","sources":["../../src/goal/subgoal-curriculum.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAM7C,gEAAgE;AAChE,eAAO,MAAM,WAAW;;;CAAyB,CAAC;AAElD,2GAA2G;AAC3G,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CA8BrD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,GAChE,IAAI,CAON"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Difficulty-based curriculum ordering for subgoal selection.
|
|
3
|
+
* Prioritizes medium-complexity (0.3-0.7) subgoals using gap × (1 - confidence).
|
|
4
|
+
*/
|
|
5
|
+
import { calculateDimensionGap, aggregateGaps, } from "../drive/gap-calculator.js";
|
|
6
|
+
/** Preferred difficulty band for curriculum-based selection. */
|
|
7
|
+
export const MEDIUM_BAND = { min: 0.3, max: 0.7 };
|
|
8
|
+
/** Goals with aggregated gap below this threshold are treated as medium difficulty to avoid starvation. */
|
|
9
|
+
export const NEAR_COMPLETE_GAP_THRESHOLD = 0.1;
|
|
10
|
+
/**
|
|
11
|
+
* Estimate difficulty for a single goal.
|
|
12
|
+
* difficulty = aggregatedGap × (1 - minConfidence), clamped to [0, 1].
|
|
13
|
+
* Uses calculateDimensionGap for consistent gap computation, aggregateGaps for aggregation.
|
|
14
|
+
* Returns 0.5 (medium) when dimensions is empty or goal is near-complete.
|
|
15
|
+
*/
|
|
16
|
+
export function estimateDifficulty(goal) {
|
|
17
|
+
const dims = goal.dimensions;
|
|
18
|
+
if (dims.length === 0)
|
|
19
|
+
return 0.5;
|
|
20
|
+
const weightedGaps = dims.map((d) => calculateDimensionGap({
|
|
21
|
+
name: d.name,
|
|
22
|
+
current_value: d.current_value,
|
|
23
|
+
threshold: d.threshold,
|
|
24
|
+
confidence: d.confidence,
|
|
25
|
+
uncertainty_weight: d.uncertainty_weight,
|
|
26
|
+
}, goal.uncertainty_weight));
|
|
27
|
+
// Use normalized_gap (pre-uncertainty-weighting) so the confidence multiplier
|
|
28
|
+
// below applies uniformly, including for null current_value (which yields 1.0).
|
|
29
|
+
const gapValues = weightedGaps.map((wg) => wg.normalized_gap);
|
|
30
|
+
const weights = dims.map((d) => d.weight ?? 1.0);
|
|
31
|
+
const minConfidence = Math.min(...dims.map((d) => d.confidence));
|
|
32
|
+
const aggregatedGap = aggregateGaps(gapValues, goal.gap_aggregation, weights);
|
|
33
|
+
// Near-complete goals (gap < threshold) should not be starved — treat as medium difficulty
|
|
34
|
+
if (aggregatedGap < NEAR_COMPLETE_GAP_THRESHOLD)
|
|
35
|
+
return 0.5;
|
|
36
|
+
const difficulty = aggregatedGap * (1 - minConfidence);
|
|
37
|
+
return Math.min(1, Math.max(0, difficulty));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Sort subgoal entries in-place using center-biased curriculum ordering.
|
|
41
|
+
* Primary: |difficulty - 0.5| ascending (closest to medium first).
|
|
42
|
+
* Tiebreaker: depth descending (deeper first).
|
|
43
|
+
*/
|
|
44
|
+
export function curriculumSort(entries) {
|
|
45
|
+
entries.sort((a, b) => {
|
|
46
|
+
const aDist = Math.abs(a.difficulty - 0.5);
|
|
47
|
+
const bDist = Math.abs(b.difficulty - 0.5);
|
|
48
|
+
if (aDist !== bDist)
|
|
49
|
+
return aDist - bDist;
|
|
50
|
+
return b.depth - a.depth;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=subgoal-curriculum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subgoal-curriculum.js","sourceRoot":"","sources":["../../src/goal/subgoal-curriculum.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,qBAAqB,EACrB,aAAa,GACd,MAAM,4BAA4B,CAAC;AAEpC,gEAAgE;AAChE,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAElD,2GAA2G;AAC3G,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAU;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;IAC7B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAElC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAClC,qBAAqB,CACnB;QACE,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,aAAa,EAAE,CAAC,CAAC,aAAa;QAC9B,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,kBAAkB,EAAE,CAAC,CAAC,kBAAkB;KACzC,EACD,IAAI,CAAC,kBAAkB,CACxB,CACF,CAAC;IAEF,8EAA8E;IAC9E,gFAAgF;IAChF,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;IACjD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjE,MAAM,aAAa,GAAG,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IAE9E,2FAA2F;IAC3F,IAAI,aAAa,GAAG,2BAA2B;QAAE,OAAO,GAAG,CAAC;IAE5D,MAAM,UAAU,GAAG,aAAa,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAiE;IAEjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;QAC3C,IAAI,KAAK,KAAK,KAAK;YAAE,OAAO,KAAK,GAAG,KAAK,CAAC;QAC1C,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-loop-orchestrator.d.ts","sourceRoot":"","sources":["../../src/goal/tree-loop-orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"tree-loop-orchestrator.d.ts","sourceRoot":"","sources":["../../src/goal/tree-loop-orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAIrE;;;;;;;;;;;;GAYG;AACH,qBAAa,oBAAoB;IAa7B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAhB/B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAKZ;gBAGiB,YAAY,EAAE,YAAY,EAC1B,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,eAAe,EAChC,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,CAAC,EAAE,WAAW,YAAA;IAK5C;;;;;OAKG;IACG,kBAAkB,CACtB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,IAAI,CAAC;IAwBhB;;;;;;OAMG;IACG,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCtD;;;;;;;;;;;;;OAaG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA4B5D;;;;OAIG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlD;;;;OAIG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAanD;;;;;;;;OAQG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCpD;;OAEG;YACW,wBAAwB;IAWtC;;;OAGG;YACW,qBAAqB;IAqBnC;;OAEG;YACW,uBAAuB;CAatC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { hasValidatedDimensions } from "./goal-refiner.js";
|
|
2
|
+
import { estimateDifficulty, curriculumSort } from "./subgoal-curriculum.js";
|
|
2
3
|
/**
|
|
3
4
|
* TreeLoopOrchestrator manages the execution of independent loops across
|
|
4
5
|
* all nodes in a goal tree.
|
|
@@ -239,13 +240,13 @@ export class TreeLoopOrchestrator {
|
|
|
239
240
|
if (goal.loop_status === "running" || goal.loop_status === "paused")
|
|
240
241
|
continue;
|
|
241
242
|
if (goal.node_type === "leaf") {
|
|
242
|
-
eligibleLeaves.push({ id, depth: goal.decomposition_depth ?? 0 });
|
|
243
|
+
eligibleLeaves.push({ id, depth: goal.decomposition_depth ?? 0, difficulty: estimateDifficulty(goal) });
|
|
243
244
|
}
|
|
244
245
|
else {
|
|
245
246
|
eligibleNonLeaves.push(id);
|
|
246
247
|
}
|
|
247
248
|
}
|
|
248
|
-
eligibleLeaves
|
|
249
|
+
curriculumSort(eligibleLeaves);
|
|
249
250
|
return eligibleLeaves[0]?.id ?? eligibleNonLeaves[0] ?? null;
|
|
250
251
|
}
|
|
251
252
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-loop-orchestrator.js","sourceRoot":"","sources":["../../src/goal/tree-loop-orchestrator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"tree-loop-orchestrator.js","sourceRoot":"","sources":["../../src/goal/tree-loop-orchestrator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAK3D,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE7E;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,oBAAoB;IAaZ;IACA;IACA;IACA;IACA;IAhBnB;;;OAGG;IACK,MAAM,GAA4B;QACxC,SAAS,EAAE,CAAC;QACZ,eAAe,EAAE,GAAG;QACpB,oBAAoB,EAAE,GAAG;QACzB,mBAAmB,EAAE,CAAC;KACvB,CAAC;IAEF,YACmB,YAA0B,EAC1B,eAAgC,EAChC,eAAgC,EAChC,gBAAkC,EAClC,WAAyB;QAJzB,iBAAY,GAAZ,YAAY,CAAc;QAC1B,oBAAe,GAAf,eAAe,CAAiB;QAChC,oBAAe,GAAf,eAAe,CAAiB;QAChC,qBAAgB,GAAhB,gBAAgB,CAAkB;QAClC,gBAAW,GAAX,WAAW,CAAc;IACzC,CAAC;IAEJ,wCAAwC;IAExC;;;;;OAKG;IACH,KAAK,CAAC,kBAAkB,CACtB,MAAc,EACd,MAA+B;QAE/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,2EAA2E;QAC3E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC;QAExE,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAClD,IAAI,IAAI,IAAI,IAAI,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC;gBACxC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;oBAC/B,GAAG,IAAI;oBACP,WAAW,EAAE,MAAM;oBACnB,UAAU,EAAE,GAAG;iBAChB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,yBAAyB;IAEzB;;;;;;OAMG;IACH,KAAK,CAAC,iBAAiB,CAAC,MAAc;QACpC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,8CAA8C;QAC9C,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO;QAEzC,0DAA0D;QAC1D,IAAI,sBAAsB,CAAC,IAAI,CAAC;YAAE,OAAO;QAEzC,MAAM,mBAAmB,GAA4B;YACnD,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;YAChC,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe;YAC5C,oBAAoB,EAAE,IAAI,CAAC,MAAM,CAAC,oBAAoB;YACtD,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB;SACrD,CAAC;QAEF,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACP,0DAA0D;gBAC1D,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;gBACxE,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;YACxE,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,cAAc,CAAC,MAAc;QACjC,+BAA+B;QAC/B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAClE,IAAI,SAAS,CAAC,YAAY,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;YACrE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mDAAmD;QACnD,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC;QACxE,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAE5D,IAAI,UAAU,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAErC,gCAAgC;QAChC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC9D,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;gBAC/B,GAAG,QAAQ;gBACX,WAAW,EAAE,SAAS;gBACtB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACrC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,4BAA4B;IAE5B;;;;OAIG;IACH,KAAK,CAAC,aAAa,CAAC,MAAc;QAChC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;YAC/B,GAAG,IAAI;YACP,WAAW,EAAE,QAAQ;YACrB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,MAAc;QACjC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;YAC/B,GAAG,IAAI;YACP,WAAW,EAAE,SAAS;YACtB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC,CAAC;IACL,CAAC;IAED,mCAAmC;IAEnC;;;;;;;;OAQG;IACH,KAAK,CAAC,eAAe,CAAC,MAAc;QAClC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAErC,sCAAsC;QACtC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;gBAC/B,GAAG,IAAI;gBACP,WAAW,EAAE,MAAM;gBACnB,UAAU,EAAE,GAAG;aAChB,CAAC,CAAC;QACL,CAAC;QAED,2CAA2C;QAC3C,IAAI,QAAQ,GAAG,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC;QACvC,OAAO,QAAQ,KAAK,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAC5D,CAAC;YAAC,MAAM,CAAC;gBACP,uDAAuD;gBACvD,MAAM;YACR,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC1D,QAAQ,GAAG,MAAM,EAAE,SAAS,IAAI,IAAI,CAAC;QACvC,CAAC;QAED,6BAA6B;QAC7B,MAAM,IAAI,CAAC,uBAAuB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;IAED,0BAA0B;IAE1B;;OAEG;IACK,KAAK,CAAC,wBAAwB,CAAC,MAAc;QACnD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QACrB,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,qBAAqB,CAAC,MAAgB;QAClD,MAAM,cAAc,GAA6D,EAAE,CAAC;QACpF,MAAM,iBAAiB,GAAa,EAAE,CAAC;QAEvC,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAClD,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ;gBAAE,SAAS;YACvC,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,KAAK,QAAQ;gBAAE,SAAS;YAE9E,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;gBAC9B,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,mBAAmB,IAAI,CAAC,EAAE,UAAU,EAAE,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC1G,CAAC;iBAAM,CAAC;gBACN,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,cAAc,CAAC,cAAc,CAAC,CAAC;QAC/B,OAAO,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,iBAAiB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC/D,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,uBAAuB,CAAC,MAAc,EAAE,GAAW;QAC/D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC7E,KAAK,MAAM,UAAU,IAAI,UAAU,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC9D,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAChD,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;oBAC/B,GAAG,QAAQ;oBACX,MAAM,EAAE,WAAW;oBACnB,UAAU,EAAE,GAAG;iBAChB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -9,10 +9,27 @@ export declare const MAX_RETRY_ATTEMPTS = 3;
|
|
|
9
9
|
/** Exponential backoff delays in milliseconds: 1s, 2s, 4s */
|
|
10
10
|
export declare const RETRY_DELAYS_MS: number[];
|
|
11
11
|
/**
|
|
12
|
-
* Extract JSON from a string that may contain markdown code blocks.
|
|
13
|
-
*
|
|
12
|
+
* Extract JSON from a string that may contain markdown code blocks or prose.
|
|
13
|
+
*
|
|
14
|
+
* Strategies (first match wins):
|
|
15
|
+
* 1. Fast path — already valid JSON, return as-is
|
|
16
|
+
* 2. Code fence extraction — ```json ... ``` or ``` ... ```
|
|
17
|
+
* 3. Brace matching — find first { or [ and last matching } or ]
|
|
14
18
|
*/
|
|
15
19
|
export declare function extractJSON(text: string): string;
|
|
20
|
+
export interface ParseJSONMessage {
|
|
21
|
+
role: string;
|
|
22
|
+
content: string;
|
|
23
|
+
}
|
|
24
|
+
/** Options for parseJSON(). Pass `retry` to enable a single re-prompt on failure. */
|
|
25
|
+
export interface ParseJSONOptions {
|
|
26
|
+
retry?: {
|
|
27
|
+
/** Original messages used to produce the first LLM response. */
|
|
28
|
+
messages: ParseJSONMessage[];
|
|
29
|
+
/** Optional system prompt for the retry call. */
|
|
30
|
+
systemPrompt?: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
16
33
|
/**
|
|
17
34
|
* Abstract base for all LLM clients.
|
|
18
35
|
* Provides a shared parseJSON() implementation with safeParse-based validation,
|
|
@@ -29,10 +46,25 @@ export declare abstract class BaseLLMClient {
|
|
|
29
46
|
*/
|
|
30
47
|
protected resolveEffectiveModel(defaultModel: string, tier?: ModelTier): string;
|
|
31
48
|
/**
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
49
|
+
* Send messages to the LLM and return the response text.
|
|
50
|
+
* Used internally by parseJSON retry logic.
|
|
51
|
+
* Subclasses that support retry must override this method.
|
|
52
|
+
*/
|
|
53
|
+
protected callLLMRaw(_messages: ParseJSONMessage[], _systemPrompt?: string): Promise<string>;
|
|
54
|
+
/**
|
|
55
|
+
* Attempt to parse and validate a single content string against the schema.
|
|
56
|
+
* Returns the parsed value on success, or throws LLMError on failure.
|
|
57
|
+
*/
|
|
58
|
+
private attemptParse;
|
|
59
|
+
/**
|
|
60
|
+
* Extract JSON from LLM response text (handles markdown code blocks)
|
|
61
|
+
* and validate against the given Zod schema.
|
|
62
|
+
* Throws on parse failure or schema validation failure with detailed messages.
|
|
63
|
+
*
|
|
64
|
+
* When `options.retry` is provided, a single retry is attempted on first failure:
|
|
65
|
+
* the original messages are re-sent with an error feedback message appended.
|
|
66
|
+
*/
|
|
67
|
+
parseJSON<T>(content: string, schema: ZodSchema<T>, options?: ParseJSONOptions): Promise<T>;
|
|
36
68
|
parseJSON<T>(content: string, schema: ZodSchema<T>): T;
|
|
37
69
|
}
|
|
38
70
|
//# sourceMappingURL=base-llm-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-llm-client.d.ts","sourceRoot":"","sources":["../../src/llm/base-llm-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"base-llm-client.d.ts","sourceRoot":"","sources":["../../src/llm/base-llm-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAMrC,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAIzC,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,kDAAkD;AAClD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,6DAA6D;AAC7D,eAAO,MAAM,eAAe,UAAqB,CAAC;AAIlD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA2DhD;AAID,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qFAAqF;AACrF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE;QACN,gEAAgE;QAChE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAC7B,iDAAiD;QACjD,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAID;;;;GAIG;AACH,8BAAsB,aAAa;IACjC,iFAAiF;IACjF,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;;OAKG;IACH,SAAS,CAAC,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM;IAO/E;;;;OAIG;cAEa,UAAU,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlG;;;OAGG;IACH,OAAO,CAAC,YAAY;IAoBpB;;;;;;;OAOG;IACG,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IACjG,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;CAmCvD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LLMError } from "../utils/errors.js";
|
|
2
|
+
import { sanitizeLLMJson } from "./json-sanitizer.js";
|
|
2
3
|
// ─── Shared constants ───
|
|
3
4
|
export const DEFAULT_MAX_TOKENS = 4096;
|
|
4
5
|
/** Default LLM request timeout in milliseconds */
|
|
@@ -9,19 +10,81 @@ export const MAX_RETRY_ATTEMPTS = 3;
|
|
|
9
10
|
export const RETRY_DELAYS_MS = [1000, 2000, 4000];
|
|
10
11
|
// ─── JSON extraction utility ───
|
|
11
12
|
/**
|
|
12
|
-
* Extract JSON from a string that may contain markdown code blocks.
|
|
13
|
-
*
|
|
13
|
+
* Extract JSON from a string that may contain markdown code blocks or prose.
|
|
14
|
+
*
|
|
15
|
+
* Strategies (first match wins):
|
|
16
|
+
* 1. Fast path — already valid JSON, return as-is
|
|
17
|
+
* 2. Code fence extraction — ```json ... ``` or ``` ... ```
|
|
18
|
+
* 3. Brace matching — find first { or [ and last matching } or ]
|
|
14
19
|
*/
|
|
15
20
|
export function extractJSON(text) {
|
|
16
|
-
const
|
|
21
|
+
const trimmed = text.trim();
|
|
22
|
+
// 1. Fast path: already valid JSON
|
|
23
|
+
try {
|
|
24
|
+
JSON.parse(trimmed);
|
|
25
|
+
return trimmed;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// not bare JSON, continue
|
|
29
|
+
}
|
|
30
|
+
// 2. Code fence extraction
|
|
31
|
+
const jsonBlock = trimmed.match(/```json\s*([\s\S]*?)```/);
|
|
17
32
|
if (jsonBlock) {
|
|
18
33
|
return jsonBlock[1].trim();
|
|
19
34
|
}
|
|
20
|
-
const genericBlock =
|
|
35
|
+
const genericBlock = trimmed.match(/```\s*([\s\S]*?)```/);
|
|
21
36
|
if (genericBlock) {
|
|
22
37
|
return genericBlock[1].trim();
|
|
23
38
|
}
|
|
24
|
-
|
|
39
|
+
// 3. Depth-aware brace matching: scan from first { or [ to its matching close
|
|
40
|
+
const firstBrace = trimmed.indexOf("{");
|
|
41
|
+
const firstBracket = trimmed.indexOf("[");
|
|
42
|
+
let start = -1;
|
|
43
|
+
let openChar;
|
|
44
|
+
let closeChar;
|
|
45
|
+
if (firstBrace === -1 && firstBracket === -1) {
|
|
46
|
+
return trimmed;
|
|
47
|
+
}
|
|
48
|
+
else if (firstBrace === -1 || (firstBracket !== -1 && firstBracket < firstBrace)) {
|
|
49
|
+
start = firstBracket;
|
|
50
|
+
openChar = "[";
|
|
51
|
+
closeChar = "]";
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
start = firstBrace;
|
|
55
|
+
openChar = "{";
|
|
56
|
+
closeChar = "}";
|
|
57
|
+
}
|
|
58
|
+
let depth = 0;
|
|
59
|
+
let inString = false;
|
|
60
|
+
let escape = false;
|
|
61
|
+
for (let i = start; i < trimmed.length; i++) {
|
|
62
|
+
const ch = trimmed[i];
|
|
63
|
+
if (escape) {
|
|
64
|
+
escape = false;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (ch === "\\" && inString) {
|
|
68
|
+
escape = true;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (ch === '"') {
|
|
72
|
+
inString = !inString;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (inString)
|
|
76
|
+
continue;
|
|
77
|
+
if (ch === openChar) {
|
|
78
|
+
depth++;
|
|
79
|
+
}
|
|
80
|
+
else if (ch === closeChar) {
|
|
81
|
+
depth--;
|
|
82
|
+
if (depth === 0) {
|
|
83
|
+
return trimmed.slice(start, i + 1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return trimmed;
|
|
25
88
|
}
|
|
26
89
|
// ─── BaseLLMClient ───
|
|
27
90
|
/**
|
|
@@ -45,25 +108,68 @@ export class BaseLLMClient {
|
|
|
45
108
|
return effectiveModel;
|
|
46
109
|
}
|
|
47
110
|
/**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
111
|
+
* Send messages to the LLM and return the response text.
|
|
112
|
+
* Used internally by parseJSON retry logic.
|
|
113
|
+
* Subclasses that support retry must override this method.
|
|
114
|
+
*/
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
116
|
+
async callLLMRaw(_messages, _systemPrompt) {
|
|
117
|
+
throw new LLMError("callLLMRaw not implemented — override in subclass to enable parseJSON retry");
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Attempt to parse and validate a single content string against the schema.
|
|
121
|
+
* Returns the parsed value on success, or throws LLMError on failure.
|
|
122
|
+
*/
|
|
123
|
+
attemptParse(content, schema) {
|
|
124
|
+
const jsonText = sanitizeLLMJson(extractJSON(content));
|
|
54
125
|
let raw;
|
|
55
126
|
try {
|
|
56
127
|
raw = JSON.parse(jsonText);
|
|
57
128
|
}
|
|
58
129
|
catch (err) {
|
|
59
|
-
|
|
130
|
+
const msg = `LLM response JSON parse failed — ${String(err)}`;
|
|
131
|
+
console.warn(`[parseJSON] ${msg} | raw(200): ${content.slice(0, 200)}`);
|
|
132
|
+
throw new LLMError(`${msg}\nContent: ${content}`);
|
|
60
133
|
}
|
|
61
134
|
const result = schema.safeParse(raw);
|
|
62
135
|
if (!result.success) {
|
|
63
|
-
|
|
64
|
-
|
|
136
|
+
const issues = result.error.issues.map((i) => i.message).join(", ");
|
|
137
|
+
const msg = `LLM response validation failed: ${issues}`;
|
|
138
|
+
console.warn(`[parseJSON] ${msg} | raw(200): ${JSON.stringify(raw).slice(0, 200)}`);
|
|
139
|
+
throw new LLMError(`${msg}. Raw: ${JSON.stringify(raw).slice(0, 200)}`);
|
|
65
140
|
}
|
|
66
141
|
return result.data;
|
|
67
142
|
}
|
|
143
|
+
parseJSON(content, schema, options) {
|
|
144
|
+
if (!options?.retry) {
|
|
145
|
+
return this.attemptParse(content, schema);
|
|
146
|
+
}
|
|
147
|
+
// Async path: retry enabled
|
|
148
|
+
return (async () => {
|
|
149
|
+
let firstError;
|
|
150
|
+
try {
|
|
151
|
+
return this.attemptParse(content, schema);
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
firstError = err;
|
|
155
|
+
}
|
|
156
|
+
console.warn(`[parseJSON] first attempt failed, retrying... Error: ${firstError.message}`);
|
|
157
|
+
const retryMessages = [
|
|
158
|
+
...options.retry.messages,
|
|
159
|
+
{
|
|
160
|
+
role: "user",
|
|
161
|
+
content: `Your previous response was not valid JSON. Error: ${firstError.message}. Please respond with ONLY valid JSON matching the required schema, no other text.`,
|
|
162
|
+
},
|
|
163
|
+
];
|
|
164
|
+
const retryContent = await this.callLLMRaw(retryMessages, options.retry.systemPrompt);
|
|
165
|
+
try {
|
|
166
|
+
return this.attemptParse(retryContent, schema);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
console.warn(`[parseJSON] retry also failed`);
|
|
170
|
+
throw err;
|
|
171
|
+
}
|
|
172
|
+
})();
|
|
173
|
+
}
|
|
68
174
|
}
|
|
69
175
|
//# sourceMappingURL=base-llm-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-llm-client.js","sourceRoot":"","sources":["../../src/llm/base-llm-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"base-llm-client.js","sourceRoot":"","sources":["../../src/llm/base-llm-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* json-sanitizer.ts — Shared LLM JSON response sanitization utilities.
|
|
3
|
+
*
|
|
4
|
+
* Centralizes all sanitization logic so it can be applied consistently
|
|
5
|
+
* before JSON.parse() and Zod validation.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Sanitizes LLM-returned threshold_type strings to valid enum values.
|
|
9
|
+
* Handles the union of all known non-standard values from both
|
|
10
|
+
* GoalRefiner (leaf test) and GoalTreeManager (subgoal decomposition).
|
|
11
|
+
*
|
|
12
|
+
* Uses regex replacement so it works on raw JSON strings before parsing.
|
|
13
|
+
*/
|
|
14
|
+
export declare function sanitizeThresholdTypes(raw: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Sanitizes LLM-returned threshold_value when threshold_type is "present".
|
|
17
|
+
* When the LLM returns an object (e.g. `{"type":"present"}`) as the value for
|
|
18
|
+
* a present threshold, replace it with null so downstream Zod schemas accept it.
|
|
19
|
+
*
|
|
20
|
+
* Operates on the raw JSON string before parsing to avoid any type-safety issues
|
|
21
|
+
* with the un-parsed LLM output.
|
|
22
|
+
*/
|
|
23
|
+
export declare function sanitizeThresholdValues(raw: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Applies all LLM JSON sanitizers in sequence.
|
|
26
|
+
*
|
|
27
|
+
* Order:
|
|
28
|
+
* 1. Remove trailing commas (syntactic fix — must come before JSON.parse attempts)
|
|
29
|
+
* 2. Replace NaN/Infinity with null (syntactic fix)
|
|
30
|
+
* 3. Sanitize threshold_type enum values (domain-specific string replacement)
|
|
31
|
+
* 4. Sanitize threshold_value for "present" thresholds (requires parse+reserialize)
|
|
32
|
+
*/
|
|
33
|
+
export declare function sanitizeLLMJson(raw: string): string;
|
|
34
|
+
//# sourceMappingURL=json-sanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-sanitizer.d.ts","sourceRoot":"","sources":["../../src/llm/json-sanitizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS1D;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAY3D;AAgDD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOnD"}
|