@sensigo/realm 0.39.0 → 0.41.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 (57) hide show
  1. package/dist/engine/apply-resume.d.ts.map +1 -1
  2. package/dist/engine/apply-resume.js +5 -1
  3. package/dist/engine/apply-resume.js.map +1 -1
  4. package/dist/engine/execution-loop.d.ts.map +1 -1
  5. package/dist/engine/execution-loop.js +8 -3
  6. package/dist/engine/execution-loop.js.map +1 -1
  7. package/dist/engine/run-health.d.ts +1 -1
  8. package/dist/engine/run-health.d.ts.map +1 -1
  9. package/dist/engine/run-health.js +89 -0
  10. package/dist/engine/run-health.js.map +1 -1
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/store/failed-attempt-store.d.ts +9 -1
  16. package/dist/store/failed-attempt-store.d.ts.map +1 -1
  17. package/dist/store/failed-attempt-store.js +12 -1
  18. package/dist/store/failed-attempt-store.js.map +1 -1
  19. package/dist/store/json-file-store.d.ts +19 -2
  20. package/dist/store/json-file-store.d.ts.map +1 -1
  21. package/dist/store/json-file-store.js +57 -5
  22. package/dist/store/json-file-store.js.map +1 -1
  23. package/dist/store/per-run-artifact-store.d.ts +42 -1
  24. package/dist/store/per-run-artifact-store.d.ts.map +1 -1
  25. package/dist/store/trace-buffer-store.d.ts +32 -6
  26. package/dist/store/trace-buffer-store.d.ts.map +1 -1
  27. package/dist/store/trace-buffer-store.js +39 -6
  28. package/dist/store/trace-buffer-store.js.map +1 -1
  29. package/dist/types/response-envelope.d.ts +0 -1
  30. package/dist/types/response-envelope.d.ts.map +1 -1
  31. package/dist/types/run-record.d.ts +78 -0
  32. package/dist/types/run-record.d.ts.map +1 -1
  33. package/dist/types/workflow-definition.d.ts +11 -1
  34. package/dist/types/workflow-definition.d.ts.map +1 -1
  35. package/dist/types/workflow-definition.js +1 -0
  36. package/dist/types/workflow-definition.js.map +1 -1
  37. package/dist/types/workflow-error.d.ts +44 -0
  38. package/dist/types/workflow-error.d.ts.map +1 -1
  39. package/dist/types/workflow-error.js +30 -1
  40. package/dist/types/workflow-error.js.map +1 -1
  41. package/dist/workflow/diagnostics.d.ts +51 -13
  42. package/dist/workflow/diagnostics.d.ts.map +1 -1
  43. package/dist/workflow/diagnostics.js +50 -32
  44. package/dist/workflow/diagnostics.js.map +1 -1
  45. package/dist/workflow/registrar.d.ts +26 -0
  46. package/dist/workflow/registrar.d.ts.map +1 -1
  47. package/dist/workflow/registrar.js +35 -5
  48. package/dist/workflow/registrar.js.map +1 -1
  49. package/dist/workflow/source-positions.d.ts +39 -0
  50. package/dist/workflow/source-positions.d.ts.map +1 -0
  51. package/dist/workflow/source-positions.js +107 -0
  52. package/dist/workflow/source-positions.js.map +1 -0
  53. package/dist/workflow/yaml-loader.d.ts +17 -0
  54. package/dist/workflow/yaml-loader.d.ts.map +1 -1
  55. package/dist/workflow/yaml-loader.js +1386 -1087
  56. package/dist/workflow/yaml-loader.js.map +1 -1
  57. package/package.json +1 -1
