@studio-foundation/ralph 0.4.0-beta → 0.5.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 +1 -1
- package/dist/loop.d.ts +7 -0
- package/dist/loop.d.ts.map +1 -1
- package/dist/loop.js +8 -2
- package/dist/loop.js.map +1 -1
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +100 -9
- package/dist/validator.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @studio-foundation/ralph
|
|
2
2
|
|
|
3
|
-
**Studio** is
|
|
3
|
+
**Studio** is a declarative YAML runtime for AI agents. It orchestrates multi-stage agent workflows with structured output validation and automatic retry. This package is **ralph**: the retry engine. Execute → validate → retry with escalated feedback → repeat, until success or max attempts is reached.
|
|
4
4
|
|
|
5
5
|
**RALPH** = Recursive Automated Loop for Persistent Handling.
|
|
6
6
|
|
package/dist/loop.d.ts
CHANGED
|
@@ -20,6 +20,13 @@ export interface RalphConfig<T> {
|
|
|
20
20
|
onRetry?: (event: RetryEvent<T>) => void | Promise<void>;
|
|
21
21
|
onSuccess?: (result: T, attempts: number) => void | Promise<void>;
|
|
22
22
|
onExhausted?: (lastResult: T, allFailures: string[]) => void | Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Predicate marking a failed result as deterministic — one that a retry
|
|
25
|
+
* cannot fix (e.g. a script process that crashed at startup). When it returns
|
|
26
|
+
* true for a result that failed validation, the loop stops immediately
|
|
27
|
+
* instead of burning the remaining attempts. Success is never re-checked.
|
|
28
|
+
*/
|
|
29
|
+
isFatal?: (result: T) => boolean;
|
|
23
30
|
signal?: AbortSignal;
|
|
24
31
|
}
|
|
25
32
|
export type RalphResult<T> = {
|
package/dist/loop.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,CAAC,CAAC;IACV,UAAU,EAAE,gBAAgB,CAAC;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACpD,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,IACrB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9D,wBAAsB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,CAAC,CAAC;IACV,UAAU,EAAE,gBAAgB,CAAC;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACpD,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;IACjC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,IACrB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9D,wBAAsB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAiF9E"}
|
package/dist/loop.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export async function ralph(config) {
|
|
2
|
-
const { executor, validator, maxAttempts, retryStrategy, onRetry, onSuccess, onExhausted, signal } = config;
|
|
2
|
+
const { executor, validator, maxAttempts, retryStrategy, onRetry, onSuccess, onExhausted, isFatal, signal } = config;
|
|
3
3
|
let attempt = 1;
|
|
4
4
|
const allFailures = [];
|
|
5
5
|
let lastResult;
|
|
@@ -34,7 +34,13 @@ export async function ralph(config) {
|
|
|
34
34
|
}
|
|
35
35
|
// 4. Si invalide → accumuler erreurs
|
|
36
36
|
allFailures.push(...validation.errors);
|
|
37
|
-
// 5.
|
|
37
|
+
// 5. Deterministic failure → stop now, don't burn the remaining attempts.
|
|
38
|
+
// A crashed startup won't heal on attempt 2/3.
|
|
39
|
+
if (isFatal?.(result)) {
|
|
40
|
+
await onExhausted?.(result, allFailures);
|
|
41
|
+
return { status: 'exhausted', lastResult: result, attempts: attempt, failures: allFailures };
|
|
42
|
+
}
|
|
43
|
+
// 6. Si dernière tentative → EXHAUSTED
|
|
38
44
|
if (attempt >= maxAttempts) {
|
|
39
45
|
await onExhausted?.(result, allFailures);
|
|
40
46
|
return { status: 'exhausted', lastResult: result, attempts: attempt, failures: allFailures };
|
package/dist/loop.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"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"}
|
package/dist/validator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAwB,QAAQ,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAE3I,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAEvF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,QAAQ,EAAE,CAAC;CACxB;AAwFD,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,GAAG,gBAAgB,CA0C1F;AAMD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,CAAC,EAAE,oBAAoB,GAAG,gBAAgB,CA4B9G;AAOD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,CAAC,EAAE,oBAAoB,GAAG,gBAAgB,CAkBlH;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,CAAC,EAAE,oBAAoB,GAAG,gBAAgB,CAmBjH;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,CAAC,EAAE,oBAAoB,GAAG,gBAAgB,CAoB/G;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAYtE"}
|
package/dist/validator.js
CHANGED
|
@@ -1,21 +1,112 @@
|
|
|
1
|
+
/** Human-readable JSON type of a runtime value, for error messages. */
|
|
2
|
+
function describeType(value) {
|
|
3
|
+
if (value === null)
|
|
4
|
+
return 'null';
|
|
5
|
+
if (Array.isArray(value))
|
|
6
|
+
return 'array';
|
|
7
|
+
return typeof value;
|
|
8
|
+
}
|
|
9
|
+
/** Does `value` match the declared field `type`? */
|
|
10
|
+
function matchesType(value, type) {
|
|
11
|
+
switch (type) {
|
|
12
|
+
case 'string':
|
|
13
|
+
return typeof value === 'string';
|
|
14
|
+
case 'number':
|
|
15
|
+
return typeof value === 'number' && !Number.isNaN(value);
|
|
16
|
+
case 'integer':
|
|
17
|
+
return typeof value === 'number' && Number.isInteger(value);
|
|
18
|
+
case 'boolean':
|
|
19
|
+
return typeof value === 'boolean';
|
|
20
|
+
case 'object':
|
|
21
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
22
|
+
case 'array':
|
|
23
|
+
return Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The type a spec effectively requires. An explicit `type` wins; otherwise it's
|
|
28
|
+
* inferred from structural keys so that `items` implies array and
|
|
29
|
+
* `required_fields`/`fields` imply object. This makes the nested checks below
|
|
30
|
+
* safe: if the effective type is enforced, the runtime shape is guaranteed.
|
|
31
|
+
*/
|
|
32
|
+
function effectiveType(spec) {
|
|
33
|
+
if (spec.type)
|
|
34
|
+
return spec.type;
|
|
35
|
+
if (spec.items)
|
|
36
|
+
return 'array';
|
|
37
|
+
if (spec.required_fields || spec.fields)
|
|
38
|
+
return 'object';
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validate a single field value against its spec, accumulating errors with a
|
|
43
|
+
* dotted/indexed `path` (e.g. `pages[2].importance`) so failures point at the
|
|
44
|
+
* exact location. Recurses into object fields and array items.
|
|
45
|
+
*/
|
|
46
|
+
function validateField(value, spec, path, errors) {
|
|
47
|
+
const type = effectiveType(spec);
|
|
48
|
+
// Type gate — on mismatch, stop: enum/nested checks assume the type held.
|
|
49
|
+
if (type && !matchesType(value, type)) {
|
|
50
|
+
errors.push(`Field '${path}' must be ${type}, got ${describeType(value)}`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Enumeration — value must be one of the allowed literals.
|
|
54
|
+
if (spec.enum && spec.enum.length > 0 && !spec.enum.some((allowed) => allowed === value)) {
|
|
55
|
+
errors.push(`Field '${path}' must be one of [${spec.enum.join(', ')}], got ${JSON.stringify(value)}`);
|
|
56
|
+
}
|
|
57
|
+
// Nested object: required sub-fields and per-field specs.
|
|
58
|
+
if ((spec.required_fields || spec.fields) && matchesType(value, 'object')) {
|
|
59
|
+
const obj = value;
|
|
60
|
+
if (spec.required_fields) {
|
|
61
|
+
for (const field of spec.required_fields) {
|
|
62
|
+
if (!(field in obj)) {
|
|
63
|
+
errors.push(`Missing required field: ${path}.${field}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (spec.fields) {
|
|
68
|
+
for (const [name, childSpec] of Object.entries(spec.fields)) {
|
|
69
|
+
if (name in obj) {
|
|
70
|
+
validateField(obj[name], childSpec, `${path}.${name}`, errors);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Array items: every element must satisfy the item spec.
|
|
76
|
+
if (spec.items && Array.isArray(value)) {
|
|
77
|
+
value.forEach((item, index) => {
|
|
78
|
+
validateField(item, spec.items, `${path}[${index}]`, errors);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
1
82
|
export function validateSchema(output, contract) {
|
|
2
83
|
const errors = [];
|
|
3
84
|
const warnings = [];
|
|
4
|
-
|
|
5
|
-
|
|
85
|
+
const schema = contract.schema;
|
|
86
|
+
// Nothing to check without required_fields or field specs.
|
|
87
|
+
if (!schema || (!schema.required_fields && !schema.fields)) {
|
|
6
88
|
return { valid: true, errors, warnings };
|
|
7
89
|
}
|
|
8
|
-
const requiredFields = contract.schema.required_fields;
|
|
9
90
|
// Output must be an object to check fields
|
|
10
|
-
if (output === null || typeof output !== 'object') {
|
|
11
|
-
errors.push(`Expected object output, got ${output
|
|
91
|
+
if (output === null || typeof output !== 'object' || Array.isArray(output)) {
|
|
92
|
+
errors.push(`Expected object output, got ${describeType(output)}`);
|
|
12
93
|
return { valid: false, errors, warnings };
|
|
13
94
|
}
|
|
14
95
|
const outputObj = output;
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
96
|
+
// Top-level presence check (required_fields)
|
|
97
|
+
if (schema.required_fields) {
|
|
98
|
+
for (const field of schema.required_fields) {
|
|
99
|
+
if (!(field in outputObj)) {
|
|
100
|
+
errors.push(`Missing required field: ${field}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Field-level shape check (type / enum / nested) — only for present fields.
|
|
105
|
+
if (schema.fields) {
|
|
106
|
+
for (const [name, spec] of Object.entries(schema.fields)) {
|
|
107
|
+
if (name in outputObj) {
|
|
108
|
+
validateField(outputObj[name], spec, name, errors);
|
|
109
|
+
}
|
|
19
110
|
}
|
|
20
111
|
}
|
|
21
112
|
return {
|
package/dist/validator.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAYA,MAAM,
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@studio-foundation/ralph",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.5.2",
|
|
4
|
+
"description": "Retry loop: execute, validate, retry with escalating feedback. The R in RALPH. Used by Studio.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"license": "AGPL-3.0-only",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"js-yaml": "^4.1.1",
|
|
27
|
-
"@studio-foundation/contracts": "0.
|
|
27
|
+
"@studio-foundation/contracts": "0.5.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/js-yaml": "^4.0.9",
|