@ordewell/core 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/LICENSE +211 -0
  2. package/README.md +37 -0
  3. package/dist/ITerminalRunner-Bbpe8uts.d.ts +535 -0
  4. package/dist/ITerminalRunner-D8Bf-HD4.d.mts +535 -0
  5. package/dist/Task-1NwmUImI.d.mts +264 -0
  6. package/dist/Task-1NwmUImI.d.ts +264 -0
  7. package/dist/chunk-4KIWPW4K.mjs +510 -0
  8. package/dist/chunk-4KIWPW4K.mjs.map +1 -0
  9. package/dist/chunk-SRGQBGI5.mjs +463 -0
  10. package/dist/chunk-SRGQBGI5.mjs.map +1 -0
  11. package/dist/chunk-YXAIQKVE.mjs +398 -0
  12. package/dist/chunk-YXAIQKVE.mjs.map +1 -0
  13. package/dist/index.d.mts +2990 -0
  14. package/dist/index.d.ts +2990 -0
  15. package/dist/index.js +12927 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/index.mjs +11449 -0
  18. package/dist/index.mjs.map +1 -0
  19. package/dist/parsing-RjN9JbyG.d.ts +161 -0
  20. package/dist/parsing-xpozY5ac.d.mts +161 -0
  21. package/dist/parsing.d.mts +2 -0
  22. package/dist/parsing.d.ts +2 -0
  23. package/dist/parsing.js +432 -0
  24. package/dist/parsing.js.map +1 -0
  25. package/dist/parsing.mjs +15 -0
  26. package/dist/parsing.mjs.map +1 -0
  27. package/dist/plan-utils-Cgc0cCH1.d.ts +111 -0
  28. package/dist/plan-utils-nfHKSbd3.d.mts +111 -0
  29. package/dist/plan-utils.d.mts +2 -0
  30. package/dist/plan-utils.d.ts +2 -0
  31. package/dist/plan-utils.js +181 -0
  32. package/dist/plan-utils.js.map +1 -0
  33. package/dist/plan-utils.mjs +18 -0
  34. package/dist/plan-utils.mjs.map +1 -0
  35. package/dist/testing.d.mts +28 -0
  36. package/dist/testing.d.ts +28 -0
  37. package/dist/testing.js +113 -0
  38. package/dist/testing.js.map +1 -0
  39. package/dist/testing.mjs +86 -0
  40. package/dist/testing.mjs.map +1 -0
  41. package/package.json +92 -0
