@dylanrussell/agent-router 2.0.2 → 2.1.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.
- package/CHANGELOG.md +8 -0
- package/README.md +95 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.js +623 -168
- package/dist/plugin.js.map +1 -1
- package/package.json +2 -1
package/dist/plugin.js
CHANGED
|
@@ -729,9 +729,9 @@ function floatSafeRemainder(val, step) {
|
|
|
729
729
|
return ratio - roundedRatio;
|
|
730
730
|
}
|
|
731
731
|
var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
|
|
732
|
-
function defineLazy(object2,
|
|
732
|
+
function defineLazy(object2, key2, getter) {
|
|
733
733
|
let value = void 0;
|
|
734
|
-
Object.defineProperty(object2,
|
|
734
|
+
Object.defineProperty(object2, key2, {
|
|
735
735
|
get() {
|
|
736
736
|
if (value === EVALUATING) {
|
|
737
737
|
return void 0;
|
|
@@ -743,7 +743,7 @@ function defineLazy(object2, key, getter) {
|
|
|
743
743
|
return value;
|
|
744
744
|
},
|
|
745
745
|
set(v) {
|
|
746
|
-
Object.defineProperty(object2,
|
|
746
|
+
Object.defineProperty(object2, key2, {
|
|
747
747
|
value: v
|
|
748
748
|
// configurable: true,
|
|
749
749
|
});
|
|
@@ -776,11 +776,11 @@ function cloneDef(schema) {
|
|
|
776
776
|
function getElementAtPath(obj, path8) {
|
|
777
777
|
if (!path8)
|
|
778
778
|
return obj;
|
|
779
|
-
return path8.reduce((acc,
|
|
779
|
+
return path8.reduce((acc, key2) => acc?.[key2], obj);
|
|
780
780
|
}
|
|
781
781
|
function promiseAllObject(promisesObj) {
|
|
782
782
|
const keys = Object.keys(promisesObj);
|
|
783
|
-
const promises = keys.map((
|
|
783
|
+
const promises = keys.map((key2) => promisesObj[key2]);
|
|
784
784
|
return Promise.all(promises).then((results) => {
|
|
785
785
|
const resolvedObj = {};
|
|
786
786
|
for (let i = 0; i < keys.length; i++) {
|
|
@@ -852,8 +852,8 @@ function shallowClone(o) {
|
|
|
852
852
|
}
|
|
853
853
|
function numKeys(data) {
|
|
854
854
|
let keyCount = 0;
|
|
855
|
-
for (const
|
|
856
|
-
if (Object.prototype.hasOwnProperty.call(data,
|
|
855
|
+
for (const key2 in data) {
|
|
856
|
+
if (Object.prototype.hasOwnProperty.call(data, key2)) {
|
|
857
857
|
keyCount++;
|
|
858
858
|
}
|
|
859
859
|
}
|
|
@@ -1003,13 +1003,13 @@ function pick(schema, mask) {
|
|
|
1003
1003
|
const def = mergeDefs(schema._zod.def, {
|
|
1004
1004
|
get shape() {
|
|
1005
1005
|
const newShape = {};
|
|
1006
|
-
for (const
|
|
1007
|
-
if (!(
|
|
1008
|
-
throw new Error(`Unrecognized key: "${
|
|
1006
|
+
for (const key2 in mask) {
|
|
1007
|
+
if (!(key2 in currDef.shape)) {
|
|
1008
|
+
throw new Error(`Unrecognized key: "${key2}"`);
|
|
1009
1009
|
}
|
|
1010
|
-
if (!mask[
|
|
1010
|
+
if (!mask[key2])
|
|
1011
1011
|
continue;
|
|
1012
|
-
newShape[
|
|
1012
|
+
newShape[key2] = currDef.shape[key2];
|
|
1013
1013
|
}
|
|
1014
1014
|
assignProp(this, "shape", newShape);
|
|
1015
1015
|
return newShape;
|
|
@@ -1028,13 +1028,13 @@ function omit(schema, mask) {
|
|
|
1028
1028
|
const def = mergeDefs(schema._zod.def, {
|
|
1029
1029
|
get shape() {
|
|
1030
1030
|
const newShape = { ...schema._zod.def.shape };
|
|
1031
|
-
for (const
|
|
1032
|
-
if (!(
|
|
1033
|
-
throw new Error(`Unrecognized key: "${
|
|
1031
|
+
for (const key2 in mask) {
|
|
1032
|
+
if (!(key2 in currDef.shape)) {
|
|
1033
|
+
throw new Error(`Unrecognized key: "${key2}"`);
|
|
1034
1034
|
}
|
|
1035
|
-
if (!mask[
|
|
1035
|
+
if (!mask[key2])
|
|
1036
1036
|
continue;
|
|
1037
|
-
delete newShape[
|
|
1037
|
+
delete newShape[key2];
|
|
1038
1038
|
}
|
|
1039
1039
|
assignProp(this, "shape", newShape);
|
|
1040
1040
|
return newShape;
|
|
@@ -1051,8 +1051,8 @@ function extend(schema, shape) {
|
|
|
1051
1051
|
const hasChecks = checks && checks.length > 0;
|
|
1052
1052
|
if (hasChecks) {
|
|
1053
1053
|
const existingShape = schema._zod.def.shape;
|
|
1054
|
-
for (const
|
|
1055
|
-
if (Object.getOwnPropertyDescriptor(existingShape,
|
|
1054
|
+
for (const key2 in shape) {
|
|
1055
|
+
if (Object.getOwnPropertyDescriptor(existingShape, key2) !== void 0) {
|
|
1056
1056
|
throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.");
|
|
1057
1057
|
}
|
|
1058
1058
|
}
|
|
@@ -1108,23 +1108,23 @@ function partial(Class2, schema, mask) {
|
|
|
1108
1108
|
const oldShape = schema._zod.def.shape;
|
|
1109
1109
|
const shape = { ...oldShape };
|
|
1110
1110
|
if (mask) {
|
|
1111
|
-
for (const
|
|
1112
|
-
if (!(
|
|
1113
|
-
throw new Error(`Unrecognized key: "${
|
|
1111
|
+
for (const key2 in mask) {
|
|
1112
|
+
if (!(key2 in oldShape)) {
|
|
1113
|
+
throw new Error(`Unrecognized key: "${key2}"`);
|
|
1114
1114
|
}
|
|
1115
|
-
if (!mask[
|
|
1115
|
+
if (!mask[key2])
|
|
1116
1116
|
continue;
|
|
1117
|
-
shape[
|
|
1117
|
+
shape[key2] = Class2 ? new Class2({
|
|
1118
1118
|
type: "optional",
|
|
1119
|
-
innerType: oldShape[
|
|
1120
|
-
}) : oldShape[
|
|
1119
|
+
innerType: oldShape[key2]
|
|
1120
|
+
}) : oldShape[key2];
|
|
1121
1121
|
}
|
|
1122
1122
|
} else {
|
|
1123
|
-
for (const
|
|
1124
|
-
shape[
|
|
1123
|
+
for (const key2 in oldShape) {
|
|
1124
|
+
shape[key2] = Class2 ? new Class2({
|
|
1125
1125
|
type: "optional",
|
|
1126
|
-
innerType: oldShape[
|
|
1127
|
-
}) : oldShape[
|
|
1126
|
+
innerType: oldShape[key2]
|
|
1127
|
+
}) : oldShape[key2];
|
|
1128
1128
|
}
|
|
1129
1129
|
}
|
|
1130
1130
|
assignProp(this, "shape", shape);
|
|
@@ -1140,22 +1140,22 @@ function required(Class2, schema, mask) {
|
|
|
1140
1140
|
const oldShape = schema._zod.def.shape;
|
|
1141
1141
|
const shape = { ...oldShape };
|
|
1142
1142
|
if (mask) {
|
|
1143
|
-
for (const
|
|
1144
|
-
if (!(
|
|
1145
|
-
throw new Error(`Unrecognized key: "${
|
|
1143
|
+
for (const key2 in mask) {
|
|
1144
|
+
if (!(key2 in shape)) {
|
|
1145
|
+
throw new Error(`Unrecognized key: "${key2}"`);
|
|
1146
1146
|
}
|
|
1147
|
-
if (!mask[
|
|
1147
|
+
if (!mask[key2])
|
|
1148
1148
|
continue;
|
|
1149
|
-
shape[
|
|
1149
|
+
shape[key2] = new Class2({
|
|
1150
1150
|
type: "nonoptional",
|
|
1151
|
-
innerType: oldShape[
|
|
1151
|
+
innerType: oldShape[key2]
|
|
1152
1152
|
});
|
|
1153
1153
|
}
|
|
1154
1154
|
} else {
|
|
1155
|
-
for (const
|
|
1156
|
-
shape[
|
|
1155
|
+
for (const key2 in oldShape) {
|
|
1156
|
+
shape[key2] = new Class2({
|
|
1157
1157
|
type: "nonoptional",
|
|
1158
|
-
innerType: oldShape[
|
|
1158
|
+
innerType: oldShape[key2]
|
|
1159
1159
|
});
|
|
1160
1160
|
}
|
|
1161
1161
|
}
|
|
@@ -2936,13 +2936,13 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
|
2936
2936
|
return payload;
|
|
2937
2937
|
};
|
|
2938
2938
|
});
|
|
2939
|
-
function handlePropertyResult(result, final,
|
|
2940
|
-
const isPresent =
|
|
2939
|
+
function handlePropertyResult(result, final, key2, input, isOptionalIn, isOptionalOut) {
|
|
2940
|
+
const isPresent = key2 in input;
|
|
2941
2941
|
if (result.issues.length) {
|
|
2942
2942
|
if (isOptionalIn && isOptionalOut && !isPresent) {
|
|
2943
2943
|
return;
|
|
2944
2944
|
}
|
|
2945
|
-
final.issues.push(...prefixIssues(
|
|
2945
|
+
final.issues.push(...prefixIssues(key2, result.issues));
|
|
2946
2946
|
}
|
|
2947
2947
|
if (!isPresent && !isOptionalIn) {
|
|
2948
2948
|
if (!result.issues.length) {
|
|
@@ -2950,17 +2950,17 @@ function handlePropertyResult(result, final, key, input, isOptionalIn, isOptiona
|
|
|
2950
2950
|
code: "invalid_type",
|
|
2951
2951
|
expected: "nonoptional",
|
|
2952
2952
|
input: void 0,
|
|
2953
|
-
path: [
|
|
2953
|
+
path: [key2]
|
|
2954
2954
|
});
|
|
2955
2955
|
}
|
|
2956
2956
|
return;
|
|
2957
2957
|
}
|
|
2958
2958
|
if (result.value === void 0) {
|
|
2959
2959
|
if (isPresent) {
|
|
2960
|
-
final.value[
|
|
2960
|
+
final.value[key2] = void 0;
|
|
2961
2961
|
}
|
|
2962
2962
|
} else {
|
|
2963
|
-
final.value[
|
|
2963
|
+
final.value[key2] = result.value;
|
|
2964
2964
|
}
|
|
2965
2965
|
}
|
|
2966
2966
|
function normalizeDef(def) {
|
|
@@ -2986,20 +2986,20 @@ function handleCatchall(proms, input, payload, ctx, def, inst) {
|
|
|
2986
2986
|
const t = _catchall.def.type;
|
|
2987
2987
|
const isOptionalIn = _catchall.optin === "optional";
|
|
2988
2988
|
const isOptionalOut = _catchall.optout === "optional";
|
|
2989
|
-
for (const
|
|
2990
|
-
if (
|
|
2989
|
+
for (const key2 in input) {
|
|
2990
|
+
if (key2 === "__proto__")
|
|
2991
2991
|
continue;
|
|
2992
|
-
if (keySet.has(
|
|
2992
|
+
if (keySet.has(key2))
|
|
2993
2993
|
continue;
|
|
2994
2994
|
if (t === "never") {
|
|
2995
|
-
unrecognized.push(
|
|
2995
|
+
unrecognized.push(key2);
|
|
2996
2996
|
continue;
|
|
2997
2997
|
}
|
|
2998
|
-
const r = _catchall.run({ value: input[
|
|
2998
|
+
const r = _catchall.run({ value: input[key2], issues: [] }, ctx);
|
|
2999
2999
|
if (r instanceof Promise) {
|
|
3000
|
-
proms.push(r.then((r2) => handlePropertyResult(r2, payload,
|
|
3000
|
+
proms.push(r.then((r2) => handlePropertyResult(r2, payload, key2, input, isOptionalIn, isOptionalOut)));
|
|
3001
3001
|
} else {
|
|
3002
|
-
handlePropertyResult(r, payload,
|
|
3002
|
+
handlePropertyResult(r, payload, key2, input, isOptionalIn, isOptionalOut);
|
|
3003
3003
|
}
|
|
3004
3004
|
}
|
|
3005
3005
|
if (unrecognized.length) {
|
|
@@ -3035,12 +3035,12 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
3035
3035
|
defineLazy(inst._zod, "propValues", () => {
|
|
3036
3036
|
const shape = def.shape;
|
|
3037
3037
|
const propValues = {};
|
|
3038
|
-
for (const
|
|
3039
|
-
const field = shape[
|
|
3038
|
+
for (const key2 in shape) {
|
|
3039
|
+
const field = shape[key2]._zod;
|
|
3040
3040
|
if (field.values) {
|
|
3041
|
-
propValues[
|
|
3041
|
+
propValues[key2] ?? (propValues[key2] = /* @__PURE__ */ new Set());
|
|
3042
3042
|
for (const v of field.values)
|
|
3043
|
-
propValues[
|
|
3043
|
+
propValues[key2].add(v);
|
|
3044
3044
|
}
|
|
3045
3045
|
}
|
|
3046
3046
|
return propValues;
|
|
@@ -3063,15 +3063,15 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
3063
3063
|
payload.value = {};
|
|
3064
3064
|
const proms = [];
|
|
3065
3065
|
const shape = value.shape;
|
|
3066
|
-
for (const
|
|
3067
|
-
const el = shape[
|
|
3066
|
+
for (const key2 of value.keys) {
|
|
3067
|
+
const el = shape[key2];
|
|
3068
3068
|
const isOptionalIn = el._zod.optin === "optional";
|
|
3069
3069
|
const isOptionalOut = el._zod.optout === "optional";
|
|
3070
|
-
const r = el._zod.run({ value: input[
|
|
3070
|
+
const r = el._zod.run({ value: input[key2], issues: [] }, ctx);
|
|
3071
3071
|
if (r instanceof Promise) {
|
|
3072
|
-
proms.push(r.then((r2) => handlePropertyResult(r2, payload,
|
|
3072
|
+
proms.push(r.then((r2) => handlePropertyResult(r2, payload, key2, input, isOptionalIn, isOptionalOut)));
|
|
3073
3073
|
} else {
|
|
3074
|
-
handlePropertyResult(r, payload,
|
|
3074
|
+
handlePropertyResult(r, payload, key2, input, isOptionalIn, isOptionalOut);
|
|
3075
3075
|
}
|
|
3076
3076
|
}
|
|
3077
3077
|
if (!catchall) {
|
|
@@ -3087,24 +3087,24 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
3087
3087
|
const generateFastpass = (shape) => {
|
|
3088
3088
|
const doc = new Doc(["shape", "payload", "ctx"]);
|
|
3089
3089
|
const normalized = _normalized.value;
|
|
3090
|
-
const parseStr = (
|
|
3091
|
-
const k = esc(
|
|
3090
|
+
const parseStr = (key2) => {
|
|
3091
|
+
const k = esc(key2);
|
|
3092
3092
|
return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
|
|
3093
3093
|
};
|
|
3094
3094
|
doc.write(`const input = payload.value;`);
|
|
3095
3095
|
const ids = /* @__PURE__ */ Object.create(null);
|
|
3096
3096
|
let counter = 0;
|
|
3097
|
-
for (const
|
|
3098
|
-
ids[
|
|
3097
|
+
for (const key2 of normalized.keys) {
|
|
3098
|
+
ids[key2] = `key_${counter++}`;
|
|
3099
3099
|
}
|
|
3100
3100
|
doc.write(`const newResult = {};`);
|
|
3101
|
-
for (const
|
|
3102
|
-
const id = ids[
|
|
3103
|
-
const k = esc(
|
|
3104
|
-
const schema = shape[
|
|
3101
|
+
for (const key2 of normalized.keys) {
|
|
3102
|
+
const id = ids[key2];
|
|
3103
|
+
const k = esc(key2);
|
|
3104
|
+
const schema = shape[key2];
|
|
3105
3105
|
const isOptionalIn = schema?._zod?.optin === "optional";
|
|
3106
3106
|
const isOptionalOut = schema?._zod?.optout === "optional";
|
|
3107
|
-
doc.write(`const ${id} = ${parseStr(
|
|
3107
|
+
doc.write(`const ${id} = ${parseStr(key2)};`);
|
|
3108
3108
|
if (isOptionalIn && isOptionalOut) {
|
|
3109
3109
|
doc.write(`
|
|
3110
3110
|
if (${id}.issues.length) {
|
|
@@ -3416,17 +3416,17 @@ function mergeValues(a, b) {
|
|
|
3416
3416
|
}
|
|
3417
3417
|
if (isPlainObject(a) && isPlainObject(b)) {
|
|
3418
3418
|
const bKeys = Object.keys(b);
|
|
3419
|
-
const sharedKeys = Object.keys(a).filter((
|
|
3419
|
+
const sharedKeys = Object.keys(a).filter((key2) => bKeys.indexOf(key2) !== -1);
|
|
3420
3420
|
const newObj = { ...a, ...b };
|
|
3421
|
-
for (const
|
|
3422
|
-
const sharedValue = mergeValues(a[
|
|
3421
|
+
for (const key2 of sharedKeys) {
|
|
3422
|
+
const sharedValue = mergeValues(a[key2], b[key2]);
|
|
3423
3423
|
if (!sharedValue.valid) {
|
|
3424
3424
|
return {
|
|
3425
3425
|
valid: false,
|
|
3426
|
-
mergeErrorPath: [
|
|
3426
|
+
mergeErrorPath: [key2, ...sharedValue.mergeErrorPath]
|
|
3427
3427
|
};
|
|
3428
3428
|
}
|
|
3429
|
-
newObj[
|
|
3429
|
+
newObj[key2] = sharedValue.data;
|
|
3430
3430
|
}
|
|
3431
3431
|
return { valid: true, data: newObj };
|
|
3432
3432
|
}
|
|
@@ -3561,9 +3561,9 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
|
|
|
3561
3561
|
return handleTupleResults(itemResults, payload, items, input, optoutStart);
|
|
3562
3562
|
};
|
|
3563
3563
|
});
|
|
3564
|
-
function getTupleOptStart(items,
|
|
3564
|
+
function getTupleOptStart(items, key2) {
|
|
3565
3565
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
3566
|
-
if (items[i]._zod[
|
|
3566
|
+
if (items[i]._zod[key2] !== "optional")
|
|
3567
3567
|
return i + 1;
|
|
3568
3568
|
}
|
|
3569
3569
|
return 0;
|
|
@@ -3614,10 +3614,10 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
3614
3614
|
if (values) {
|
|
3615
3615
|
payload.value = {};
|
|
3616
3616
|
const recordKeys = /* @__PURE__ */ new Set();
|
|
3617
|
-
for (const
|
|
3618
|
-
if (typeof
|
|
3619
|
-
recordKeys.add(typeof
|
|
3620
|
-
const keyResult = def.keyType._zod.run({ value:
|
|
3617
|
+
for (const key2 of values) {
|
|
3618
|
+
if (typeof key2 === "string" || typeof key2 === "number" || typeof key2 === "symbol") {
|
|
3619
|
+
recordKeys.add(typeof key2 === "number" ? key2.toString() : key2);
|
|
3620
|
+
const keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
|
|
3621
3621
|
if (keyResult instanceof Promise) {
|
|
3622
3622
|
throw new Error("Async schemas not supported in object keys currently");
|
|
3623
3623
|
}
|
|
@@ -3626,34 +3626,34 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
3626
3626
|
code: "invalid_key",
|
|
3627
3627
|
origin: "record",
|
|
3628
3628
|
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
3629
|
-
input:
|
|
3630
|
-
path: [
|
|
3629
|
+
input: key2,
|
|
3630
|
+
path: [key2],
|
|
3631
3631
|
inst
|
|
3632
3632
|
});
|
|
3633
3633
|
continue;
|
|
3634
3634
|
}
|
|
3635
3635
|
const outKey = keyResult.value;
|
|
3636
|
-
const result = def.valueType._zod.run({ value: input[
|
|
3636
|
+
const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
|
|
3637
3637
|
if (result instanceof Promise) {
|
|
3638
3638
|
proms.push(result.then((result2) => {
|
|
3639
3639
|
if (result2.issues.length) {
|
|
3640
|
-
payload.issues.push(...prefixIssues(
|
|
3640
|
+
payload.issues.push(...prefixIssues(key2, result2.issues));
|
|
3641
3641
|
}
|
|
3642
3642
|
payload.value[outKey] = result2.value;
|
|
3643
3643
|
}));
|
|
3644
3644
|
} else {
|
|
3645
3645
|
if (result.issues.length) {
|
|
3646
|
-
payload.issues.push(...prefixIssues(
|
|
3646
|
+
payload.issues.push(...prefixIssues(key2, result.issues));
|
|
3647
3647
|
}
|
|
3648
3648
|
payload.value[outKey] = result.value;
|
|
3649
3649
|
}
|
|
3650
3650
|
}
|
|
3651
3651
|
}
|
|
3652
3652
|
let unrecognized;
|
|
3653
|
-
for (const
|
|
3654
|
-
if (!recordKeys.has(
|
|
3653
|
+
for (const key2 in input) {
|
|
3654
|
+
if (!recordKeys.has(key2)) {
|
|
3655
3655
|
unrecognized = unrecognized ?? [];
|
|
3656
|
-
unrecognized.push(
|
|
3656
|
+
unrecognized.push(key2);
|
|
3657
3657
|
}
|
|
3658
3658
|
}
|
|
3659
3659
|
if (unrecognized && unrecognized.length > 0) {
|
|
@@ -3666,18 +3666,18 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
3666
3666
|
}
|
|
3667
3667
|
} else {
|
|
3668
3668
|
payload.value = {};
|
|
3669
|
-
for (const
|
|
3670
|
-
if (
|
|
3669
|
+
for (const key2 of Reflect.ownKeys(input)) {
|
|
3670
|
+
if (key2 === "__proto__")
|
|
3671
3671
|
continue;
|
|
3672
|
-
if (!Object.prototype.propertyIsEnumerable.call(input,
|
|
3672
|
+
if (!Object.prototype.propertyIsEnumerable.call(input, key2))
|
|
3673
3673
|
continue;
|
|
3674
|
-
let keyResult = def.keyType._zod.run({ value:
|
|
3674
|
+
let keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
|
|
3675
3675
|
if (keyResult instanceof Promise) {
|
|
3676
3676
|
throw new Error("Async schemas not supported in object keys currently");
|
|
3677
3677
|
}
|
|
3678
|
-
const checkNumericKey = typeof
|
|
3678
|
+
const checkNumericKey = typeof key2 === "string" && number.test(key2) && keyResult.issues.length;
|
|
3679
3679
|
if (checkNumericKey) {
|
|
3680
|
-
const retryResult = def.keyType._zod.run({ value: Number(
|
|
3680
|
+
const retryResult = def.keyType._zod.run({ value: Number(key2), issues: [] }, ctx);
|
|
3681
3681
|
if (retryResult instanceof Promise) {
|
|
3682
3682
|
throw new Error("Async schemas not supported in object keys currently");
|
|
3683
3683
|
}
|
|
@@ -3687,30 +3687,30 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
3687
3687
|
}
|
|
3688
3688
|
if (keyResult.issues.length) {
|
|
3689
3689
|
if (def.mode === "loose") {
|
|
3690
|
-
payload.value[
|
|
3690
|
+
payload.value[key2] = input[key2];
|
|
3691
3691
|
} else {
|
|
3692
3692
|
payload.issues.push({
|
|
3693
3693
|
code: "invalid_key",
|
|
3694
3694
|
origin: "record",
|
|
3695
3695
|
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
3696
|
-
input:
|
|
3697
|
-
path: [
|
|
3696
|
+
input: key2,
|
|
3697
|
+
path: [key2],
|
|
3698
3698
|
inst
|
|
3699
3699
|
});
|
|
3700
3700
|
}
|
|
3701
3701
|
continue;
|
|
3702
3702
|
}
|
|
3703
|
-
const result = def.valueType._zod.run({ value: input[
|
|
3703
|
+
const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
|
|
3704
3704
|
if (result instanceof Promise) {
|
|
3705
3705
|
proms.push(result.then((result2) => {
|
|
3706
3706
|
if (result2.issues.length) {
|
|
3707
|
-
payload.issues.push(...prefixIssues(
|
|
3707
|
+
payload.issues.push(...prefixIssues(key2, result2.issues));
|
|
3708
3708
|
}
|
|
3709
3709
|
payload.value[keyResult.value] = result2.value;
|
|
3710
3710
|
}));
|
|
3711
3711
|
} else {
|
|
3712
3712
|
if (result.issues.length) {
|
|
3713
|
-
payload.issues.push(...prefixIssues(
|
|
3713
|
+
payload.issues.push(...prefixIssues(key2, result.issues));
|
|
3714
3714
|
}
|
|
3715
3715
|
payload.value[keyResult.value] = result.value;
|
|
3716
3716
|
}
|
|
@@ -3737,15 +3737,15 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
|
|
|
3737
3737
|
}
|
|
3738
3738
|
const proms = [];
|
|
3739
3739
|
payload.value = /* @__PURE__ */ new Map();
|
|
3740
|
-
for (const [
|
|
3741
|
-
const keyResult = def.keyType._zod.run({ value:
|
|
3740
|
+
for (const [key2, value] of input) {
|
|
3741
|
+
const keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
|
|
3742
3742
|
const valueResult = def.valueType._zod.run({ value, issues: [] }, ctx);
|
|
3743
3743
|
if (keyResult instanceof Promise || valueResult instanceof Promise) {
|
|
3744
3744
|
proms.push(Promise.all([keyResult, valueResult]).then(([keyResult2, valueResult2]) => {
|
|
3745
|
-
handleMapResult(keyResult2, valueResult2, payload,
|
|
3745
|
+
handleMapResult(keyResult2, valueResult2, payload, key2, input, inst, ctx);
|
|
3746
3746
|
}));
|
|
3747
3747
|
} else {
|
|
3748
|
-
handleMapResult(keyResult, valueResult, payload,
|
|
3748
|
+
handleMapResult(keyResult, valueResult, payload, key2, input, inst, ctx);
|
|
3749
3749
|
}
|
|
3750
3750
|
}
|
|
3751
3751
|
if (proms.length)
|
|
@@ -3753,10 +3753,10 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
|
|
|
3753
3753
|
return payload;
|
|
3754
3754
|
};
|
|
3755
3755
|
});
|
|
3756
|
-
function handleMapResult(keyResult, valueResult, final,
|
|
3756
|
+
function handleMapResult(keyResult, valueResult, final, key2, input, inst, ctx) {
|
|
3757
3757
|
if (keyResult.issues.length) {
|
|
3758
|
-
if (propertyKeyTypes.has(typeof
|
|
3759
|
-
final.issues.push(...prefixIssues(
|
|
3758
|
+
if (propertyKeyTypes.has(typeof key2)) {
|
|
3759
|
+
final.issues.push(...prefixIssues(key2, keyResult.issues));
|
|
3760
3760
|
} else {
|
|
3761
3761
|
final.issues.push({
|
|
3762
3762
|
code: "invalid_key",
|
|
@@ -3768,15 +3768,15 @@ function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) {
|
|
|
3768
3768
|
}
|
|
3769
3769
|
}
|
|
3770
3770
|
if (valueResult.issues.length) {
|
|
3771
|
-
if (propertyKeyTypes.has(typeof
|
|
3772
|
-
final.issues.push(...prefixIssues(
|
|
3771
|
+
if (propertyKeyTypes.has(typeof key2)) {
|
|
3772
|
+
final.issues.push(...prefixIssues(key2, valueResult.issues));
|
|
3773
3773
|
} else {
|
|
3774
3774
|
final.issues.push({
|
|
3775
3775
|
origin: "map",
|
|
3776
3776
|
code: "invalid_element",
|
|
3777
3777
|
input,
|
|
3778
3778
|
inst,
|
|
3779
|
-
key,
|
|
3779
|
+
key: key2,
|
|
3780
3780
|
issues: valueResult.issues.map((iss) => finalizeIssue(iss, ctx, config()))
|
|
3781
3781
|
});
|
|
3782
3782
|
}
|
|
@@ -11537,8 +11537,8 @@ function extractDefs(ctx, schema) {
|
|
|
11537
11537
|
if (defId)
|
|
11538
11538
|
seen.defId = defId;
|
|
11539
11539
|
const schema2 = seen.schema;
|
|
11540
|
-
for (const
|
|
11541
|
-
delete schema2[
|
|
11540
|
+
for (const key2 in schema2) {
|
|
11541
|
+
delete schema2[key2];
|
|
11542
11542
|
}
|
|
11543
11543
|
schema2.$ref = ref;
|
|
11544
11544
|
};
|
|
@@ -11607,20 +11607,20 @@ function finalize(ctx, schema) {
|
|
|
11607
11607
|
Object.assign(schema2, _cached);
|
|
11608
11608
|
const isParentRef = zodSchema._zod.parent === ref;
|
|
11609
11609
|
if (isParentRef) {
|
|
11610
|
-
for (const
|
|
11611
|
-
if (
|
|
11610
|
+
for (const key2 in schema2) {
|
|
11611
|
+
if (key2 === "$ref" || key2 === "allOf")
|
|
11612
11612
|
continue;
|
|
11613
|
-
if (!(
|
|
11614
|
-
delete schema2[
|
|
11613
|
+
if (!(key2 in _cached)) {
|
|
11614
|
+
delete schema2[key2];
|
|
11615
11615
|
}
|
|
11616
11616
|
}
|
|
11617
11617
|
}
|
|
11618
11618
|
if (refSchema.$ref && refSeen.def) {
|
|
11619
|
-
for (const
|
|
11620
|
-
if (
|
|
11619
|
+
for (const key2 in schema2) {
|
|
11620
|
+
if (key2 === "$ref" || key2 === "allOf")
|
|
11621
11621
|
continue;
|
|
11622
|
-
if (
|
|
11623
|
-
delete schema2[
|
|
11622
|
+
if (key2 in refSeen.def && JSON.stringify(schema2[key2]) === JSON.stringify(refSeen.def[key2])) {
|
|
11623
|
+
delete schema2[key2];
|
|
11624
11624
|
}
|
|
11625
11625
|
}
|
|
11626
11626
|
}
|
|
@@ -11632,11 +11632,11 @@ function finalize(ctx, schema) {
|
|
|
11632
11632
|
if (parentSeen?.schema.$ref) {
|
|
11633
11633
|
schema2.$ref = parentSeen.schema.$ref;
|
|
11634
11634
|
if (parentSeen.def) {
|
|
11635
|
-
for (const
|
|
11636
|
-
if (
|
|
11635
|
+
for (const key2 in schema2) {
|
|
11636
|
+
if (key2 === "$ref" || key2 === "allOf")
|
|
11637
11637
|
continue;
|
|
11638
|
-
if (
|
|
11639
|
-
delete schema2[
|
|
11638
|
+
if (key2 in parentSeen.def && JSON.stringify(schema2[key2]) === JSON.stringify(parentSeen.def[key2])) {
|
|
11639
|
+
delete schema2[key2];
|
|
11640
11640
|
}
|
|
11641
11641
|
}
|
|
11642
11642
|
}
|
|
@@ -11737,8 +11737,8 @@ function isTransforming(_schema, _ctx) {
|
|
|
11737
11737
|
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
|
11738
11738
|
}
|
|
11739
11739
|
if (def.type === "object") {
|
|
11740
|
-
for (const
|
|
11741
|
-
if (isTransforming(def.shape[
|
|
11740
|
+
for (const key2 in def.shape) {
|
|
11741
|
+
if (isTransforming(def.shape[key2], ctx))
|
|
11742
11742
|
return true;
|
|
11743
11743
|
}
|
|
11744
11744
|
return false;
|
|
@@ -12027,15 +12027,15 @@ var objectProcessor = (schema, ctx, _json, params) => {
|
|
|
12027
12027
|
json2.type = "object";
|
|
12028
12028
|
json2.properties = {};
|
|
12029
12029
|
const shape = def.shape;
|
|
12030
|
-
for (const
|
|
12031
|
-
json2.properties[
|
|
12030
|
+
for (const key2 in shape) {
|
|
12031
|
+
json2.properties[key2] = process2(shape[key2], ctx, {
|
|
12032
12032
|
...params,
|
|
12033
|
-
path: [...params.path, "properties",
|
|
12033
|
+
path: [...params.path, "properties", key2]
|
|
12034
12034
|
});
|
|
12035
12035
|
}
|
|
12036
12036
|
const allKeys = new Set(Object.keys(shape));
|
|
12037
|
-
const requiredKeys = new Set([...allKeys].filter((
|
|
12038
|
-
const v = def.shape[
|
|
12037
|
+
const requiredKeys = new Set([...allKeys].filter((key2) => {
|
|
12038
|
+
const v = def.shape[key2]._zod;
|
|
12039
12039
|
if (ctx.io === "input") {
|
|
12040
12040
|
return v.optin === void 0;
|
|
12041
12041
|
} else {
|
|
@@ -12301,9 +12301,9 @@ function toJSONSchema(input, params) {
|
|
|
12301
12301
|
};
|
|
12302
12302
|
ctx2.external = external;
|
|
12303
12303
|
for (const entry of registry2._idmap.entries()) {
|
|
12304
|
-
const [
|
|
12304
|
+
const [key2, schema] = entry;
|
|
12305
12305
|
extractDefs(ctx2, schema);
|
|
12306
|
-
schemas[
|
|
12306
|
+
schemas[key2] = finalize(ctx2, schema);
|
|
12307
12307
|
}
|
|
12308
12308
|
if (Object.keys(defs).length > 0) {
|
|
12309
12309
|
const defsSegment = ctx2.target === "draft-2020-12" ? "$defs" : "definitions";
|
|
@@ -12709,14 +12709,14 @@ function _installLazyMethods(inst, group, methods) {
|
|
|
12709
12709
|
if (installed.has(group))
|
|
12710
12710
|
return;
|
|
12711
12711
|
installed.add(group);
|
|
12712
|
-
for (const
|
|
12713
|
-
const fn = methods[
|
|
12714
|
-
Object.defineProperty(proto,
|
|
12712
|
+
for (const key2 in methods) {
|
|
12713
|
+
const fn = methods[key2];
|
|
12714
|
+
Object.defineProperty(proto, key2, {
|
|
12715
12715
|
configurable: true,
|
|
12716
12716
|
enumerable: false,
|
|
12717
12717
|
get() {
|
|
12718
12718
|
const bound = fn.bind(this);
|
|
12719
|
-
Object.defineProperty(this,
|
|
12719
|
+
Object.defineProperty(this, key2, {
|
|
12720
12720
|
configurable: true,
|
|
12721
12721
|
writable: true,
|
|
12722
12722
|
enumerable: true,
|
|
@@ -12725,7 +12725,7 @@ function _installLazyMethods(inst, group, methods) {
|
|
|
12725
12725
|
return bound;
|
|
12726
12726
|
},
|
|
12727
12727
|
set(v) {
|
|
12728
|
-
Object.defineProperty(this,
|
|
12728
|
+
Object.defineProperty(this, key2, {
|
|
12729
12729
|
configurable: true,
|
|
12730
12730
|
writable: true,
|
|
12731
12731
|
enumerable: true,
|
|
@@ -14113,11 +14113,11 @@ function resolveRef(ref, ctx) {
|
|
|
14113
14113
|
}
|
|
14114
14114
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
14115
14115
|
if (path8[0] === defsKey) {
|
|
14116
|
-
const
|
|
14117
|
-
if (!
|
|
14116
|
+
const key2 = path8[1];
|
|
14117
|
+
if (!key2 || !ctx.defs[key2]) {
|
|
14118
14118
|
throw new Error(`Reference not found: ${ref}`);
|
|
14119
14119
|
}
|
|
14120
|
-
return ctx.defs[
|
|
14120
|
+
return ctx.defs[key2];
|
|
14121
14121
|
}
|
|
14122
14122
|
throw new Error(`Reference not found: ${ref}`);
|
|
14123
14123
|
}
|
|
@@ -14303,9 +14303,9 @@ function convertBaseSchema(schema, ctx) {
|
|
|
14303
14303
|
const shape = {};
|
|
14304
14304
|
const properties = schema.properties || {};
|
|
14305
14305
|
const requiredSet = new Set(schema.required || []);
|
|
14306
|
-
for (const [
|
|
14306
|
+
for (const [key2, propSchema] of Object.entries(properties)) {
|
|
14307
14307
|
const propZodSchema = convertSchema(propSchema, ctx);
|
|
14308
|
-
shape[
|
|
14308
|
+
shape[key2] = requiredSet.has(key2) ? propZodSchema : propZodSchema.optional();
|
|
14309
14309
|
}
|
|
14310
14310
|
if (schema.propertyNames) {
|
|
14311
14311
|
const keySchema = convertSchema(schema.propertyNames, ctx);
|
|
@@ -14446,20 +14446,20 @@ function convertSchema(schema, ctx) {
|
|
|
14446
14446
|
}
|
|
14447
14447
|
const extraMeta = {};
|
|
14448
14448
|
const coreMetadataKeys = ["$id", "id", "$comment", "$anchor", "$vocabulary", "$dynamicRef", "$dynamicAnchor"];
|
|
14449
|
-
for (const
|
|
14450
|
-
if (
|
|
14451
|
-
extraMeta[
|
|
14449
|
+
for (const key2 of coreMetadataKeys) {
|
|
14450
|
+
if (key2 in schema) {
|
|
14451
|
+
extraMeta[key2] = schema[key2];
|
|
14452
14452
|
}
|
|
14453
14453
|
}
|
|
14454
14454
|
const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
|
|
14455
|
-
for (const
|
|
14456
|
-
if (
|
|
14457
|
-
extraMeta[
|
|
14455
|
+
for (const key2 of contentMetadataKeys) {
|
|
14456
|
+
if (key2 in schema) {
|
|
14457
|
+
extraMeta[key2] = schema[key2];
|
|
14458
14458
|
}
|
|
14459
14459
|
}
|
|
14460
|
-
for (const
|
|
14461
|
-
if (!RECOGNIZED_KEYS.has(
|
|
14462
|
-
extraMeta[
|
|
14460
|
+
for (const key2 of Object.keys(schema)) {
|
|
14461
|
+
if (!RECOGNIZED_KEYS.has(key2)) {
|
|
14462
|
+
extraMeta[key2] = schema[key2];
|
|
14463
14463
|
}
|
|
14464
14464
|
}
|
|
14465
14465
|
if (Object.keys(extraMeta).length > 0) {
|
|
@@ -14776,10 +14776,32 @@ function createFailover(routes, notice) {
|
|
|
14776
14776
|
const notify = (message) => notice(`agent-router: ${message}`).catch(() => {
|
|
14777
14777
|
});
|
|
14778
14778
|
return {
|
|
14779
|
+
pending(sessionID) {
|
|
14780
|
+
const state = sessions.get(sessionID);
|
|
14781
|
+
return enabled && !state?.disabled && state?.pending ? { ...state.pending } : void 0;
|
|
14782
|
+
},
|
|
14779
14783
|
active(sessionID) {
|
|
14780
14784
|
const state = sessions.get(sessionID);
|
|
14781
14785
|
return enabled && Boolean(state?.turn) && !state?.disabled;
|
|
14782
14786
|
},
|
|
14787
|
+
/** Register an admission already selected by a separate policy; no retry occurs. */
|
|
14788
|
+
admit(sessionID, message) {
|
|
14789
|
+
if (!enabled) return;
|
|
14790
|
+
const chain = chains.get(message.agent);
|
|
14791
|
+
const index = chain?.findIndex((candidate) => same(candidate, message.model)) ?? -1;
|
|
14792
|
+
if (index < 0 || !sessions.has(sessionID) && sessions.size >= 1024) return;
|
|
14793
|
+
const state = sessions.get(sessionID) ?? { disabled: false, indices: /* @__PURE__ */ new Map() };
|
|
14794
|
+
state.disabled = false;
|
|
14795
|
+
state.indices.set(message.agent, index);
|
|
14796
|
+
state.pending = void 0;
|
|
14797
|
+
state.turn = {
|
|
14798
|
+
agent: message.agent,
|
|
14799
|
+
parent: message.id,
|
|
14800
|
+
model: { ...message.model },
|
|
14801
|
+
handled: false
|
|
14802
|
+
};
|
|
14803
|
+
sessions.set(sessionID, state);
|
|
14804
|
+
},
|
|
14783
14805
|
disable() {
|
|
14784
14806
|
enabled = false;
|
|
14785
14807
|
sessions.clear();
|
|
@@ -15142,29 +15164,29 @@ function parseMapping(lines, startIdx, indent) {
|
|
|
15142
15164
|
i++;
|
|
15143
15165
|
continue;
|
|
15144
15166
|
}
|
|
15145
|
-
const
|
|
15146
|
-
if (
|
|
15167
|
+
const key2 = stripKeyQuotes(line.text.slice(0, colon).trim());
|
|
15168
|
+
if (key2 === "") {
|
|
15147
15169
|
i++;
|
|
15148
15170
|
continue;
|
|
15149
15171
|
}
|
|
15150
15172
|
const rest = line.text.slice(colon + 1).trim();
|
|
15151
15173
|
if (rest !== "") {
|
|
15152
|
-
out[
|
|
15174
|
+
out[key2] = parseFlowValue(rest);
|
|
15153
15175
|
i++;
|
|
15154
15176
|
} else {
|
|
15155
15177
|
const childIndent = lines[i + 1]?.indent ?? line.indent + 1;
|
|
15156
15178
|
let j = i + 1;
|
|
15157
15179
|
while (j < lines.length && (lines[j]?.indent ?? -1) >= childIndent) j++;
|
|
15158
15180
|
if (j === i + 1) {
|
|
15159
|
-
out[
|
|
15181
|
+
out[key2] = null;
|
|
15160
15182
|
i++;
|
|
15161
15183
|
} else {
|
|
15162
15184
|
const childBlock = lines.slice(i + 1, j);
|
|
15163
15185
|
const firstChild = childBlock[0];
|
|
15164
15186
|
if (firstChild?.text.trimStart().startsWith("- ")) {
|
|
15165
|
-
out[
|
|
15187
|
+
out[key2] = parseSequence(childBlock, childIndent);
|
|
15166
15188
|
} else {
|
|
15167
|
-
out[
|
|
15189
|
+
out[key2] = parseMapping(childBlock, 0, childIndent).value;
|
|
15168
15190
|
}
|
|
15169
15191
|
i = j;
|
|
15170
15192
|
}
|
|
@@ -15276,24 +15298,24 @@ function setFrontmatterOptions(content, options) {
|
|
|
15276
15298
|
for (let i = 0; i < lines.length; i++) {
|
|
15277
15299
|
const m = /^([A-Za-z0-9_-]+):[ \t]*(.*)$/.exec(lines[i] ?? "");
|
|
15278
15300
|
if (!m) continue;
|
|
15279
|
-
const
|
|
15280
|
-
if (!(
|
|
15281
|
-
handled.add(
|
|
15301
|
+
const key2 = m[1] ?? "";
|
|
15302
|
+
if (!(key2 in options)) continue;
|
|
15303
|
+
handled.add(key2);
|
|
15282
15304
|
let end = i + 1;
|
|
15283
15305
|
while (end < lines.length && /^[ \t]+/.test(lines[end] ?? "")) end++;
|
|
15284
|
-
const value = options[
|
|
15306
|
+
const value = options[key2];
|
|
15285
15307
|
if (value === null || value === void 0) {
|
|
15286
15308
|
lines.splice(i, end - i);
|
|
15287
15309
|
i--;
|
|
15288
15310
|
} else {
|
|
15289
|
-
lines.splice(i, end - i, `${
|
|
15311
|
+
lines.splice(i, end - i, `${key2}: ${serializeOptionValue(value)}`);
|
|
15290
15312
|
}
|
|
15291
15313
|
}
|
|
15292
15314
|
const appended = [];
|
|
15293
|
-
for (const [
|
|
15294
|
-
if (handled.has(
|
|
15315
|
+
for (const [key2, value] of Object.entries(options)) {
|
|
15316
|
+
if (handled.has(key2)) continue;
|
|
15295
15317
|
if (value === null || value === void 0) continue;
|
|
15296
|
-
appended.push(`${
|
|
15318
|
+
appended.push(`${key2}: ${serializeOptionValue(value)}`);
|
|
15297
15319
|
}
|
|
15298
15320
|
const nextBlock = appended.length > 0 ? lines.join(eol) + eol + appended.join(eol) : lines.join(eol);
|
|
15299
15321
|
if (nextBlock === block) return content;
|
|
@@ -15731,6 +15753,364 @@ async function captureStack(paths, name, options = {}) {
|
|
|
15731
15753
|
return { name, path: dest, agents: Object.keys(agents).length };
|
|
15732
15754
|
}
|
|
15733
15755
|
|
|
15756
|
+
// src/core/pin-store.ts
|
|
15757
|
+
var Pins = external_exports.object({ version: external_exports.literal(1), sessionIDs: external_exports.array(external_exports.string().min(1)).max(1024) }).strict();
|
|
15758
|
+
var PIN_STORE_KEY = "quota-pins-v1";
|
|
15759
|
+
function createPinStore(storage) {
|
|
15760
|
+
let lane = Promise.resolve();
|
|
15761
|
+
let pending = 0;
|
|
15762
|
+
const read = async () => {
|
|
15763
|
+
const value = await storage.get(PIN_STORE_KEY);
|
|
15764
|
+
return new Set(value === void 0 ? [] : Pins.parse(value).sessionIDs);
|
|
15765
|
+
};
|
|
15766
|
+
const mutate = (sessionID, add, valid) => {
|
|
15767
|
+
if (pending >= 65) return Promise.reject(new Error("Session pin storage is busy; try again."));
|
|
15768
|
+
pending++;
|
|
15769
|
+
const operation = lane.then(async () => {
|
|
15770
|
+
const pins = await read();
|
|
15771
|
+
if (!valid()) throw new Error("Session pin operation was cancelled.");
|
|
15772
|
+
if (add) {
|
|
15773
|
+
if (!pins.has(sessionID) && pins.size >= 1024)
|
|
15774
|
+
throw new Error("Session pin capacity reached.");
|
|
15775
|
+
pins.add(sessionID);
|
|
15776
|
+
} else if (!pins.delete(sessionID)) return;
|
|
15777
|
+
await storage.set(PIN_STORE_KEY, { version: 1, sessionIDs: [...pins] });
|
|
15778
|
+
});
|
|
15779
|
+
lane = operation.then(
|
|
15780
|
+
() => {
|
|
15781
|
+
pending--;
|
|
15782
|
+
},
|
|
15783
|
+
() => {
|
|
15784
|
+
pending--;
|
|
15785
|
+
}
|
|
15786
|
+
);
|
|
15787
|
+
return operation;
|
|
15788
|
+
};
|
|
15789
|
+
return {
|
|
15790
|
+
async has(sessionID) {
|
|
15791
|
+
await lane;
|
|
15792
|
+
return (await read()).has(sessionID);
|
|
15793
|
+
},
|
|
15794
|
+
add: (sessionID, valid) => mutate(sessionID, true, valid),
|
|
15795
|
+
remove: (sessionID, valid = () => true) => mutate(sessionID, false, valid),
|
|
15796
|
+
drain: () => lane
|
|
15797
|
+
};
|
|
15798
|
+
}
|
|
15799
|
+
|
|
15800
|
+
// src/core/quota-preflight.ts
|
|
15801
|
+
import { Rpc } from "@opencode/plugin/rpc";
|
|
15802
|
+
var ID = external_exports.string().max(200).regex(/^[a-zA-Z0-9][a-zA-Z0-9._:/+-]*$/);
|
|
15803
|
+
var Candidate = external_exports.object({ providerID: ID, id: ID }).strict();
|
|
15804
|
+
var Result = Candidate.extend({
|
|
15805
|
+
status: external_exports.enum(["available", "exhausted", "unknown"]),
|
|
15806
|
+
checkedAt: external_exports.number().finite().nullable(),
|
|
15807
|
+
validUntil: external_exports.number().finite().nullable(),
|
|
15808
|
+
resetAt: external_exports.number().finite().nullable(),
|
|
15809
|
+
reason: external_exports.string(),
|
|
15810
|
+
accountRef: external_exports.string().nullable(),
|
|
15811
|
+
scopeRef: external_exports.string().nullable()
|
|
15812
|
+
}).strict();
|
|
15813
|
+
var QuotaOutput = external_exports.object({ candidates: external_exports.array(Result).max(64) }).strict();
|
|
15814
|
+
var UsageQuota = Rpc.define({
|
|
15815
|
+
id: "direct-api-usage",
|
|
15816
|
+
methods: {
|
|
15817
|
+
query: {
|
|
15818
|
+
input: external_exports.object({ candidates: external_exports.array(Candidate).max(64) }).strict(),
|
|
15819
|
+
output: QuotaOutput
|
|
15820
|
+
}
|
|
15821
|
+
},
|
|
15822
|
+
events: {}
|
|
15823
|
+
});
|
|
15824
|
+
var QuotaOptions = external_exports.object({ enabled: external_exports.boolean().default(false), allowPaidFallbacks: external_exports.boolean().default(false) }).strict();
|
|
15825
|
+
function quotaCandidate(entry) {
|
|
15826
|
+
const slash = entry.model.indexOf("/");
|
|
15827
|
+
return { providerID: entry.model.slice(0, slash), id: entry.model.slice(slash + 1) };
|
|
15828
|
+
}
|
|
15829
|
+
function effectiveQuotaStatus(candidate, results, now = Date.now()) {
|
|
15830
|
+
const matches = results.filter(
|
|
15831
|
+
(r) => r.providerID === candidate.providerID && r.id === candidate.id
|
|
15832
|
+
);
|
|
15833
|
+
const result = matches.length === 1 ? matches[0] : void 0;
|
|
15834
|
+
const bound = Boolean(result?.accountRef && result.scopeRef);
|
|
15835
|
+
const fresh = bound && result?.checkedAt !== null && result?.checkedAt !== void 0 && result.checkedAt > 0 && result.checkedAt <= now && result.validUntil !== null && result.validUntil > now && (result.resetAt === null || result.resetAt > now);
|
|
15836
|
+
return { status: fresh ? result?.status ?? "unknown" : "unknown", bound };
|
|
15837
|
+
}
|
|
15838
|
+
function chooseQuotaRoute(route, results, allowPaidFallbacks, now = Date.now(), startIndex = 0) {
|
|
15839
|
+
for (const [index, entry] of [route, ...route.fallbacks ?? []].entries()) {
|
|
15840
|
+
if (index < startIndex) continue;
|
|
15841
|
+
const candidate = quotaCandidate(entry);
|
|
15842
|
+
const { status, bound } = effectiveQuotaStatus(candidate, results, now);
|
|
15843
|
+
if (status === "exhausted") continue;
|
|
15844
|
+
if (index === 0 || bound || allowPaidFallbacks) return entry;
|
|
15845
|
+
}
|
|
15846
|
+
return void 0;
|
|
15847
|
+
}
|
|
15848
|
+
function createQuotaQuery(query, deadlineMs = 3e3, capacity = 16) {
|
|
15849
|
+
const pending = /* @__PURE__ */ new Set();
|
|
15850
|
+
let disposed = false;
|
|
15851
|
+
return {
|
|
15852
|
+
async read(candidates) {
|
|
15853
|
+
if (disposed || pending.size >= capacity) return [];
|
|
15854
|
+
const controller = new AbortController();
|
|
15855
|
+
pending.add(controller);
|
|
15856
|
+
let timer;
|
|
15857
|
+
const request = Promise.resolve().then(() => query({ candidates }, { signal: controller.signal })).then((value) => {
|
|
15858
|
+
const parsed = QuotaOutput.safeParse(value);
|
|
15859
|
+
return parsed.success ? parsed.data.candidates : [];
|
|
15860
|
+
}).catch(() => []).finally(() => pending.delete(controller));
|
|
15861
|
+
const timeout = new Promise((resolve) => {
|
|
15862
|
+
const stop = () => resolve([]);
|
|
15863
|
+
controller.signal.addEventListener("abort", stop, { once: true });
|
|
15864
|
+
timer = setTimeout(() => controller.abort(), deadlineMs);
|
|
15865
|
+
});
|
|
15866
|
+
try {
|
|
15867
|
+
return await Promise.race([request, timeout]);
|
|
15868
|
+
} finally {
|
|
15869
|
+
clearTimeout(timer);
|
|
15870
|
+
}
|
|
15871
|
+
},
|
|
15872
|
+
dispose() {
|
|
15873
|
+
disposed = true;
|
|
15874
|
+
for (const controller of pending) controller.abort();
|
|
15875
|
+
}
|
|
15876
|
+
};
|
|
15877
|
+
}
|
|
15878
|
+
|
|
15879
|
+
// src/quota-v2.ts
|
|
15880
|
+
var key = (model) => model ? `${model.providerID}/${model.id}#${model.variant === "default" ? "" : model.variant ?? ""}` : "";
|
|
15881
|
+
function createQuotaAdmission(ctx, routes, current) {
|
|
15882
|
+
const parsed = QuotaOptions.safeParse(ctx.options?.quotaPreflight ?? {});
|
|
15883
|
+
if (!parsed.success || !parsed.data.enabled) return void 0;
|
|
15884
|
+
const options = parsed.data;
|
|
15885
|
+
const query = createQuotaQuery((input, request) => ctx.rpc(UsageQuota).query(input, request));
|
|
15886
|
+
const owned = /* @__PURE__ */ new Map();
|
|
15887
|
+
const expected = /* @__PURE__ */ new Map();
|
|
15888
|
+
const busy = /* @__PURE__ */ new Set();
|
|
15889
|
+
const versions = /* @__PURE__ */ new Map();
|
|
15890
|
+
const controls = /* @__PURE__ */ new Set();
|
|
15891
|
+
const pinned = /* @__PURE__ */ new Set();
|
|
15892
|
+
const deletedControls = /* @__PURE__ */ new Set();
|
|
15893
|
+
const pinStore = createPinStore(ctx.storage);
|
|
15894
|
+
const reasons = /* @__PURE__ */ new Map();
|
|
15895
|
+
let disposed = false;
|
|
15896
|
+
const invalidate = (sessionID) => {
|
|
15897
|
+
if (busy.has(sessionID)) versions.set(sessionID, (versions.get(sessionID) ?? 0) + 1);
|
|
15898
|
+
};
|
|
15899
|
+
const reason = (sessionID, value, model) => {
|
|
15900
|
+
if (disposed) return;
|
|
15901
|
+
if (reasons.has(sessionID) || reasons.size < 1024) reasons.set(sessionID, value);
|
|
15902
|
+
console.info(`agent-router: [${sessionID}] ${value}${model ? ` ${key(model)}` : ""}`);
|
|
15903
|
+
};
|
|
15904
|
+
const isPinned = async (sessionID) => {
|
|
15905
|
+
if (pinned.has(sessionID)) return true;
|
|
15906
|
+
try {
|
|
15907
|
+
return await pinStore.has(sessionID);
|
|
15908
|
+
} catch {
|
|
15909
|
+
return true;
|
|
15910
|
+
}
|
|
15911
|
+
};
|
|
15912
|
+
const evaluate = async (route, pending) => {
|
|
15913
|
+
const candidates = [route, ...route.fallbacks ?? []].map(quotaCandidate).filter(
|
|
15914
|
+
(entry, index, all) => all.findIndex(
|
|
15915
|
+
(other) => other.providerID === entry.providerID && other.id === entry.id
|
|
15916
|
+
) === index
|
|
15917
|
+
);
|
|
15918
|
+
const results = await query.read(candidates);
|
|
15919
|
+
return () => {
|
|
15920
|
+
const now = Date.now();
|
|
15921
|
+
const startIndex = pending ? Math.max(
|
|
15922
|
+
0,
|
|
15923
|
+
[route, ...route.fallbacks ?? []].findIndex(
|
|
15924
|
+
(entry) => key({
|
|
15925
|
+
...quotaCandidate(entry),
|
|
15926
|
+
...entry.variant ? { variant: entry.variant } : {}
|
|
15927
|
+
}) === key(pending)
|
|
15928
|
+
)
|
|
15929
|
+
) : 0;
|
|
15930
|
+
const choice = chooseQuotaRoute(route, results, options.allowPaidFallbacks, now, startIndex);
|
|
15931
|
+
return {
|
|
15932
|
+
choice,
|
|
15933
|
+
reason: !choice ? "no_eligible_fallback" : pending ? "staged_reactive_fallback" : choice.model !== route.model ? "known_exhaustion_fallback" : effectiveQuotaStatus(quotaCandidate(route), results, now).status === "available" ? "primary_available" : "primary_unknown"
|
|
15934
|
+
};
|
|
15935
|
+
};
|
|
15936
|
+
};
|
|
15937
|
+
return {
|
|
15938
|
+
isPinned,
|
|
15939
|
+
async status(sessionID) {
|
|
15940
|
+
const session = await ctx.session.get({ sessionID });
|
|
15941
|
+
const explicit = await isPinned(sessionID);
|
|
15942
|
+
const automatic = !explicit && (!session.model || owned.get(sessionID)?.model === key(session.model));
|
|
15943
|
+
const resolved = session.model ?? (session.agent ? (await ctx.agent.get({ agentID: session.agent })).data.model : void 0) ?? (await ctx.model.default()).data;
|
|
15944
|
+
return {
|
|
15945
|
+
sessionID,
|
|
15946
|
+
mode: automatic ? "automatic" : "pinned",
|
|
15947
|
+
model: resolved ? {
|
|
15948
|
+
providerID: resolved.providerID,
|
|
15949
|
+
id: resolved.id,
|
|
15950
|
+
..."variant" in resolved && typeof resolved.variant === "string" ? { variant: resolved.variant } : {}
|
|
15951
|
+
} : null,
|
|
15952
|
+
reason: explicit ? "explicit_pin" : automatic ? reasons.get(sessionID) ?? "awaiting_next_turn" : "manual_or_preexisting_selection"
|
|
15953
|
+
};
|
|
15954
|
+
},
|
|
15955
|
+
async control(sessionID, action, pause) {
|
|
15956
|
+
if (disposed || !current())
|
|
15957
|
+
throw new Error("Router configuration changed; reload before changing session routing.");
|
|
15958
|
+
if (controls.has(sessionID) || controls.size >= 64)
|
|
15959
|
+
throw new Error("Session routing control is busy; try again.");
|
|
15960
|
+
if (action === "pin" && !pinned.has(sessionID) && pinned.size >= 1024)
|
|
15961
|
+
throw new Error("Session pin capacity reached.");
|
|
15962
|
+
controls.add(sessionID);
|
|
15963
|
+
invalidate(sessionID);
|
|
15964
|
+
const live = () => !disposed && current() && !deletedControls.has(sessionID);
|
|
15965
|
+
try {
|
|
15966
|
+
await pause();
|
|
15967
|
+
const session = await ctx.session.get({ sessionID });
|
|
15968
|
+
if (!live())
|
|
15969
|
+
throw new Error("Router stopped or session deleted before the control completed.");
|
|
15970
|
+
if (!session.agent || !routes[session.agent])
|
|
15971
|
+
throw new Error("No configured route for this session agent.");
|
|
15972
|
+
if (action === "pin") {
|
|
15973
|
+
owned.delete(sessionID);
|
|
15974
|
+
expected.delete(sessionID);
|
|
15975
|
+
await pinStore.add(sessionID, live);
|
|
15976
|
+
if (!live()) throw new Error("Router stopped or session deleted during pinning.");
|
|
15977
|
+
pinned.add(sessionID);
|
|
15978
|
+
if (!session.model) {
|
|
15979
|
+
const agent = await ctx.agent.get({ agentID: session.agent });
|
|
15980
|
+
const resolved = agent.data.model ?? (await ctx.model.default()).data;
|
|
15981
|
+
if (!resolved) throw new Error("No native model is resolved; routing remains pinned.");
|
|
15982
|
+
const latest = await ctx.session.get({ sessionID });
|
|
15983
|
+
if (!live()) throw new Error("Router stopped or session deleted during pinning.");
|
|
15984
|
+
if (latest.agent !== session.agent || key(latest.model) !== key(session.model))
|
|
15985
|
+
throw new Error(
|
|
15986
|
+
"Session selection changed while pinning; current selection remains pinned."
|
|
15987
|
+
);
|
|
15988
|
+
const model = {
|
|
15989
|
+
providerID: resolved.providerID,
|
|
15990
|
+
id: resolved.id,
|
|
15991
|
+
..."variant" in resolved && typeof resolved.variant === "string" ? { variant: resolved.variant } : {}
|
|
15992
|
+
};
|
|
15993
|
+
await ctx.session.switchModel({ sessionID, model });
|
|
15994
|
+
}
|
|
15995
|
+
if (!live()) throw new Error("Router stopped or session deleted during pinning.");
|
|
15996
|
+
reason(sessionID, "explicit_pin", (await ctx.session.get({ sessionID })).model);
|
|
15997
|
+
} else {
|
|
15998
|
+
if (!owned.has(sessionID) && owned.size >= 1024)
|
|
15999
|
+
throw new Error("Automatic session capacity reached.");
|
|
16000
|
+
await pinStore.remove(sessionID, live);
|
|
16001
|
+
if (!live()) throw new Error("Router stopped; automatic routing was not resumed.");
|
|
16002
|
+
pinned.delete(sessionID);
|
|
16003
|
+
owned.set(sessionID, { agent: session.agent, model: key(session.model) });
|
|
16004
|
+
reason(sessionID, "automatic_next_explicit_turn", session.model);
|
|
16005
|
+
}
|
|
16006
|
+
} finally {
|
|
16007
|
+
controls.delete(sessionID);
|
|
16008
|
+
deletedControls.delete(sessionID);
|
|
16009
|
+
}
|
|
16010
|
+
},
|
|
16011
|
+
/** Called for every selection event, including before the first prompt. */
|
|
16012
|
+
event(sessionID, type, model) {
|
|
16013
|
+
if (type === "session.model.selected" && expected.get(sessionID) === key(model)) {
|
|
16014
|
+
expected.delete(sessionID);
|
|
16015
|
+
return true;
|
|
16016
|
+
}
|
|
16017
|
+
if ([
|
|
16018
|
+
"session.model.selected",
|
|
16019
|
+
"session.agent.selected",
|
|
16020
|
+
"session.execution.interrupted",
|
|
16021
|
+
"session.deleted"
|
|
16022
|
+
].includes(type)) {
|
|
16023
|
+
owned.delete(sessionID);
|
|
16024
|
+
expected.delete(sessionID);
|
|
16025
|
+
invalidate(sessionID);
|
|
16026
|
+
if (type === "session.deleted") {
|
|
16027
|
+
if (controls.has(sessionID)) deletedControls.add(sessionID);
|
|
16028
|
+
pinned.delete(sessionID);
|
|
16029
|
+
reasons.delete(sessionID);
|
|
16030
|
+
return pinStore.remove(sessionID).then(() => false);
|
|
16031
|
+
}
|
|
16032
|
+
}
|
|
16033
|
+
return false;
|
|
16034
|
+
},
|
|
16035
|
+
async main(sessionID, session, pending) {
|
|
16036
|
+
if (disposed || !current() || session.parentID || !session.agent || busy.has(sessionID))
|
|
16037
|
+
return;
|
|
16038
|
+
if (busy.size >= 64) return;
|
|
16039
|
+
busy.add(sessionID);
|
|
16040
|
+
const generation = versions.get(sessionID) ?? 0;
|
|
16041
|
+
try {
|
|
16042
|
+
if (controls.has(sessionID) || await isPinned(sessionID)) return;
|
|
16043
|
+
if (disposed || controls.has(sessionID) || pinned.has(sessionID) || (versions.get(sessionID) ?? 0) !== generation)
|
|
16044
|
+
return;
|
|
16045
|
+
const route = routes[session.agent];
|
|
16046
|
+
if (!route) return;
|
|
16047
|
+
const previous = owned.get(sessionID);
|
|
16048
|
+
if (session.model && (!previous || previous.agent !== session.agent || previous.model !== key(session.model)))
|
|
16049
|
+
return;
|
|
16050
|
+
if (!owned.has(sessionID) && owned.size >= 1024) return;
|
|
16051
|
+
const choose = await evaluate(route, pending);
|
|
16052
|
+
if (disposed || !current() || (versions.get(sessionID) ?? 0) !== generation) return;
|
|
16053
|
+
const latest = await ctx.session.get({ sessionID });
|
|
16054
|
+
if (disposed || controls.has(sessionID) || pinned.has(sessionID) || latest.agent !== session.agent || key(latest.model) !== key(session.model) || (versions.get(sessionID) ?? 0) !== generation || !current())
|
|
16055
|
+
return;
|
|
16056
|
+
const decision = choose();
|
|
16057
|
+
const { choice } = decision;
|
|
16058
|
+
if (!choice) {
|
|
16059
|
+
reason(sessionID, decision.reason, session.model);
|
|
16060
|
+
return;
|
|
16061
|
+
}
|
|
16062
|
+
const model = {
|
|
16063
|
+
...quotaCandidate(choice),
|
|
16064
|
+
...choice.variant && choice.variant !== "default" ? { variant: choice.variant } : {}
|
|
16065
|
+
};
|
|
16066
|
+
if (key(model) !== key(session.model) && (session.model || choice.model !== route.model || choice.variant !== route.variant)) {
|
|
16067
|
+
expected.set(sessionID, key(model));
|
|
16068
|
+
try {
|
|
16069
|
+
await ctx.session.switchModel({ sessionID, model });
|
|
16070
|
+
} catch {
|
|
16071
|
+
expected.delete(sessionID);
|
|
16072
|
+
return;
|
|
16073
|
+
}
|
|
16074
|
+
}
|
|
16075
|
+
if (disposed || controls.has(sessionID) || pinned.has(sessionID) || (versions.get(sessionID) ?? 0) !== generation)
|
|
16076
|
+
return;
|
|
16077
|
+
owned.set(sessionID, { agent: session.agent, model: key(model) });
|
|
16078
|
+
reason(sessionID, decision.reason, model);
|
|
16079
|
+
return model;
|
|
16080
|
+
} finally {
|
|
16081
|
+
busy.delete(sessionID);
|
|
16082
|
+
versions.delete(sessionID);
|
|
16083
|
+
}
|
|
16084
|
+
},
|
|
16085
|
+
async child(event) {
|
|
16086
|
+
if (disposed || !current() || event.tool !== "subagent" || !event.input || typeof event.input !== "object")
|
|
16087
|
+
return;
|
|
16088
|
+
const input = event.input;
|
|
16089
|
+
if ("model" in input || "sessionID" in input || "session_id" in input || "task_id" in input || typeof input.agent !== "string")
|
|
16090
|
+
return;
|
|
16091
|
+
const route = routes[input.agent];
|
|
16092
|
+
if (!route) return;
|
|
16093
|
+
const originalAgent = input.agent;
|
|
16094
|
+
const choose = await evaluate(route);
|
|
16095
|
+
const { choice } = choose();
|
|
16096
|
+
if (!choice || disposed || !current() || input.agent !== originalAgent || "model" in input)
|
|
16097
|
+
return;
|
|
16098
|
+
input.model = choice.model + (choice.variant && choice.variant !== "default" ? `#${choice.variant}` : "");
|
|
16099
|
+
},
|
|
16100
|
+
async dispose() {
|
|
16101
|
+
disposed = true;
|
|
16102
|
+
query.dispose();
|
|
16103
|
+
owned.clear();
|
|
16104
|
+
expected.clear();
|
|
16105
|
+
versions.clear();
|
|
16106
|
+
controls.clear();
|
|
16107
|
+
pinned.clear();
|
|
16108
|
+
reasons.clear();
|
|
16109
|
+
await pinStore.drain();
|
|
16110
|
+
}
|
|
16111
|
+
};
|
|
16112
|
+
}
|
|
16113
|
+
|
|
15734
16114
|
// src/v2.ts
|
|
15735
16115
|
var variant = (value) => value === "default" ? void 0 : value ?? void 0;
|
|
15736
16116
|
async function setupV2(ctx) {
|
|
@@ -15793,11 +16173,50 @@ async function setupV2(ctx) {
|
|
|
15793
16173
|
const turns = /* @__PURE__ */ new Map();
|
|
15794
16174
|
const kinds = /* @__PURE__ */ new Map();
|
|
15795
16175
|
const ownSelections = /* @__PURE__ */ new Map();
|
|
16176
|
+
const quota = createQuotaAdmission(ctx, routes, () => state() === initial);
|
|
16177
|
+
if (quota) {
|
|
16178
|
+
await ctx.tool.transform((editor) => {
|
|
16179
|
+
const input = { type: "object", properties: {}, additionalProperties: false };
|
|
16180
|
+
for (const action of ["pin", "auto"])
|
|
16181
|
+
editor.add({
|
|
16182
|
+
name: `router_${action}`,
|
|
16183
|
+
description: action === "pin" ? "Only on an explicit user request: pin this session's current model and disable automatic quota/reactive routing. Takes no model or session arguments." : "Only on an explicit user request: resume quota-aware routing for this session on its NEXT explicit user turn. Does not send a prompt or switch immediately.",
|
|
16184
|
+
input,
|
|
16185
|
+
async execute(_input, context) {
|
|
16186
|
+
await quota.control(context.sessionID, action, async () => {
|
|
16187
|
+
turns.delete(context.sessionID);
|
|
16188
|
+
kinds.delete(context.sessionID);
|
|
16189
|
+
await failover.event({
|
|
16190
|
+
event: {
|
|
16191
|
+
type: "session.next.model.switched",
|
|
16192
|
+
properties: { sessionID: context.sessionID }
|
|
16193
|
+
}
|
|
16194
|
+
});
|
|
16195
|
+
});
|
|
16196
|
+
return { content: JSON.stringify(await quota.status(context.sessionID)) };
|
|
16197
|
+
}
|
|
16198
|
+
});
|
|
16199
|
+
editor.add({
|
|
16200
|
+
name: "router_routing_status",
|
|
16201
|
+
description: "Show this session's automatic/pinned routing mode, current model, and routing reason.",
|
|
16202
|
+
input,
|
|
16203
|
+
async execute(_input, context) {
|
|
16204
|
+
return { content: JSON.stringify(await quota.status(context.sessionID)) };
|
|
16205
|
+
}
|
|
16206
|
+
});
|
|
16207
|
+
});
|
|
16208
|
+
}
|
|
15796
16209
|
const controller = new AbortController();
|
|
15797
16210
|
const events = (async () => {
|
|
15798
16211
|
for await (const event of ctx.event.subscribe({ signal: controller.signal })) {
|
|
15799
16212
|
if (!("sessionID" in event.data)) continue;
|
|
15800
16213
|
const sessionID = String(event.data.sessionID);
|
|
16214
|
+
if (await quota?.event(
|
|
16215
|
+
sessionID,
|
|
16216
|
+
event.type,
|
|
16217
|
+
event.type === "session.model.selected" ? event.data.model : void 0
|
|
16218
|
+
))
|
|
16219
|
+
continue;
|
|
15801
16220
|
if (!turns.has(sessionID)) continue;
|
|
15802
16221
|
if (event.type === "session.model.selected") {
|
|
15803
16222
|
const model = event.data.model;
|
|
@@ -15825,6 +16244,7 @@ async function setupV2(ctx) {
|
|
|
15825
16244
|
await ctx.session.hook("model.request", (event) => {
|
|
15826
16245
|
if (turns.has(event.sessionID)) kinds.set(event.sessionID, event.kind);
|
|
15827
16246
|
});
|
|
16247
|
+
if (quota) await ctx.tool.hook("execute.before", (event) => quota.child(event));
|
|
15828
16248
|
await ctx.session.hook("prompt", async (event) => {
|
|
15829
16249
|
if (turns.get(event.sessionID)?.id === event.messageID) return;
|
|
15830
16250
|
if (state() !== initial) {
|
|
@@ -15833,6 +16253,40 @@ async function setupV2(ctx) {
|
|
|
15833
16253
|
return;
|
|
15834
16254
|
}
|
|
15835
16255
|
const session = await ctx.session.get({ sessionID: event.sessionID });
|
|
16256
|
+
if (turns.get(event.sessionID)?.id === event.messageID) return;
|
|
16257
|
+
if (quota) {
|
|
16258
|
+
if (session.parentID && await quota.isPinned(event.sessionID)) {
|
|
16259
|
+
turns.delete(event.sessionID);
|
|
16260
|
+
return;
|
|
16261
|
+
}
|
|
16262
|
+
const pending = failover.pending(event.sessionID);
|
|
16263
|
+
const selected = session.parentID ? session.model : await quota.main(
|
|
16264
|
+
event.sessionID,
|
|
16265
|
+
session,
|
|
16266
|
+
pending ? {
|
|
16267
|
+
providerID: pending.providerID,
|
|
16268
|
+
id: pending.modelID,
|
|
16269
|
+
variant: pending.variant
|
|
16270
|
+
} : void 0
|
|
16271
|
+
);
|
|
16272
|
+
if (!selected || !session.agent || !routes[session.agent]) {
|
|
16273
|
+
turns.delete(event.sessionID);
|
|
16274
|
+
return;
|
|
16275
|
+
}
|
|
16276
|
+
const message2 = {
|
|
16277
|
+
id: event.messageID,
|
|
16278
|
+
agent: session.agent,
|
|
16279
|
+
model: {
|
|
16280
|
+
providerID: selected.providerID,
|
|
16281
|
+
modelID: selected.id,
|
|
16282
|
+
variant: variant(selected.variant)
|
|
16283
|
+
}
|
|
16284
|
+
};
|
|
16285
|
+
failover.admit(event.sessionID, message2);
|
|
16286
|
+
if (!failover.active(event.sessionID)) return;
|
|
16287
|
+
turns.set(event.sessionID, message2);
|
|
16288
|
+
return;
|
|
16289
|
+
}
|
|
15836
16290
|
if (!session.agent || !session.model || !routes[session.agent]) return;
|
|
15837
16291
|
const message = {
|
|
15838
16292
|
id: event.messageID,
|
|
@@ -15909,6 +16363,7 @@ async function setupV2(ctx) {
|
|
|
15909
16363
|
});
|
|
15910
16364
|
return async () => {
|
|
15911
16365
|
controller.abort();
|
|
16366
|
+
await quota?.dispose();
|
|
15912
16367
|
failover.disable();
|
|
15913
16368
|
turns.clear();
|
|
15914
16369
|
kinds.clear();
|
|
@@ -15918,7 +16373,7 @@ async function setupV2(ctx) {
|
|
|
15918
16373
|
}
|
|
15919
16374
|
|
|
15920
16375
|
// src/version.ts
|
|
15921
|
-
var VERSION = "2.0
|
|
16376
|
+
var VERSION = "2.1.0";
|
|
15922
16377
|
|
|
15923
16378
|
// src/plugin.ts
|
|
15924
16379
|
var tool = Object.assign(
|