@@ -0,0 +1,39 @@
1
+ import type { State } from 'js-yaml';
2
+ /**
3
+ * Where a key sits in the source. 1-based. `endColumn` is exclusive — one past the last character
4
+ * (the editor convention); all other bounds inclusive.
5
+ */
6
+ export interface SourcePosition {
7
+ line: number;
8
+ column: number;
9
+ endLine: number;
10
+ endColumn: number;
11
+ }
12
+ /**
13
+ * Resolves a semantic path to its position in the source, or `undefined` if it cannot.
14
+ *
15
+ * The path is a SEQUENCE OF SEGMENTS — `['steps', 'my_step', 'execution']` — never a joined
16
+ * string, and that is a correctness requirement rather than a style preference. A dotted path
17
+ * aliases: a step literally named `a.b` and a field `b` on a step named `a` both flatten to
18
+ * `steps.a.b`, and last-write-wins hands one of them the OTHER's line. That is lawful YAML
19
+ * producing a confidently wrong position — the one outcome this module exists to make impossible.
20
+ *
21
+ * No separator fixes it. NUL does not: js-yaml parses `"a\0b"` into a key that CONTAINS a literal
22
+ * NUL, so a NUL-join aliases exactly as the dot did. There is no character a YAML key cannot hold,
23
+ * so only structure can carry the distinction.
24
+ */
25
+ export interface SourcePositionMap {
26
+ posOf(segments: readonly string[]): SourcePosition | undefined;
27
+ }
28
+ /** A map that resolves nothing — for callers with no source text to map against. */
29
+ export declare function emptySourcePositionMap(): SourcePositionMap;
30
+ /**
31
+ * Collects positions during a parse. Create one, hand `listener` to `yaml.load`, then call
32
+ * `finish()`. One instance per parse — there is no module state, so concurrent loads cannot see
33
+ * each other's positions.
34
+ */
35
+ export declare function createSourcePositionCollector(): {
36
+ listener: (event: 'open' | 'close', state: State) => void;
37
+ finish: () => SourcePositionMap;
38
+ };
39
+ //# sourceMappingURL=source-positions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-positions.d.ts","sourceRoot":"","sources":["../../src/workflow/source-positions.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,GAAG,SAAS,CAAC;CAChE;AAgCD,oFAAoF;AACpF,wBAAgB,sBAAsB,IAAI,iBAAiB,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI;IAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC1D,MAAM,EAAE,MAAM,iBAAiB,CAAC;CACjC,CA0CA"}
@@ -0,0 +1,107 @@
1
+ const EMPTY_MAP = { posOf: () => undefined };
2
+ /**
3
+ * The map's internal key. `JSON.stringify` of a string array is injective — the escaping is
4
+ * deterministic and the array brackets/commas are part of the encoding — so two different segment
5
+ * sequences can never produce the same key. `['a.b']` encodes as `["a.b"]` and `['a','b']` as
6
+ * `["a","b"]`; there is no input that collapses them.
7
+ */
8
+ function keyOf(segments) {
9
+ return JSON.stringify(segments);
10
+ }
11
+ /** A map that resolves nothing — for callers with no source text to map against. */
12
+ export function emptySourcePositionMap() {
13
+ return EMPTY_MAP;
14
+ }
15
+ /**
16
+ * Collects positions during a parse. Create one, hand `listener` to `yaml.load`, then call
17
+ * `finish()`. One instance per parse — there is no module state, so concurrent loads cannot see
18
+ * each other's positions.
19
+ */
20
+ export function createSourcePositionCollector() {
21
+ // The root frame is a container for whatever closes at the top level; the document's own node
22
+ // lands in its children.
23
+ const stack = [{ startLine: 0, startColumn: 0, children: [] }];
24
+ return {
25
+ listener(event, state) {
26
+ if (event === 'open') {
27
+ stack.push({
28
+ startLine: state.line,
29
+ startColumn: state.position - state.lineStart,
30
+ children: [],
31
+ });
32
+ return;
33
+ }
34
+ // A close with nothing open would mean the stream is not balanced. It is, on every input
35
+ // this parser accepts — but if it ever were not, dropping the event is the behaviour that
36
+ // preserves the invariant.
37
+ if (stack.length <= 1)
38
+ return;
39
+ const frame = stack.pop();
40
+ const parent = stack[stack.length - 1];
41
+ parent.children.push({
42
+ kind: state.kind,
43
+ result: state.result,
44
+ startLine: frame.startLine,
45
+ startColumn: frame.startColumn,
46
+ endLine: state.line,
47
+ endColumn: state.position - state.lineStart,
48
+ children: frame.children,
49
+ });
50
+ },
51
+ finish() {
52
+ const positions = new Map();
53
+ // The document node is the last thing to close at the top level.
54
+ const root = stack[0]?.children[stack[0].children.length - 1];
55
+ if (root !== undefined)
56
+ collect(root, [], positions);
57
+ return {
58
+ posOf: (segments) => positions.get(keyOf(segments)),
59
+ };
60
+ },
61
+ };
62
+ }
63
+ /**
64
+ * Walks a mapping and records one position per key, then descends.
65
+ *
66
+ * THE STRICT PAIRING RULE. A block mapping's immediate children arrive as key, value, key, value
67
+ * — so `children.length` must be exactly twice the key count, and each even child must BE the
68
+ * corresponding key. Anything else means this node's children do not line up with its keys the
69
+ * way they normally do: a flow mapping with a valueless key, a merge key that expanded, an anchor
70
+ * replayed from elsewhere in the document. In every one of those the positions would be off by
71
+ * some amount that is not knowable from here.
72
+ *
73
+ * So on any mismatch this records NOTHING for the whole mapping — not a best guess for the keys
74
+ * that happened to line up. That is the absent-never-wrong invariant, and it is deliberately
75
+ * blunt: the cost is a missing line number on an exotic shape, and the alternative is a confident
76
+ * wrong one on the same shape.
77
+ */
78
+ function collect(node, path, into) {
79
+ // Only structural nodes are walked. Anchor replays surface as events nested inside scalars,
80
+ // which have no keys to map and are never descended into.
81
+ if (node.kind !== 'mapping')
82
+ return;
83
+ if (typeof node.result !== 'object' || node.result === null || Array.isArray(node.result))
84
+ return;
85
+ const keys = Object.keys(node.result);
86
+ if (node.children.length !== 2 * keys.length)
87
+ return;
88
+ for (let i = 0; i < keys.length; i++) {
89
+ if (node.children[2 * i].result !== keys[i])
90
+ return;
91
+ }
92
+ for (let i = 0; i < keys.length; i++) {
93
+ const keyNode = node.children[2 * i];
94
+ const valueNode = node.children[2 * i + 1];
95
+ const childPath = [...path, keys[i]];
96
+ // +1 on every coordinate: this is the ONE place 0-based parser state becomes 1-based
97
+ // human/agent coordinates.
98
+ into.set(keyOf(childPath), {
99
+ line: keyNode.startLine + 1,
100
+ column: keyNode.startColumn + 1,
101
+ endLine: keyNode.endLine + 1,
102
+ endColumn: keyNode.endColumn + 1,
103
+ });
104
+ collect(valueNode, childPath, into);
105
+ }
106
+ }
107
+ //# sourceMappingURL=source-positions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-positions.js","sourceRoot":"","sources":["../../src/workflow/source-positions.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { WorkflowDefinition } from '../types/workflow-definition.js';
2
+ import { WorkflowError } from '../types/workflow-error.js';
2
3
  import { type LoaderWarning } from './diagnostics.js';
