@swissspidy/belay-core 0.1.0 → 0.1.1
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/dist/calibration.d.ts +11 -0
- package/dist/calibration.d.ts.map +1 -0
- package/dist/calibration.js +68 -0
- package/dist/calibration.js.map +1 -0
- package/dist/cloud.d.ts +37 -0
- package/dist/cloud.d.ts.map +1 -0
- package/dist/cloud.js +43 -0
- package/dist/cloud.js.map +1 -0
- package/dist/confidence.d.ts +22 -0
- package/dist/confidence.d.ts.map +1 -0
- package/dist/confidence.js +30 -0
- package/dist/confidence.js.map +1 -0
- package/dist/cost.d.ts +60 -0
- package/dist/cost.d.ts.map +1 -0
- package/dist/cost.js +99 -0
- package/dist/cost.js.map +1 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +16 -0
- package/dist/errors.js.map +1 -0
- package/dist/hash.d.ts +5 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +19 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/schema.d.ts +33 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +174 -0
- package/dist/schema.js.map +1 -0
- package/dist/task.d.ts +7 -0
- package/dist/task.d.ts.map +1 -0
- package/dist/task.js +288 -0
- package/dist/task.js.map +1 -0
- package/dist/types.d.ts +396 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +3 -2
package/dist/schema.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { BelayError } from './errors.js';
|
|
2
|
+
import { canonicalJson, fnv1a } from './hash.js';
|
|
3
|
+
export function normalizeOptions(options) {
|
|
4
|
+
return options.map((o) => (typeof o === 'string' ? { label: o } : { ...o }));
|
|
5
|
+
}
|
|
6
|
+
export function optionLabels(schema) {
|
|
7
|
+
switch (schema.type) {
|
|
8
|
+
case 'binary':
|
|
9
|
+
return ['true', 'false'];
|
|
10
|
+
case 'categorical':
|
|
11
|
+
case 'ordinal':
|
|
12
|
+
return normalizeOptions(schema.options).map((o) => o.label);
|
|
13
|
+
case 'structured':
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** Throws `BelayError('invalid-task')` if the schema is malformed. */
|
|
18
|
+
export function assertValidSchema(schema) {
|
|
19
|
+
const fail = (msg) => {
|
|
20
|
+
throw new BelayError('invalid-task', msg);
|
|
21
|
+
};
|
|
22
|
+
if (!schema || typeof schema !== 'object')
|
|
23
|
+
fail('schema must be an object');
|
|
24
|
+
switch (schema.type) {
|
|
25
|
+
case 'binary':
|
|
26
|
+
if (typeof schema.prompt !== 'string' || !schema.prompt.trim())
|
|
27
|
+
fail('binary schema needs a prompt');
|
|
28
|
+
return;
|
|
29
|
+
case 'categorical':
|
|
30
|
+
case 'ordinal': {
|
|
31
|
+
if (!Array.isArray(schema.options) || schema.options.length < 2) {
|
|
32
|
+
fail(`${schema.type} schema needs at least two options`);
|
|
33
|
+
}
|
|
34
|
+
const labels = optionLabels(schema);
|
|
35
|
+
if (labels.some((l) => typeof l !== 'string' || !l))
|
|
36
|
+
fail('option labels must be non-empty strings');
|
|
37
|
+
if (new Set(labels).size !== labels.length)
|
|
38
|
+
fail('option labels must be unique');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
case 'structured':
|
|
42
|
+
if (!schema.jsonSchema || typeof schema.jsonSchema !== 'object')
|
|
43
|
+
fail('structured schema needs jsonSchema');
|
|
44
|
+
if (typeof schema.validate !== 'function')
|
|
45
|
+
fail('structured schema needs a validate function');
|
|
46
|
+
return;
|
|
47
|
+
default:
|
|
48
|
+
fail(`unknown schema type ${schema.type}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Fingerprint of everything in the schema that influences model behavior (type, prompt,
|
|
53
|
+
* option labels and descriptions, JSON Schema). Stored in calibration files so a task can
|
|
54
|
+
* tell when its calibration was produced for a different schema.
|
|
55
|
+
*/
|
|
56
|
+
export function schemaFingerprint(schema) {
|
|
57
|
+
const { type, prompt } = schema;
|
|
58
|
+
const shape = { type, prompt: prompt ?? null };
|
|
59
|
+
if (schema.type === 'categorical' || schema.type === 'ordinal')
|
|
60
|
+
shape['options'] = normalizeOptions(schema.options);
|
|
61
|
+
if (schema.type === 'structured')
|
|
62
|
+
shape['jsonSchema'] = schema.jsonSchema;
|
|
63
|
+
return `fnv1a:${fnv1a(canonicalJson(shape))}`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* JSON Schema of the output. Non-structured outputs are wrapped as `{ "value": ... }`
|
|
67
|
+
* because many providers require an object at the root.
|
|
68
|
+
*/
|
|
69
|
+
export function toJsonSchema(schema) {
|
|
70
|
+
const wrap = (value) => ({
|
|
71
|
+
type: 'object',
|
|
72
|
+
properties: { value },
|
|
73
|
+
required: ['value'],
|
|
74
|
+
additionalProperties: false,
|
|
75
|
+
});
|
|
76
|
+
switch (schema.type) {
|
|
77
|
+
case 'binary':
|
|
78
|
+
return wrap({ type: 'boolean' });
|
|
79
|
+
case 'categorical':
|
|
80
|
+
case 'ordinal':
|
|
81
|
+
return wrap({ type: 'string', enum: optionLabels(schema) });
|
|
82
|
+
case 'structured':
|
|
83
|
+
return schema.jsonSchema;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** A provider-neutral instruction for cloud runners that build their own prompt from it. */
|
|
87
|
+
export function buildInstruction(schema, context) {
|
|
88
|
+
const lines = [];
|
|
89
|
+
if (context)
|
|
90
|
+
lines.push(context);
|
|
91
|
+
switch (schema.type) {
|
|
92
|
+
case 'binary':
|
|
93
|
+
lines.push(`Answer the question about the input with true or false: ${schema.prompt}`);
|
|
94
|
+
lines.push('Respond with JSON: {"value": true} or {"value": false}.');
|
|
95
|
+
break;
|
|
96
|
+
case 'categorical':
|
|
97
|
+
case 'ordinal': {
|
|
98
|
+
lines.push(schema.prompt ?? 'Classify the input into exactly one of the options.');
|
|
99
|
+
lines.push(schema.type === 'ordinal' ? 'Options, ordered from lowest to highest:' : 'Options:');
|
|
100
|
+
for (const o of normalizeOptions(schema.options)) {
|
|
101
|
+
lines.push(o.description ? `- ${o.label}: ${o.description}` : `- ${o.label}`);
|
|
102
|
+
}
|
|
103
|
+
lines.push('Respond with JSON: {"value": "<one option label>"}.');
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
case 'structured':
|
|
107
|
+
if (schema.prompt)
|
|
108
|
+
lines.push(schema.prompt);
|
|
109
|
+
lines.push('Respond with JSON matching this JSON Schema:');
|
|
110
|
+
lines.push(JSON.stringify(schema.jsonSchema));
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
return lines.join('\n');
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Coerces a runner output into the schema's value type. Accepts the bare value or the
|
|
117
|
+
* `{ value }` wrapper from {@link toJsonSchema}, and JSON strings of either.
|
|
118
|
+
*/
|
|
119
|
+
export function parseValue(schema, raw) {
|
|
120
|
+
const ok = (value) => ({ ok: true, value: value });
|
|
121
|
+
const err = (error) => ({ ok: false, error });
|
|
122
|
+
let candidate = raw;
|
|
123
|
+
if (typeof candidate === 'string' && schema.type === 'structured') {
|
|
124
|
+
try {
|
|
125
|
+
candidate = JSON.parse(candidate);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return err('output is not valid JSON');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (typeof candidate === 'string' && /^\s*\{/.test(candidate)) {
|
|
132
|
+
try {
|
|
133
|
+
candidate = JSON.parse(candidate);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// fall through: treat as a plain string
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (schema.type === 'structured') {
|
|
140
|
+
return schema.validate(candidate) ? ok(candidate) : err('output failed schema validation');
|
|
141
|
+
}
|
|
142
|
+
if (candidate && typeof candidate === 'object' && 'value' in candidate) {
|
|
143
|
+
candidate = candidate.value;
|
|
144
|
+
}
|
|
145
|
+
if (schema.type === 'binary') {
|
|
146
|
+
if (typeof candidate === 'boolean')
|
|
147
|
+
return ok(candidate);
|
|
148
|
+
if (typeof candidate === 'string') {
|
|
149
|
+
const s = candidate.trim().toLowerCase();
|
|
150
|
+
if (s === 'true' || s === 'yes')
|
|
151
|
+
return ok(true);
|
|
152
|
+
if (s === 'false' || s === 'no')
|
|
153
|
+
return ok(false);
|
|
154
|
+
}
|
|
155
|
+
return err(`expected a boolean, got ${JSON.stringify(candidate)}`);
|
|
156
|
+
}
|
|
157
|
+
const labels = optionLabels(schema);
|
|
158
|
+
if (typeof candidate === 'number' && schema.type === 'ordinal')
|
|
159
|
+
candidate = String(candidate);
|
|
160
|
+
if (typeof candidate !== 'string')
|
|
161
|
+
return err(`expected one of ${labels.join(', ')}`);
|
|
162
|
+
if (labels.includes(candidate))
|
|
163
|
+
return ok(candidate);
|
|
164
|
+
const folded = candidate.trim().toLowerCase();
|
|
165
|
+
const match = labels.find((l) => l.toLowerCase() === folded);
|
|
166
|
+
return match !== undefined ? ok(match) : err(`"${candidate}" is not one of ${labels.join(', ')}`);
|
|
167
|
+
}
|
|
168
|
+
/** Label of a value for telemetry and per-label thresholds; `undefined` for structured tasks. */
|
|
169
|
+
export function labelOf(schema, value) {
|
|
170
|
+
if (schema.type === 'structured')
|
|
171
|
+
return undefined;
|
|
172
|
+
return String(value);
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/task.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Task, TaskOptions, TaskSchema } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Defines a task: run locally first, escalate to the cloud runner only when needed.
|
|
4
|
+
* The cascade is specified in docs/adr/0001-public-api-confidence-and-calibration.md.
|
|
5
|
+
*/
|
|
6
|
+
export declare function task<S extends TaskSchema>(options: TaskOptions<S>): Task<S>;
|
|
7
|
+
//# sourceMappingURL=task.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAYV,IAAI,EACJ,WAAW,EACX,UAAU,EAEX,MAAM,YAAY,CAAC;AAapB;;;GAGG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAiS3E"}
|
package/dist/task.js
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { loadCalibration, thresholdFor } from './calibration.js';
|
|
2
|
+
import { combineConfidence } from './confidence.js';
|
|
3
|
+
import { usageParts } from './cost.js';
|
|
4
|
+
import { BelayError, LocalUnavailableError } from './errors.js';
|
|
5
|
+
import { assertValidSchema, buildInstruction, labelOf, parseValue, schemaFingerprint, toJsonSchema } from './schema.js';
|
|
6
|
+
const STRICTNESS = { auto: 0, consent: 1, never: 2 };
|
|
7
|
+
const now = () => globalThis.performance?.now() ?? Date.now();
|
|
8
|
+
class LocalTimeoutError extends Error {
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Defines a task: run locally first, escalate to the cloud runner only when needed.
|
|
12
|
+
* The cascade is specified in docs/adr/0001-public-api-confidence-and-calibration.md.
|
|
13
|
+
*/
|
|
14
|
+
export function task(options) {
|
|
15
|
+
const { name, schema, local, cloud, judge, privacy = {}, localTimeoutMs, onEvent } = options;
|
|
16
|
+
if (!name || typeof name !== 'string')
|
|
17
|
+
throw new BelayError('invalid-task', 'task needs a name');
|
|
18
|
+
assertValidSchema(schema);
|
|
19
|
+
if (!local)
|
|
20
|
+
throw new BelayError('invalid-task', `task "${name}" needs a local runner`);
|
|
21
|
+
if (options.threshold === undefined && options.calibration === undefined) {
|
|
22
|
+
throw new BelayError('invalid-task', `task "${name}" needs a threshold or a calibration`);
|
|
23
|
+
}
|
|
24
|
+
// Above 1, nothing is accepted locally: every run escalates.
|
|
25
|
+
if (options.threshold !== undefined && !(options.threshold >= 0)) {
|
|
26
|
+
throw new BelayError('invalid-task', `task "${name}": threshold must be ≥ 0`);
|
|
27
|
+
}
|
|
28
|
+
if (privacy.escalation === 'consent' && typeof privacy.consent !== 'function') {
|
|
29
|
+
throw new BelayError('invalid-task', `task "${name}": escalation "consent" needs a consent callback`);
|
|
30
|
+
}
|
|
31
|
+
const fingerprint = schemaFingerprint(schema);
|
|
32
|
+
const jsonSchema = toJsonSchema(schema);
|
|
33
|
+
const emit = (event) => {
|
|
34
|
+
try {
|
|
35
|
+
onEvent?.(event);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Telemetry must never break a run.
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const emitError = (stage, err) => {
|
|
42
|
+
emit({ type: 'error', task: name, timestamp: Date.now(), stage, message: err instanceof Error ? err.message : String(err) });
|
|
43
|
+
};
|
|
44
|
+
let thresholdPromise;
|
|
45
|
+
const resolveThreshold = () => {
|
|
46
|
+
thresholdPromise ??= (async () => {
|
|
47
|
+
const fallback = options.threshold;
|
|
48
|
+
if (options.calibration === undefined)
|
|
49
|
+
return { calibration: null, fallback };
|
|
50
|
+
try {
|
|
51
|
+
const calibration = await loadCalibration(options.calibration, name);
|
|
52
|
+
if (calibration.schemaFingerprint !== fingerprint) {
|
|
53
|
+
throw new BelayError('invalid-calibration', `calibration for "${name}" was made for a different schema (${calibration.schemaFingerprint}, expected ${fingerprint}); re-run \`belay calibrate\``);
|
|
54
|
+
}
|
|
55
|
+
return { calibration, fallback };
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
emitError('calibration', err);
|
|
59
|
+
if (fallback === undefined) {
|
|
60
|
+
thresholdPromise = undefined; // allow a retry on the next run
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
return { calibration: null, fallback };
|
|
64
|
+
}
|
|
65
|
+
})();
|
|
66
|
+
return thresholdPromise;
|
|
67
|
+
};
|
|
68
|
+
const thresholdOf = (state, label) => state.calibration ? thresholdFor(state.calibration, label) : state.fallback;
|
|
69
|
+
const contextFor = (runContext) => [options.context, runContext].filter(Boolean).join('\n') || undefined;
|
|
70
|
+
async function run(input, runOptions = {}) {
|
|
71
|
+
const { signal } = runOptions;
|
|
72
|
+
const started = now();
|
|
73
|
+
signal?.throwIfAborted();
|
|
74
|
+
let policy = privacy.escalation ?? 'auto';
|
|
75
|
+
if (runOptions.escalation && STRICTNESS[runOptions.escalation] > STRICTNESS[policy])
|
|
76
|
+
policy = runOptions.escalation;
|
|
77
|
+
if (runOptions.escalation === 'consent' && typeof privacy.consent !== 'function') {
|
|
78
|
+
throw new BelayError('invalid-task', `task "${name}": escalation "consent" needs a consent callback`);
|
|
79
|
+
}
|
|
80
|
+
if (!cloud)
|
|
81
|
+
policy = 'never';
|
|
82
|
+
const thresholdState = await resolveThreshold();
|
|
83
|
+
const context = contextFor(runOptions.context);
|
|
84
|
+
const ctx = { task: name, schema, ...(context ? { context } : {}), ...(signal ? { signal } : {}) };
|
|
85
|
+
// ---- 1. Local attempt -------------------------------------------------
|
|
86
|
+
let reason = null;
|
|
87
|
+
let localResult = null;
|
|
88
|
+
let localConfidence = null;
|
|
89
|
+
let localLatencyMs = null;
|
|
90
|
+
let threshold = thresholdOf(thresholdState);
|
|
91
|
+
const localStarted = now();
|
|
92
|
+
const timeout = new AbortController();
|
|
93
|
+
const localSignal = signal ? AbortSignal.any([signal, timeout.signal]) : timeout.signal;
|
|
94
|
+
let timer;
|
|
95
|
+
try {
|
|
96
|
+
const availability = await local.availability(ctx);
|
|
97
|
+
if (availability !== 'available') {
|
|
98
|
+
reason = 'local-unavailable';
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const runPromise = local.run(input, { ...ctx, signal: localSignal });
|
|
102
|
+
const output = await (localTimeoutMs === undefined
|
|
103
|
+
? runPromise
|
|
104
|
+
: Promise.race([
|
|
105
|
+
runPromise,
|
|
106
|
+
new Promise((_, reject) => {
|
|
107
|
+
timer = setTimeout(() => {
|
|
108
|
+
timeout.abort();
|
|
109
|
+
reject(new LocalTimeoutError(`local runner exceeded ${localTimeoutMs}ms`));
|
|
110
|
+
}, localTimeoutMs);
|
|
111
|
+
}),
|
|
112
|
+
]));
|
|
113
|
+
signal?.throwIfAborted();
|
|
114
|
+
const parsed = parseValue(schema, output.value);
|
|
115
|
+
if (!parsed.ok) {
|
|
116
|
+
reason = 'invalid-output';
|
|
117
|
+
localConfidence = 0;
|
|
118
|
+
// Fixed message: the parse error quotes the rejected output, which must not reach telemetry.
|
|
119
|
+
emitError('local', new Error('local output failed schema validation'));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
const judged = judge ? await judge({ input, value: parsed.value, task: name, ...(signal ? { signal } : {}) }) : undefined;
|
|
123
|
+
const confidence = combineConfidence({ valid: true, runner: output.confidence, judge: judged });
|
|
124
|
+
if (confidence === undefined) {
|
|
125
|
+
throw new BelayError('invalid-task', `task "${name}": local runner "${local.id}" reports no confidence and the task has no judge`);
|
|
126
|
+
}
|
|
127
|
+
localConfidence = confidence;
|
|
128
|
+
localLatencyMs = now() - localStarted;
|
|
129
|
+
localResult = {
|
|
130
|
+
value: parsed.value,
|
|
131
|
+
confidence,
|
|
132
|
+
latencyMs: localLatencyMs,
|
|
133
|
+
...(output.probabilities ? { probabilities: output.probabilities } : {}),
|
|
134
|
+
};
|
|
135
|
+
threshold = thresholdOf(thresholdState, labelOf(schema, parsed.value));
|
|
136
|
+
// The one rule: accept iff confidence >= threshold.
|
|
137
|
+
if (confidence < threshold)
|
|
138
|
+
reason = 'low-confidence';
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
if (signal?.aborted)
|
|
144
|
+
throw signal.reason;
|
|
145
|
+
if (err instanceof BelayError && err.code === 'invalid-task')
|
|
146
|
+
throw err;
|
|
147
|
+
reason =
|
|
148
|
+
err instanceof LocalTimeoutError
|
|
149
|
+
? 'local-timeout'
|
|
150
|
+
: err instanceof LocalUnavailableError
|
|
151
|
+
? 'local-unavailable'
|
|
152
|
+
: 'local-error';
|
|
153
|
+
if (reason !== 'local-unavailable')
|
|
154
|
+
emitError('local', err);
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
if (timer !== undefined)
|
|
158
|
+
clearTimeout(timer);
|
|
159
|
+
}
|
|
160
|
+
localLatencyMs ??= now() - localStarted;
|
|
161
|
+
const finish = (result, cloudLatencyMs, cloudUsage) => {
|
|
162
|
+
const full = {
|
|
163
|
+
...result,
|
|
164
|
+
latencyMs: now() - started,
|
|
165
|
+
threshold,
|
|
166
|
+
escalationReason: reason,
|
|
167
|
+
local: localResult,
|
|
168
|
+
};
|
|
169
|
+
const label = labelOf(schema, full.value);
|
|
170
|
+
emit({
|
|
171
|
+
type: 'run',
|
|
172
|
+
task: name,
|
|
173
|
+
timestamp: Date.now(),
|
|
174
|
+
source: full.source,
|
|
175
|
+
...(label !== undefined ? { label } : {}),
|
|
176
|
+
confidence: full.confidence,
|
|
177
|
+
localConfidence,
|
|
178
|
+
threshold,
|
|
179
|
+
thresholdSource: thresholdState.calibration ? 'calibration' : 'manual',
|
|
180
|
+
calibratedAt: thresholdState.calibration?.createdAt ?? null,
|
|
181
|
+
escalationReason: reason,
|
|
182
|
+
escalationBlocked: full.escalationBlocked,
|
|
183
|
+
latencyMs: full.latencyMs,
|
|
184
|
+
localLatencyMs,
|
|
185
|
+
cloudLatencyMs,
|
|
186
|
+
localRunner: local.id,
|
|
187
|
+
cloudRunner: cloud?.id ?? null,
|
|
188
|
+
...(cloudUsage ? { cloudUsage: usageParts(cloudUsage) } : {}),
|
|
189
|
+
});
|
|
190
|
+
return full;
|
|
191
|
+
};
|
|
192
|
+
const fallBackToLocal = (blocked, cause) => {
|
|
193
|
+
if (!localResult) {
|
|
194
|
+
const why = blocked === 'policy' ? 'escalation is disabled' : blocked === 'consent-denied' ? 'consent was denied' : 'the cloud runner failed';
|
|
195
|
+
throw new BelayError('no-result', `task "${name}": no local result (${reason}) and ${why}`, { cause });
|
|
196
|
+
}
|
|
197
|
+
return finish({ value: localResult.value, confidence: localResult.confidence, source: 'local', escalationBlocked: blocked }, null);
|
|
198
|
+
};
|
|
199
|
+
if (reason === null) {
|
|
200
|
+
return finish({ value: localResult.value, confidence: localResult.confidence, source: 'local', escalationBlocked: null }, null);
|
|
201
|
+
}
|
|
202
|
+
// ---- 2. Escalation gate -----------------------------------------------
|
|
203
|
+
if (policy === 'never' || !cloud)
|
|
204
|
+
return fallBackToLocal('policy');
|
|
205
|
+
let cloudInput = input;
|
|
206
|
+
if (privacy.redact) {
|
|
207
|
+
try {
|
|
208
|
+
cloudInput = await privacy.redact(input);
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
// Failing closed: never send unredacted input.
|
|
212
|
+
emitError('redact', err);
|
|
213
|
+
return fallBackToLocal('policy', err);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
signal?.throwIfAborted();
|
|
217
|
+
const localSummary = localResult ? { value: localResult.value, confidence: localResult.confidence } : null;
|
|
218
|
+
if (policy === 'consent') {
|
|
219
|
+
let granted = false;
|
|
220
|
+
try {
|
|
221
|
+
granted = (await privacy.consent({ task: name, reason, input: cloudInput, local: localSummary })) === true;
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
emitError('consent', err);
|
|
225
|
+
}
|
|
226
|
+
signal?.throwIfAborted();
|
|
227
|
+
if (!granted)
|
|
228
|
+
return fallBackToLocal('consent-denied');
|
|
229
|
+
}
|
|
230
|
+
// ---- 3. Cloud ----------------------------------------------------------
|
|
231
|
+
const cloudStarted = now();
|
|
232
|
+
try {
|
|
233
|
+
const output = await cloud.run({
|
|
234
|
+
task: name,
|
|
235
|
+
schema,
|
|
236
|
+
jsonSchema,
|
|
237
|
+
instruction: buildInstruction(schema, context),
|
|
238
|
+
input: cloudInput,
|
|
239
|
+
...(context ? { context } : {}),
|
|
240
|
+
...(localSummary ? { local: localSummary } : {}),
|
|
241
|
+
}, signal ? { signal } : {});
|
|
242
|
+
signal?.throwIfAborted();
|
|
243
|
+
const parsed = parseValue(schema, output.value);
|
|
244
|
+
if (!parsed.ok)
|
|
245
|
+
throw new BelayError('cloud-invalid-output', `task "${name}": cloud output failed schema validation`);
|
|
246
|
+
return finish({
|
|
247
|
+
value: parsed.value,
|
|
248
|
+
confidence: typeof output.confidence === 'number' ? output.confidence : null,
|
|
249
|
+
source: 'cloud',
|
|
250
|
+
escalationBlocked: null,
|
|
251
|
+
}, now() - cloudStarted, output.usage);
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
if (signal?.aborted)
|
|
255
|
+
throw signal.reason;
|
|
256
|
+
emitError('cloud', err);
|
|
257
|
+
if (localResult)
|
|
258
|
+
return fallBackToLocal('cloud-error', err);
|
|
259
|
+
if (err instanceof BelayError)
|
|
260
|
+
throw err;
|
|
261
|
+
throw new BelayError('cloud-error', `task "${name}": cloud runner failed`, { cause: err });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
name,
|
|
266
|
+
schema,
|
|
267
|
+
run,
|
|
268
|
+
async availability() {
|
|
269
|
+
const state = await local.availability({ task: name, schema, ...(options.context ? { context: options.context } : {}) });
|
|
270
|
+
// A judge that is not ready makes the local path unusable too: report the less ready of the two.
|
|
271
|
+
if (state !== 'available' || !judge?.availability)
|
|
272
|
+
return state;
|
|
273
|
+
return judge.availability();
|
|
274
|
+
},
|
|
275
|
+
async prepare(prepareOptions) {
|
|
276
|
+
await local.prepare?.({ task: name, schema, ...(options.context ? { context: options.context } : {}) }, prepareOptions);
|
|
277
|
+
await judge?.prepare?.(prepareOptions);
|
|
278
|
+
},
|
|
279
|
+
async threshold() {
|
|
280
|
+
return thresholdOf(await resolveThreshold());
|
|
281
|
+
},
|
|
282
|
+
destroy() {
|
|
283
|
+
local.destroy?.();
|
|
284
|
+
judge?.destroy?.();
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=task.js.map
|
package/dist/task.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"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"}
|