@@ -0,0 +1,161 @@
1
+ import { h as RunnerId, s as ValidationContext, t as ValidationResult, T as Task } from './Task-1NwmUImI.js';
2
+
3
+ interface RunnerModeInfo {
4
+ id: string;
5
+ label: string;
6
+ description: string;
7
+ autonomous?: boolean;
8
+ safe?: boolean;
9
+ }
10
+ /** The slice of RunnerRegistry this module needs — structural, so nothing here depends on the plugin layer. */
11
+ interface ManifestLookup {
12
+ getManifest(runner: RunnerId): {
13
+ modes?: RunnerModeInfo[];
14
+ } | undefined;
15
+ }
16
+ /**
17
+ * A runner's modes are declared only in its manifest, never through a service,
18
+ * so every caller that needs them fuses registry and runner list by hand. This
19
+ * is that fusion, in one place: the planner prompt, the mode pickers on each
20
+ * surface, and the runner-change retarget all read modes the same way.
21
+ *
22
+ * A runner with no modes maps to `[]` rather than being dropped — callers
23
+ * distinguish "declares no modes" from "not asked about".
24
+ */
25
+ declare function runnerModesFrom(registry: ManifestLookup, runners: RunnerId[]): Record<RunnerId, RunnerModeInfo[]>;
26
+ /**
27
+ * Find the mode ID a runner resolves to under the given toggle state.
28
+ * Tag-based first (autonomous/safe); falls back to positional last non-plan
29
+ * if no tag is present on any mode (degrades gracefully on untagged manifests).
30
+ * Returns undefined if `modes` is empty or undefined.
31
+ */
32
+ declare function resolveDefaultMode(modes: RunnerModeInfo[] | undefined, autonomousDefault?: boolean): string | undefined;
33
+ /**
34
+ * Build modes compatible with the current toggle. Plan is excluded from the
35
+ * build-mode list (it is never a default for implementation tasks). Modes
36
+ * tagged exclusively for the OPPOSITE toggle are hidden — the LLM cannot see
37
+ * or select them. A dual-tagged mode (both autonomous + safe) is shown under
38
+ * either toggle.
39
+ */
40
+ declare function filteredBuildModes(modes: RunnerModeInfo[], autonomousDefault: boolean): RunnerModeInfo[];
41
+ declare function buildModeGuide(runnerModes: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean): string;
42
+ declare function resolveTaskMode(emittedMode: string | undefined, runnerId: RunnerId, runnerModes: Record<RunnerId, RunnerModeInfo[]> | undefined, autonomousDefault?: boolean): string;
43
+
44
+ /** The envelope key a full plan reply is keyed by: `{"tasks":[...]}`. */
45
+ declare const PLAN_ENVELOPE_KEY = "tasks";
46
+ /** The envelope key a targeted-edits reply is keyed by: `{"taskOps":[...]}`. */
47
+ declare const TASK_OPS_ENVELOPE_KEY = "taskOps";
48
+ /** Thrown when an LLM plan response cannot be parsed into a valid plan. Carries the raw text so callers can log it or retry. */
49
+ declare class PlanParseError extends Error {
50
+ readonly raw: string;
51
+ /**
52
+ * True when the reply was cut off mid-object (output-token limit) rather
53
+ * than malformed — the two need different repairs: a truncated emission will
54
+ * be cut at the same point again unless the retry frees context or asks for
55
+ * terser output.
56
+ */
57
+ readonly truncated: boolean;
58
+ /**
59
+ * True when the JSON parsed fine and a *shape* rule rejected it. The generic
60
+ * "could not be parsed as JSON" corrective is a lie for these, so the model
61
+ * re-sends the same object; a semantic rejection must be repaired by naming
62
+ * the rule it broke.
63
+ */
64
+ readonly semantic: boolean;
65
+ constructor(message: string, raw: string, opts?: {
66
+ truncated?: boolean;
67
+ semantic?: boolean;
68
+ });
69
+ }
70
+ /**
71
+ * Strip the noise reasoning models wrap around their answer: markdown code
72
+ * fences and `<think>…</think>` chain-of-thought blocks (which routinely contain
73
+ * stray braces that would otherwise derail brace-balancing). Reasoning captured
74
+ * out-of-band by the service never reaches here, but a model that inlines its
75
+ * thinking in the content channel still must not corrupt parsing.
76
+ */
77
+ declare function stripModelNoise(raw: string): string;
78
+ /**
79
+ * Scan an LLM response for every balanced `{…}` object carrying a `"<key>":`
80
+ * entry. Strips fences and `<think>` blocks first. A matching object is
81
+ * skipped over wholesale, so its nested braces don't produce fragment
82
+ * candidates; non-matching objects are descended into, so a match wrapped in
83
+ * an unrelated outer object is still found. `fallback` preserves the legacy
84
+ * behavior for callers with no keyed match: the first balanced object, else
85
+ * the stripped text so a JSON.parse error still surfaces.
86
+ */
87
+ declare function extractObjectsWithKey(raw: string, key: string): {
88
+ matches: string[];
89
+ fallback: {
90
+ json: string;
91
+ balanced: boolean;
92
+ };
93
+ sawBrace: boolean;
94
+ /** An object ran to EOF unclosed — the classic signature of truncated output. */
95
+ sawUnbalanced: boolean;
96
+ };
97
+ /**
98
+ * Pull the JSON object out of an LLM response and report whether it was balanced.
99
+ * Strips fences and `<think>` blocks, then walks every top-level `{…}` and
100
+ * returns the FIRST one that contains a `"tasks"` key — so a brace appearing
101
+ * earlier in reasoning (or an unrelated preamble object) can't make us parse the
102
+ * wrong thing. Falls back to the first balanced object and, failing that, the
103
+ * first `{` onwards so a genuine `JSON.parse` error still surfaces.
104
+ */
105
+ declare function extractObjectWithBalance(raw: string): {
106
+ json: string;
107
+ balanced: boolean;
108
+ sawBrace: boolean;
109
+ };
110
+ /**
111
+ * Pull the JSON object out of an LLM response. Strips markdown code fences and
112
+ * `<think>` blocks, prefers the object containing a `tasks` key, and tolerates a
113
+ * prose preamble and trailing prose. Returns the fence-stripped text unchanged
114
+ * if no `{` is present so the caller's JSON.parse produces a clear failure.
115
+ */
116
+ declare function extractJsonObject(raw: string): string;
117
+ /** Drop trailing commas before a closing `}` or `]` — a common model quirk. */
118
+ declare function stripTrailingCommas(json: string): string;
119
+ /**
120
+ * Escape raw control characters that appear INSIDE string literals — budget
121
+ * models routinely emit multi-line `prompt` strings with literal newlines,
122
+ * which strict JSON.parse rejects ("bad control character"). Characters
123
+ * outside strings (formatting whitespace) are left untouched.
124
+ */
125
+ declare function escapeControlCharsInStrings(json: string): string;
126
+
127
+ /** A task as seen in a still-streaming plan: its title (possibly partial) and whether its object has closed. */
128
+ interface PartialPlanTask {
129
+ title: string;
130
+ status: 'streaming' | 'complete';
131
+ /** Assigned model label, once it has streamed in — for the live row's chip. */
132
+ model?: string;
133
+ /** Task mode ("build"|"plan"), once it has streamed in — for the live row's chip. */
134
+ mode?: string;
135
+ }
136
+ /**
137
+ * Parse a partial (still-streaming) plan-JSON string into an ordered list of task
138
+ * rows for the live progress view. Pure and lenient: it walks the characters of the
139
+ * `tasks` array, emitting one row per task object once it has opened, with the title
140
+ * read incrementally and the status flipping to `complete` when the object's brace
141
+ * closes. The currently-streaming object stays `streaming` even with a partial title.
142
+ * The React view is a thin renderer over this — it never parses JSON itself.
143
+ */
144
+ declare function parsePartialPlan(partial: string): PartialPlanTask[];
145
+
146
+ declare function parsePlanJson(raw: string, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean): Task[];
147
+ /**
148
+ * Whether a reply that failed {@link parsePlanJson} actually LOOKED like a
149
+ * plan attempt — a balanced tasks-keyed object, or JSON that got cut off.
150
+ * Distinguishes "the model tried to emit a plan and botched it" (worth a
151
+ * corrective retry) from prose that merely mentions `"tasks"` (leave alone).
152
+ */
153
+ declare function looksLikePlanAttempt(raw: string): boolean;
154
+ declare function checkUniqueIds(ctx: ValidationContext): ValidationResult;
155
+ declare function checkNoCycles(ctx: ValidationContext): ValidationResult;
156
+ declare function checkDepsResolve(ctx: ValidationContext): ValidationResult;
157
+ declare function checkImmutableLog(ctx: ValidationContext): ValidationResult;
158
+ declare function checkInProgress(ctx: ValidationContext): ValidationResult;
159
+ declare function validatePlanModification(ctx: ValidationContext): ValidationResult;
160
+
161
+ export { type ManifestLookup as M, PLAN_ENVELOPE_KEY as P, type RunnerModeInfo as R, TASK_OPS_ENVELOPE_KEY as T, type PartialPlanTask as a, PlanParseError as b, buildModeGuide as c, checkDepsResolve as d, checkImmutableLog as e, checkInProgress as f, checkNoCycles as g, checkUniqueIds as h, escapeControlCharsInStrings as i, extractJsonObject as j, extractObjectWithBalance as k, extractObjectsWithKey as l, filteredBuildModes as m, looksLikePlanAttempt as n, parsePlanJson as o, parsePartialPlan as p, resolveTaskMode as q, resolveDefaultMode as r, runnerModesFrom as s, stripModelNoise as t, stripTrailingCommas as u, validatePlanModification as v };
@@ -0,0 +1,161 @@
1
+ import { h as RunnerId, s as ValidationContext, t as ValidationResult, T as Task } from './Task-1NwmUImI.mjs';
2
+
3
+ interface RunnerModeInfo {
4
+ id: string;
5
+ label: string;
6
+ description: string;
7
+ autonomous?: boolean;
8
+ safe?: boolean;
9
+ }
10
+ /** The slice of RunnerRegistry this module needs — structural, so nothing here depends on the plugin layer. */
11
+ interface ManifestLookup {
12
+ getManifest(runner: RunnerId): {
13
+ modes?: RunnerModeInfo[];
14
+ } | undefined;
15
+ }
16
+ /**
17
+ * A runner's modes are declared only in its manifest, never through a service,
18
+ * so every caller that needs them fuses registry and runner list by hand. This
19
+ * is that fusion, in one place: the planner prompt, the mode pickers on each
20
+ * surface, and the runner-change retarget all read modes the same way.
21
+ *
22
+ * A runner with no modes maps to `[]` rather than being dropped — callers
23
+ * distinguish "declares no modes" from "not asked about".
24
+ */
25
+ declare function runnerModesFrom(registry: ManifestLookup, runners: RunnerId[]): Record<RunnerId, RunnerModeInfo[]>;
26
+ /**
27
+ * Find the mode ID a runner resolves to under the given toggle state.
28
+ * Tag-based first (autonomous/safe); falls back to positional last non-plan
29
+ * if no tag is present on any mode (degrades gracefully on untagged manifests).
30
+ * Returns undefined if `modes` is empty or undefined.
31
+ */
32
+ declare function resolveDefaultMode(modes: RunnerModeInfo[] | undefined, autonomousDefault?: boolean): string | undefined;
33
+ /**
34
+ * Build modes compatible with the current toggle. Plan is excluded from the
35
+ * build-mode list (it is never a default for implementation tasks). Modes
36
+ * tagged exclusively for the OPPOSITE toggle are hidden — the LLM cannot see
37
+ * or select them. A dual-tagged mode (both autonomous + safe) is shown under
38
+ * either toggle.
39
+ */
40
+ declare function filteredBuildModes(modes: RunnerModeInfo[], autonomousDefault: boolean): RunnerModeInfo[];
41
+ declare function buildModeGuide(runnerModes: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean): string;
42
+ declare function resolveTaskMode(emittedMode: string | undefined, runnerId: RunnerId, runnerModes: Record<RunnerId, RunnerModeInfo[]> | undefined, autonomousDefault?: boolean): string;
43
+
44
+ /** The envelope key a full plan reply is keyed by: `{"tasks":[...]}`. */
45
+ declare const PLAN_ENVELOPE_KEY = "tasks";
46
+ /** The envelope key a targeted-edits reply is keyed by: `{"taskOps":[...]}`. */
47
+ declare const TASK_OPS_ENVELOPE_KEY = "taskOps";
48
+ /** Thrown when an LLM plan response cannot be parsed into a valid plan. Carries the raw text so callers can log it or retry. */
49
+ declare class PlanParseError extends Error {
50
+ readonly raw: string;
51
+ /**
52
+ * True when the reply was cut off mid-object (output-token limit) rather
53
+ * than malformed — the two need different repairs: a truncated emission will
54
+ * be cut at the same point again unless the retry frees context or asks for
55
+ * terser output.
56
+ */
57
+ readonly truncated: boolean;
58
+ /**
59
+ * True when the JSON parsed fine and a *shape* rule rejected it. The generic
60
+ * "could not be parsed as JSON" corrective is a lie for these, so the model
61
+ * re-sends the same object; a semantic rejection must be repaired by naming
62
+ * the rule it broke.
63
+ */
64
+ readonly semantic: boolean;
65
+ constructor(message: string, raw: string, opts?: {
66
+ truncated?: boolean;
67
+ semantic?: boolean;
68
+ });
69
+ }
70
+ /**
71
+ * Strip the noise reasoning models wrap around their answer: markdown code
72
+ * fences and `<think>…</think>` chain-of-thought blocks (which routinely contain
73
+ * stray braces that would otherwise derail brace-balancing). Reasoning captured
74
+ * out-of-band by the service never reaches here, but a model that inlines its
75
+ * thinking in the content channel still must not corrupt parsing.
76
+ */
77
+ declare function stripModelNoise(raw: string): string;
78
+ /**
79
+ * Scan an LLM response for every balanced `{…}` object carrying a `"<key>":`
80
+ * entry. Strips fences and `<think>` blocks first. A matching object is
81
+ * skipped over wholesale, so its nested braces don't produce fragment
82
+ * candidates; non-matching objects are descended into, so a match wrapped in
83
+ * an unrelated outer object is still found. `fallback` preserves the legacy
84
+ * behavior for callers with no keyed match: the first balanced object, else
85
+ * the stripped text so a JSON.parse error still surfaces.
86
+ */
87
+ declare function extractObjectsWithKey(raw: string, key: string): {
88
+ matches: string[];
89
+ fallback: {
90
+ json: string;
91
+ balanced: boolean;
92
+ };
93
+ sawBrace: boolean;
94
+ /** An object ran to EOF unclosed — the classic signature of truncated output. */
95
+ sawUnbalanced: boolean;
96
+ };
97
+ /**
98
+ * Pull the JSON object out of an LLM response and report whether it was balanced.
99
+ * Strips fences and `<think>` blocks, then walks every top-level `{…}` and
100
+ * returns the FIRST one that contains a `"tasks"` key — so a brace appearing
101
+ * earlier in reasoning (or an unrelated preamble object) can't make us parse the
102
+ * wrong thing. Falls back to the first balanced object and, failing that, the
103
+ * first `{` onwards so a genuine `JSON.parse` error still surfaces.
104
+ */
105
+ declare function extractObjectWithBalance(raw: string): {
106
+ json: string;
107
+ balanced: boolean;
108
+ sawBrace: boolean;
109
+ };
110
+ /**
111
+ * Pull the JSON object out of an LLM response. Strips markdown code fences and
112
+ * `<think>` blocks, prefers the object containing a `tasks` key, and tolerates a
113
+ * prose preamble and trailing prose. Returns the fence-stripped text unchanged
114
+ * if no `{` is present so the caller's JSON.parse produces a clear failure.
115
+ */
116
+ declare function extractJsonObject(raw: string): string;
117
+ /** Drop trailing commas before a closing `}` or `]` — a common model quirk. */
118
+ declare function stripTrailingCommas(json: string): string;
119
+ /**
120
+ * Escape raw control characters that appear INSIDE string literals — budget
121
+ * models routinely emit multi-line `prompt` strings with literal newlines,
122
+ * which strict JSON.parse rejects ("bad control character"). Characters
123
+ * outside strings (formatting whitespace) are left untouched.
124
+ */
125
+ declare function escapeControlCharsInStrings(json: string): string;
126
+
127
+ /** A task as seen in a still-streaming plan: its title (possibly partial) and whether its object has closed. */
128
+ interface PartialPlanTask {
129
+ title: string;
130
+ status: 'streaming' | 'complete';
131
+ /** Assigned model label, once it has streamed in — for the live row's chip. */
132
+ model?: string;
133
+ /** Task mode ("build"|"plan"), once it has streamed in — for the live row's chip. */
134
+ mode?: string;
135
+ }
136
+ /**
137
+ * Parse a partial (still-streaming) plan-JSON string into an ordered list of task
138
+ * rows for the live progress view. Pure and lenient: it walks the characters of the
139
+ * `tasks` array, emitting one row per task object once it has opened, with the title
140
+ * read incrementally and the status flipping to `complete` when the object's brace
141
+ * closes. The currently-streaming object stays `streaming` even with a partial title.
142
+ * The React view is a thin renderer over this — it never parses JSON itself.
143
+ */
144
+ declare function parsePartialPlan(partial: string): PartialPlanTask[];
145
+
146
+ declare function parsePlanJson(raw: string, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean): Task[];
147
+ /**
148
+ * Whether a reply that failed {@link parsePlanJson} actually LOOKED like a
149
+ * plan attempt — a balanced tasks-keyed object, or JSON that got cut off.
150
+ * Distinguishes "the model tried to emit a plan and botched it" (worth a
151
+ * corrective retry) from prose that merely mentions `"tasks"` (leave alone).
152
+ */
153
+ declare function looksLikePlanAttempt(raw: string): boolean;
154
+ declare function checkUniqueIds(ctx: ValidationContext): ValidationResult;
155
+ declare function checkNoCycles(ctx: ValidationContext): ValidationResult;
156
+ declare function checkDepsResolve(ctx: ValidationContext): ValidationResult;
157
+ declare function checkImmutableLog(ctx: ValidationContext): ValidationResult;
158
+ declare function checkInProgress(ctx: ValidationContext): ValidationResult;
159
+ declare function validatePlanModification(ctx: ValidationContext): ValidationResult;
160
+
161
+ export { type ManifestLookup as M, PLAN_ENVELOPE_KEY as P, type RunnerModeInfo as R, TASK_OPS_ENVELOPE_KEY as T, type PartialPlanTask as a, PlanParseError as b, buildModeGuide as c, checkDepsResolve as d, checkImmutableLog as e, checkInProgress as f, checkNoCycles as g, checkUniqueIds as h, escapeControlCharsInStrings as i, extractJsonObject as j, extractObjectWithBalance as k, extractObjectsWithKey as l, filteredBuildModes as m, looksLikePlanAttempt as n, parsePlanJson as o, parsePartialPlan as p, resolveTaskMode as q, resolveDefaultMode as r, runnerModesFrom as s, stripModelNoise as t, stripTrailingCommas as u, validatePlanModification as v };
@@ -0,0 +1,2 @@
1
+ export { a as PartialPlanTask, b as PlanParseError, j as extractJsonObject, p as parsePartialPlan, o as parsePlanJson } from './parsing-xpozY5ac.mjs';
2
+ import './Task-1NwmUImI.mjs';
@@ -0,0 +1,2 @@
1
+ export { a as PartialPlanTask, b as PlanParseError, j as extractJsonObject, p as parsePartialPlan, o as parsePlanJson } from './parsing-RjN9JbyG.js';
2
+ import './Task-1NwmUImI.js';