3
4
  import type { ExtensionRegistry } from '../extensions/registry.js';
4
5
  /** Bumped on every breaking change to WorkflowDefinition's serialized format. */
@@ -12,6 +13,22 @@ export declare const CURRENT_WORKFLOW_SCHEMA_VERSION = 1;
12
13
  * Pure `package.json`/`.git` walk — zero manifest knowledge.
13
14
  */
14
15
  export declare function findTrustRoot(dir: string): string;
16
+ /**
17
+ * issue #424 — attaches the live loader warnings to an error on its way out.
18
+ *
19
+ * Two chokepoints call this (one in `parseWorkflowString`, one in `loadWorkflowFromFileCore`),
20
+ * which is why it exists rather than each throw site building its own error with a `warnings`
21
+ * option: there are eleven throw sites across this file plus four more in template-resolver.ts,
22
+ * the warnings array is out of scope at most of them, and a chokepoint covers every future one
23
+ * for free. The non-empty guard makes the classification automatic — a throw that happens before
24
+ * any warning could exist attaches nothing, by construction rather than by a rule someone has to
25
+ * remember.
26
+ *
27
+ * Attach-once: an inner chokepoint's attachment survives the outer one re-catching the same
28
+ * error, so a file-based load reports the warnings from the parse that produced it rather than
29
+ * an emptier outer set.
30
+ */
31
+ export declare function attachLoaderWarnings(err: WorkflowError, warnings: readonly LoaderWarning[]): void;
15
32
  /**
16
33
  * Loads a WorkflowDefinition from a YAML file on disk. UNCHANGED signature/return type — the
17
34
  * non-breaking invariant (issue #169): every existing execution caller keeps compiling and
@@ -1 +1 @@
1
- {"version":3,"file":"yaml-loader.d.ts","sourceRoot":"","sources":["../../src/workflow/yaml-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,kBAAkB,EAInB,MAAM,iCAAiC,CAAC;AAQzC,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAyKnE,iFAAiF;AACjF,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAkFjD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUjD;AA4JD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,kBAAkB,CAIpB;AAED;;;;GAIG;AACH,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B;IAAE,UAAU,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,CAE/D;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,kBAAkB,CAMpB;AAED;;;GAGG;AACH,wBAAgB,qCAAqC,CACnD,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,iBAAiB,GAC3B;IAAE,UAAU,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,CAE/D"}
1
+ {"version":3,"file":"yaml-loader.d.ts","sourceRoot":"","sources":["../../src/workflow/yaml-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,kBAAkB,EAInB,MAAM,iCAAiC,CAAC;AAOzC,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAsOnE,iFAAiF;AACjF,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAkFjD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUjD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAIjG;AA8KD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,kBAAkB,CAIpB;AAED;;;;GAIG;AACH,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B;IAAE,UAAU,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,CAE/D;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,kBAAkB,CAMpB;AAED;;;GAGG;AACH,wBAAgB,qCAAqC,CACnD,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,iBAAiB,GAC3B;IAAE,UAAU,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,CAE/D"}