@orkestrel/study 0.0.2 → 0.0.3
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/src/core/index.cjs +61 -16
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +67 -8
- package/dist/src/core/index.d.ts +67 -8
- package/dist/src/core/index.js +61 -18
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +2879 -928
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +874 -15
- package/dist/src/server/index.d.ts +874 -15
- package/dist/src/server/index.js +2838 -934
- package/dist/src/server/index.js.map +1 -1
- package/package.json +5 -5
package/dist/src/core/index.cjs
CHANGED
|
@@ -8,8 +8,8 @@ let _orkestrel_abort = require("@orkestrel/abort");
|
|
|
8
8
|
* Keys the own self-identity every study error stamps on itself.
|
|
9
9
|
* @remarks
|
|
10
10
|
* The global symbol registry lets every package, ESM, CommonJS and captured copy read the same
|
|
11
|
-
* key. The registry makes the key discoverable; it
|
|
12
|
-
*
|
|
11
|
+
* key. The registry makes the key discoverable; it recognizes the contract without proving
|
|
12
|
+
* its origin.
|
|
13
13
|
*/
|
|
14
14
|
var STUDY_ERROR_BRAND = Symbol.for("@orkestrel/study.error");
|
|
15
15
|
/** Caps a declared trial population before schedule allocation. */
|
|
@@ -24,6 +24,7 @@ var STUDY_ROLES = Object.freeze([
|
|
|
24
24
|
"judge",
|
|
25
25
|
"summary",
|
|
26
26
|
"metadata",
|
|
27
|
+
"maintenance",
|
|
27
28
|
"tool"
|
|
28
29
|
]);
|
|
29
30
|
/** Lists every ceiling a run can stop at in report order. */
|
|
@@ -67,16 +68,18 @@ function omitStudyAbsent(value) {
|
|
|
67
68
|
* ```
|
|
68
69
|
*/
|
|
69
70
|
function normalizeStudyProfile(profile) {
|
|
70
|
-
const { provider, qualification, settings, room, ...required } = profile;
|
|
71
|
+
const { provider, qualification, settings, record, room, ...required } = profile;
|
|
71
72
|
return {
|
|
72
73
|
...required,
|
|
73
74
|
room: omitStudyAbsent(room),
|
|
74
75
|
...provider === void 0 ? {} : { provider: {
|
|
75
76
|
...omitStudyAbsent(provider),
|
|
76
|
-
digest: omitStudyAbsent(provider.digest)
|
|
77
|
+
digest: omitStudyAbsent(provider.digest),
|
|
78
|
+
...provider.daemon === void 0 ? {} : { daemon: omitStudyAbsent(provider.daemon) }
|
|
77
79
|
} },
|
|
78
80
|
...qualification === void 0 ? {} : { qualification },
|
|
79
|
-
...settings === void 0 ? {} : { settings }
|
|
81
|
+
...settings === void 0 ? {} : { settings },
|
|
82
|
+
...record === void 0 ? {} : { record }
|
|
80
83
|
};
|
|
81
84
|
}
|
|
82
85
|
/**
|
|
@@ -418,15 +421,46 @@ function isStudyProvider(value) {
|
|
|
418
421
|
"url",
|
|
419
422
|
"model",
|
|
420
423
|
"digest"
|
|
421
|
-
], ["judge"]) || ![
|
|
424
|
+
], ["judge", "daemon"]) || ![
|
|
422
425
|
"entry",
|
|
423
426
|
"url",
|
|
424
427
|
"model"
|
|
425
428
|
].every((key) => (0, _orkestrel_contract.isNonEmptyString)(value[key])) || typeof value.url !== "string" || !(0, _orkestrel_contract.isRecord)(value.digest) || !matchesStudyKeys(value.digest, ["model"], ["judge"]) || !isStudyDigest(value.digest.model) || value.judge === void 0 !== (value.digest.judge === void 0) || value.judge !== void 0 && (!(0, _orkestrel_contract.isNonEmptyString)(value.judge) || !isStudyDigest(value.digest.judge))) return false;
|
|
426
429
|
const url = new URL(value.url);
|
|
430
|
+
if (value.daemon !== void 0) {
|
|
431
|
+
if (!isStudyDaemon(value.daemon) || !/^http:\/\/127\.0\.0\.1:[0-9]+\/?$/.test(value.url) || Number(url.port) <= 0 || Number(url.port) === 11434) return false;
|
|
432
|
+
const daemon = value.daemon;
|
|
433
|
+
const digest = value.digest;
|
|
434
|
+
if (!daemon.models.every((model) => model.name === value.model && model.digest === digest.model || value.judge !== void 0 && model.name === value.judge && model.digest === digest.judge) || !daemon.models.some((model) => model.name === value.model && model.digest === digest.model) || value.judge !== void 0 && !daemon.models.some((model) => model.name === value.judge && model.digest === digest.judge)) return false;
|
|
435
|
+
}
|
|
427
436
|
return ["http:", "https:"].includes(url.protocol) && url.username === "" && url.password === "" && url.search === "" && url.hash === "" && url.pathname === "/";
|
|
428
437
|
});
|
|
429
438
|
}
|
|
439
|
+
/** Checks whether an owned daemon declaration pins an absolute executable and distinct models.
|
|
440
|
+
* @param value - The candidate declaration.
|
|
441
|
+
* @returns True if executable, version, environment, and model identities are valid; false otherwise.
|
|
442
|
+
* @example
|
|
443
|
+
* ```ts
|
|
444
|
+
* isStudyDaemon({ executable: 'ollama' }) // false
|
|
445
|
+
* ```
|
|
446
|
+
*/
|
|
447
|
+
function isStudyDaemon(value) {
|
|
448
|
+
return (0, _orkestrel_contract.holds)(() => {
|
|
449
|
+
if (!(0, _orkestrel_contract.isRecord)(value) || !matchesStudyKeys(value, [
|
|
450
|
+
"executable",
|
|
451
|
+
"digest",
|
|
452
|
+
"version",
|
|
453
|
+
"models"
|
|
454
|
+
], ["environment"]) || typeof value.executable !== "string" || !/^(?:[A-Za-z]:[\\/]|\/(?!\/)|\\\\[^\\]+\\[^\\]+\\)/.test(value.executable) || value.executable.includes("\0") || value.executable.split(/[\\/]/).some((part) => part === "." || part === "..") || !isStudyDigest(value.digest) || !(0, _orkestrel_contract.isNonEmptyString)(value.version) || value.version.trim().length === 0 || value.version.includes("\0") || !(0, _orkestrel_contract.isArray)(value.models) || value.models.length === 0 || !value.models.every((model) => (0, _orkestrel_contract.isRecord)(model) && matchesStudyKeys(model, ["name", "digest"]) && (0, _orkestrel_contract.isNonEmptyString)(model.name) && model.name.trim().length > 0 && !model.name.includes("\0") && isStudyDigest(model.digest))) return false;
|
|
455
|
+
if (new Set(value.models.map((model) => (0, _orkestrel_contract.isRecord)(model) ? model.name : void 0)).size !== value.models.length) return false;
|
|
456
|
+
if (value.environment !== void 0) {
|
|
457
|
+
if (!(0, _orkestrel_contract.isRecord)(value.environment) || !matchesStudyKeys(value.environment, [], Object.keys(value.environment))) return false;
|
|
458
|
+
const entries = Object.entries(value.environment);
|
|
459
|
+
if (new Set(entries.map(([name]) => name.toLowerCase())).size !== entries.length || entries.some(([name, entry]) => name.length === 0 || /[=\0]/.test(name) || typeof entry !== "string" || entry.includes("\0"))) return false;
|
|
460
|
+
}
|
|
461
|
+
return true;
|
|
462
|
+
});
|
|
463
|
+
}
|
|
430
464
|
/**
|
|
431
465
|
* Checks whether a profile carries finite bounds and an optional explicit provider.
|
|
432
466
|
* @param value - The candidate profile
|
|
@@ -448,10 +482,18 @@ function isStudyProfile(value) {
|
|
|
448
482
|
], [
|
|
449
483
|
"provider",
|
|
450
484
|
"qualification",
|
|
451
|
-
"settings"
|
|
452
|
-
|
|
485
|
+
"settings",
|
|
486
|
+
"record"
|
|
487
|
+
]) && isStudyName(value.name) && (0, _orkestrel_contract.isNonEmptyString)(value.agent) && (0, _orkestrel_contract.isArray)(value.roots) && (0, _orkestrel_contract.isJSONValue)(value.roots) && value.roots.length > 0 && value.roots.every((root) => typeof root === "string" && root.trim().length > 0) && new Set(value.roots).size === value.roots.length && (0, _orkestrel_contract.isNonEmptyString)(value.subject) && isStudyBounds(value.bounds) && isStudyRoom(value.room) && (value.provider === void 0 || isStudyProvider(value.provider)) && (value.record === void 0 || isStudyRecord(value.record)) && (value.qualification === void 0 || (0, _orkestrel_contract.isNonEmptyString)(value.qualification)) && (value.settings === void 0 || (0, _orkestrel_contract.isRecord)(value.settings) && (0, _orkestrel_contract.isJSONValue)(value.settings));
|
|
453
488
|
});
|
|
454
489
|
}
|
|
490
|
+
/** Checks whether a recording declaration bounds every serialized sidecar byte.
|
|
491
|
+
* @param value - The candidate declaration.
|
|
492
|
+
* @returns True if its byte allowance is a positive safe integer; false otherwise.
|
|
493
|
+
*/
|
|
494
|
+
function isStudyRecord(value) {
|
|
495
|
+
return (0, _orkestrel_contract.holds)(() => (0, _orkestrel_contract.isRecord)(value) && matchesStudyKeys(value, ["bytes"]) && typeof value.bytes === "number" && Number.isSafeInteger(value.bytes) && value.bytes > 0);
|
|
496
|
+
}
|
|
455
497
|
/**
|
|
456
498
|
* Checks whether a byte identity is a lowercase SHA-256 digest.
|
|
457
499
|
* @param value - The candidate identity
|
|
@@ -650,9 +692,9 @@ var StudyError = class extends Error {
|
|
|
650
692
|
* valid optional failure members, and an own {@link STUDY_ERROR_BRAND} descriptor whose value is
|
|
651
693
|
* the error itself. Subclasses can replace the name.
|
|
652
694
|
* The global key is recognized across package, ESM, CommonJS and captured module copies; it is
|
|
653
|
-
* not
|
|
695
|
+
* not proof of origin. A transparent proxy is refused because its forwarded descriptor
|
|
654
696
|
* stores the target, and an unbranded copy, an inherited brand, or a property-only lookalike
|
|
655
|
-
* stays outside the type.
|
|
697
|
+
* stays outside the type. Throwing property access returns false instead of throwing.
|
|
656
698
|
* @param value - The caught value
|
|
657
699
|
* @returns True if the value is a study error; false otherwise
|
|
658
700
|
* @example
|
|
@@ -662,11 +704,12 @@ var StudyError = class extends Error {
|
|
|
662
704
|
*/
|
|
663
705
|
function isStudyError(value) {
|
|
664
706
|
return (0, _orkestrel_contract.holds)(() => {
|
|
665
|
-
if (!(
|
|
707
|
+
if (!(value instanceof _orkestrel_contract.INTRINSICS.error) || _orkestrel_contract.INTRINSICS.prototype(value) === _orkestrel_contract.INTRINSICS.error.prototype) return false;
|
|
666
708
|
const brand = _orkestrel_contract.INTRINSICS.describe(value, STUDY_ERROR_BRAND)?.value;
|
|
667
709
|
const code = _orkestrel_contract.INTRINSICS.reflect.read(value, "code");
|
|
668
710
|
const failure = _orkestrel_contract.INTRINSICS.reflect.read(value, "failure");
|
|
669
|
-
|
|
711
|
+
const stack = _orkestrel_contract.INTRINSICS.reflect.read(value, "stack");
|
|
712
|
+
if (brand !== value || !isStudyErrorCode(code) || typeof _orkestrel_contract.INTRINSICS.reflect.read(value, "name") !== "string" || typeof _orkestrel_contract.INTRINSICS.reflect.read(value, "message") !== "string" || stack !== void 0 && typeof stack !== "string") return false;
|
|
670
713
|
if (failure === void 0) return true;
|
|
671
714
|
if (!(0, _orkestrel_contract.isObject)(failure)) return false;
|
|
672
715
|
const cause = _orkestrel_contract.INTRINSICS.reflect.read(failure, "cause");
|
|
@@ -680,7 +723,7 @@ function isStudyError(value) {
|
|
|
680
723
|
const id = _orkestrel_contract.INTRINSICS.reflect.read(stop, "id");
|
|
681
724
|
const max = _orkestrel_contract.INTRINSICS.reflect.read(stop, "max");
|
|
682
725
|
const consumed = _orkestrel_contract.INTRINSICS.reflect.read(stop, "consumed");
|
|
683
|
-
return isStudyLayer(layer) && typeof id === "string" && (max === void 0 || (0, _orkestrel_contract.
|
|
726
|
+
return isStudyLayer(layer) && typeof id === "string" && (max === void 0 || (0, _orkestrel_contract.isNumber)(max)) && (consumed === void 0 || (0, _orkestrel_contract.isNumber)(consumed));
|
|
684
727
|
});
|
|
685
728
|
}
|
|
686
729
|
//#endregion
|
|
@@ -945,8 +988,8 @@ function computeStudyOutputStop(bytes, limit, outputs) {
|
|
|
945
988
|
};
|
|
946
989
|
}
|
|
947
990
|
/**
|
|
948
|
-
* Records an error
|
|
949
|
-
* @param ticket - The admitted request whose work
|
|
991
|
+
* Records an error thrown by admitted work as the failure of its ticket.
|
|
992
|
+
* @param ticket - The admitted request whose work threw
|
|
950
993
|
* @param error - The caught value, read through `readStudyFailure`
|
|
951
994
|
* @param role - The responsibility that replaces any role the reading carries; Default: the carried role, else the ticket's admitted role
|
|
952
995
|
* @remarks
|
|
@@ -955,7 +998,7 @@ function computeStudyOutputStop(bytes, limit, outputs) {
|
|
|
955
998
|
* so the parent's ownership is respected rather than inferred as local settlement. A refusal
|
|
956
999
|
* thrown by the ticket's own settlement propagates.
|
|
957
1000
|
* @throws Thrown when the ticket's settlement refuses the failure.
|
|
958
|
-
* @example Fail an
|
|
1001
|
+
* @example Fail an admitted request
|
|
959
1002
|
* ```ts
|
|
960
1003
|
* import type { StudyTicket } from '@orkestrel/study'
|
|
961
1004
|
* import { failStudyTicket } from '@orkestrel/study'
|
|
@@ -2065,6 +2108,7 @@ exports.isStudyAgentRuntime = isStudyAgentRuntime;
|
|
|
2065
2108
|
exports.isStudyBounds = isStudyBounds;
|
|
2066
2109
|
exports.isStudyCause = isStudyCause;
|
|
2067
2110
|
exports.isStudyCriterion = isStudyCriterion;
|
|
2111
|
+
exports.isStudyDaemon = isStudyDaemon;
|
|
2068
2112
|
exports.isStudyDefinition = isStudyDefinition;
|
|
2069
2113
|
exports.isStudyDigest = isStudyDigest;
|
|
2070
2114
|
exports.isStudyError = isStudyError;
|
|
@@ -2079,6 +2123,7 @@ exports.isStudyName = isStudyName;
|
|
|
2079
2123
|
exports.isStudyProduct = isStudyProduct;
|
|
2080
2124
|
exports.isStudyProfile = isStudyProfile;
|
|
2081
2125
|
exports.isStudyProvider = isStudyProvider;
|
|
2126
|
+
exports.isStudyRecord = isStudyRecord;
|
|
2082
2127
|
exports.isStudyRole = isStudyRole;
|
|
2083
2128
|
exports.isStudyRoom = isStudyRoom;
|
|
2084
2129
|
exports.isStudyRubric = isStudyRubric;
|