@dylanrussell/agent-router 2.1.1 → 2.2.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/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, key2, getter) {
732
+ function defineLazy(object2, key3, getter) {
733
733
  let value = void 0;
734
- Object.defineProperty(object2, key2, {
734
+ Object.defineProperty(object2, key3, {
735
735
  get() {
736
736
  if (value === EVALUATING) {
737
737
  return void 0;
@@ -743,7 +743,7 @@ function defineLazy(object2, key2, getter) {
743
743
  return value;
744
744
  },
745
745
  set(v) {
746
- Object.defineProperty(object2, key2, {
746
+ Object.defineProperty(object2, key3, {
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, key2) => acc?.[key2], obj);
779
+ return path8.reduce((acc, key3) => acc?.[key3], obj);
780
780
  }
781
781
  function promiseAllObject(promisesObj) {
782
782
  const keys = Object.keys(promisesObj);
783
- const promises = keys.map((key2) => promisesObj[key2]);
783
+ const promises = keys.map((key3) => promisesObj[key3]);
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 key2 in data) {
856
- if (Object.prototype.hasOwnProperty.call(data, key2)) {
855
+ for (const key3 in data) {
856
+ if (Object.prototype.hasOwnProperty.call(data, key3)) {
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 key2 in mask) {
1007
- if (!(key2 in currDef.shape)) {
1008
- throw new Error(`Unrecognized key: "${key2}"`);
1006
+ for (const key3 in mask) {
1007
+ if (!(key3 in currDef.shape)) {
1008
+ throw new Error(`Unrecognized key: "${key3}"`);
1009
1009
  }
1010
- if (!mask[key2])
1010
+ if (!mask[key3])
1011
1011
  continue;
1012
- newShape[key2] = currDef.shape[key2];
1012
+ newShape[key3] = currDef.shape[key3];
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 key2 in mask) {
1032
- if (!(key2 in currDef.shape)) {
1033
- throw new Error(`Unrecognized key: "${key2}"`);
1031
+ for (const key3 in mask) {
1032
+ if (!(key3 in currDef.shape)) {
1033
+ throw new Error(`Unrecognized key: "${key3}"`);
1034
1034
  }
1035
- if (!mask[key2])
1035
+ if (!mask[key3])
1036
1036
  continue;
1037
- delete newShape[key2];
1037
+ delete newShape[key3];
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 key2 in shape) {
1055
- if (Object.getOwnPropertyDescriptor(existingShape, key2) !== void 0) {
1054
+ for (const key3 in shape) {
1055
+ if (Object.getOwnPropertyDescriptor(existingShape, key3) !== 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 key2 in mask) {
1112
- if (!(key2 in oldShape)) {
1113
- throw new Error(`Unrecognized key: "${key2}"`);
1111
+ for (const key3 in mask) {
1112
+ if (!(key3 in oldShape)) {
1113
+ throw new Error(`Unrecognized key: "${key3}"`);
1114
1114
  }
1115
- if (!mask[key2])
1115
+ if (!mask[key3])
1116
1116
  continue;
1117
- shape[key2] = Class2 ? new Class2({
1117
+ shape[key3] = Class2 ? new Class2({
1118
1118
  type: "optional",
1119
- innerType: oldShape[key2]
1120
- }) : oldShape[key2];
1119
+ innerType: oldShape[key3]
1120
+ }) : oldShape[key3];
1121
1121
  }
1122
1122
  } else {
1123
- for (const key2 in oldShape) {
1124
- shape[key2] = Class2 ? new Class2({
1123
+ for (const key3 in oldShape) {
1124
+ shape[key3] = Class2 ? new Class2({
1125
1125
  type: "optional",
1126
- innerType: oldShape[key2]
1127
- }) : oldShape[key2];
1126
+ innerType: oldShape[key3]
1127
+ }) : oldShape[key3];
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 key2 in mask) {
1144
- if (!(key2 in shape)) {
1145
- throw new Error(`Unrecognized key: "${key2}"`);
1143
+ for (const key3 in mask) {
1144
+ if (!(key3 in shape)) {
1145
+ throw new Error(`Unrecognized key: "${key3}"`);
1146
1146
  }
1147
- if (!mask[key2])
1147
+ if (!mask[key3])
1148
1148
  continue;
1149
- shape[key2] = new Class2({
1149
+ shape[key3] = new Class2({
1150
1150
  type: "nonoptional",
1151
- innerType: oldShape[key2]
1151
+ innerType: oldShape[key3]
1152
1152
  });
1153
1153
  }
1154
1154
  } else {
1155
- for (const key2 in oldShape) {
1156
- shape[key2] = new Class2({
1155
+ for (const key3 in oldShape) {
1156
+ shape[key3] = new Class2({
1157
1157
  type: "nonoptional",
1158
- innerType: oldShape[key2]
1158
+ innerType: oldShape[key3]
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, key2, input, isOptionalIn, isOptionalOut) {
2940
- const isPresent = key2 in input;
2939
+ function handlePropertyResult(result, final, key3, input, isOptionalIn, isOptionalOut) {
2940
+ const isPresent = key3 in input;
2941
2941
  if (result.issues.length) {
2942
2942
  if (isOptionalIn && isOptionalOut && !isPresent) {
2943
2943
  return;
2944
2944
  }
2945
- final.issues.push(...prefixIssues(key2, result.issues));
2945
+ final.issues.push(...prefixIssues(key3, result.issues));
2946
2946
  }
2947
2947
  if (!isPresent && !isOptionalIn) {
2948
2948
  if (!result.issues.length) {
@@ -2950,17 +2950,17 @@ function handlePropertyResult(result, final, key2, input, isOptionalIn, isOption
2950
2950
  code: "invalid_type",
2951
2951
  expected: "nonoptional",
2952
2952
  input: void 0,
2953
- path: [key2]
2953
+ path: [key3]
2954
2954
  });
2955
2955
  }
2956
2956
  return;
2957
2957
  }
2958
2958
  if (result.value === void 0) {
2959
2959
  if (isPresent) {
2960
- final.value[key2] = void 0;
2960
+ final.value[key3] = void 0;
2961
2961
  }
2962
2962
  } else {
2963
- final.value[key2] = result.value;
2963
+ final.value[key3] = 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 key2 in input) {
2990
- if (key2 === "__proto__")
2989
+ for (const key3 in input) {
2990
+ if (key3 === "__proto__")
2991
2991
  continue;
2992
- if (keySet.has(key2))
2992
+ if (keySet.has(key3))
2993
2993
  continue;
2994
2994
  if (t === "never") {
2995
- unrecognized.push(key2);
2995
+ unrecognized.push(key3);
2996
2996
  continue;
2997
2997
  }
2998
- const r = _catchall.run({ value: input[key2], issues: [] }, ctx);
2998
+ const r = _catchall.run({ value: input[key3], issues: [] }, ctx);
2999
2999
  if (r instanceof Promise) {
3000
- proms.push(r.then((r2) => handlePropertyResult(r2, payload, key2, input, isOptionalIn, isOptionalOut)));
3000
+ proms.push(r.then((r2) => handlePropertyResult(r2, payload, key3, input, isOptionalIn, isOptionalOut)));
3001
3001
  } else {
3002
- handlePropertyResult(r, payload, key2, input, isOptionalIn, isOptionalOut);
3002
+ handlePropertyResult(r, payload, key3, 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 key2 in shape) {
3039
- const field = shape[key2]._zod;
3038
+ for (const key3 in shape) {
3039
+ const field = shape[key3]._zod;
3040
3040
  if (field.values) {
3041
- propValues[key2] ?? (propValues[key2] = /* @__PURE__ */ new Set());
3041
+ propValues[key3] ?? (propValues[key3] = /* @__PURE__ */ new Set());
3042
3042
  for (const v of field.values)
3043
- propValues[key2].add(v);
3043
+ propValues[key3].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 key2 of value.keys) {
3067
- const el = shape[key2];
3066
+ for (const key3 of value.keys) {
3067
+ const el = shape[key3];
3068
3068
  const isOptionalIn = el._zod.optin === "optional";
3069
3069
  const isOptionalOut = el._zod.optout === "optional";
3070
- const r = el._zod.run({ value: input[key2], issues: [] }, ctx);
3070
+ const r = el._zod.run({ value: input[key3], issues: [] }, ctx);
3071
3071
  if (r instanceof Promise) {
3072
- proms.push(r.then((r2) => handlePropertyResult(r2, payload, key2, input, isOptionalIn, isOptionalOut)));
3072
+ proms.push(r.then((r2) => handlePropertyResult(r2, payload, key3, input, isOptionalIn, isOptionalOut)));
3073
3073
  } else {
3074
- handlePropertyResult(r, payload, key2, input, isOptionalIn, isOptionalOut);
3074
+ handlePropertyResult(r, payload, key3, 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 = (key2) => {
3091
- const k = esc(key2);
3090
+ const parseStr = (key3) => {
3091
+ const k = esc(key3);
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 key2 of normalized.keys) {
3098
- ids[key2] = `key_${counter++}`;
3097
+ for (const key3 of normalized.keys) {
3098
+ ids[key3] = `key_${counter++}`;
3099
3099
  }
3100
3100
  doc.write(`const newResult = {};`);
3101
- for (const key2 of normalized.keys) {
3102
- const id = ids[key2];
3103
- const k = esc(key2);
3104
- const schema = shape[key2];
3101
+ for (const key3 of normalized.keys) {
3102
+ const id = ids[key3];
3103
+ const k = esc(key3);
3104
+ const schema = shape[key3];
3105
3105
  const isOptionalIn = schema?._zod?.optin === "optional";
3106
3106
  const isOptionalOut = schema?._zod?.optout === "optional";
3107
- doc.write(`const ${id} = ${parseStr(key2)};`);
3107
+ doc.write(`const ${id} = ${parseStr(key3)};`);
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((key2) => bKeys.indexOf(key2) !== -1);
3419
+ const sharedKeys = Object.keys(a).filter((key3) => bKeys.indexOf(key3) !== -1);
3420
3420
  const newObj = { ...a, ...b };
3421
- for (const key2 of sharedKeys) {
3422
- const sharedValue = mergeValues(a[key2], b[key2]);
3421
+ for (const key3 of sharedKeys) {
3422
+ const sharedValue = mergeValues(a[key3], b[key3]);
3423
3423
  if (!sharedValue.valid) {
3424
3424
  return {
3425
3425
  valid: false,
3426
- mergeErrorPath: [key2, ...sharedValue.mergeErrorPath]
3426
+ mergeErrorPath: [key3, ...sharedValue.mergeErrorPath]
3427
3427
  };
3428
3428
  }
3429
- newObj[key2] = sharedValue.data;
3429
+ newObj[key3] = 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, key2) {
3564
+ function getTupleOptStart(items, key3) {
3565
3565
  for (let i = items.length - 1; i >= 0; i--) {
3566
- if (items[i]._zod[key2] !== "optional")
3566
+ if (items[i]._zod[key3] !== "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 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);
3617
+ for (const key3 of values) {
3618
+ if (typeof key3 === "string" || typeof key3 === "number" || typeof key3 === "symbol") {
3619
+ recordKeys.add(typeof key3 === "number" ? key3.toString() : key3);
3620
+ const keyResult = def.keyType._zod.run({ value: key3, 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: key2,
3630
- path: [key2],
3629
+ input: key3,
3630
+ path: [key3],
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[key2], issues: [] }, ctx);
3636
+ const result = def.valueType._zod.run({ value: input[key3], 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(key2, result2.issues));
3640
+ payload.issues.push(...prefixIssues(key3, 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(key2, result.issues));
3646
+ payload.issues.push(...prefixIssues(key3, result.issues));
3647
3647
  }
3648
3648
  payload.value[outKey] = result.value;
3649
3649
  }
3650
3650
  }
3651
3651
  }
3652
3652
  let unrecognized;
3653
- for (const key2 in input) {
3654
- if (!recordKeys.has(key2)) {
3653
+ for (const key3 in input) {
3654
+ if (!recordKeys.has(key3)) {
3655
3655
  unrecognized = unrecognized ?? [];
3656
- unrecognized.push(key2);
3656
+ unrecognized.push(key3);
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 key2 of Reflect.ownKeys(input)) {
3670
- if (key2 === "__proto__")
3669
+ for (const key3 of Reflect.ownKeys(input)) {
3670
+ if (key3 === "__proto__")
3671
3671
  continue;
3672
- if (!Object.prototype.propertyIsEnumerable.call(input, key2))
3672
+ if (!Object.prototype.propertyIsEnumerable.call(input, key3))
3673
3673
  continue;
3674
- let keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
3674
+ let keyResult = def.keyType._zod.run({ value: key3, 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 key2 === "string" && number.test(key2) && keyResult.issues.length;
3678
+ const checkNumericKey = typeof key3 === "string" && number.test(key3) && keyResult.issues.length;
3679
3679
  if (checkNumericKey) {
3680
- const retryResult = def.keyType._zod.run({ value: Number(key2), issues: [] }, ctx);
3680
+ const retryResult = def.keyType._zod.run({ value: Number(key3), 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[key2] = input[key2];
3690
+ payload.value[key3] = input[key3];
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: key2,
3697
- path: [key2],
3696
+ input: key3,
3697
+ path: [key3],
3698
3698
  inst
3699
3699
  });
3700
3700
  }
3701
3701
  continue;
3702
3702
  }
3703
- const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
3703
+ const result = def.valueType._zod.run({ value: input[key3], 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(key2, result2.issues));
3707
+ payload.issues.push(...prefixIssues(key3, 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(key2, result.issues));
3713
+ payload.issues.push(...prefixIssues(key3, 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 [key2, value] of input) {
3741
- const keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
3740
+ for (const [key3, value] of input) {
3741
+ const keyResult = def.keyType._zod.run({ value: key3, 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, key2, input, inst, ctx);
3745
+ handleMapResult(keyResult2, valueResult2, payload, key3, input, inst, ctx);
3746
3746
  }));
3747
3747
  } else {
3748
- handleMapResult(keyResult, valueResult, payload, key2, input, inst, ctx);
3748
+ handleMapResult(keyResult, valueResult, payload, key3, 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, key2, input, inst, ctx) {
3756
+ function handleMapResult(keyResult, valueResult, final, key3, input, inst, ctx) {
3757
3757
  if (keyResult.issues.length) {
3758
- if (propertyKeyTypes.has(typeof key2)) {
3759
- final.issues.push(...prefixIssues(key2, keyResult.issues));
3758
+ if (propertyKeyTypes.has(typeof key3)) {
3759
+ final.issues.push(...prefixIssues(key3, keyResult.issues));
3760
3760
  } else {
3761
3761
  final.issues.push({
3762
3762
  code: "invalid_key",
@@ -3768,15 +3768,15 @@ function handleMapResult(keyResult, valueResult, final, key2, input, inst, ctx)
3768
3768
  }
3769
3769
  }
3770
3770
  if (valueResult.issues.length) {
3771
- if (propertyKeyTypes.has(typeof key2)) {
3772
- final.issues.push(...prefixIssues(key2, valueResult.issues));
3771
+ if (propertyKeyTypes.has(typeof key3)) {
3772
+ final.issues.push(...prefixIssues(key3, 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: key2,
3779
+ key: key3,
3780
3780
  issues: valueResult.issues.map((iss) => finalizeIssue(iss, ctx, config()))
3781
3781
  });
3782
3782
  }
@@ -11532,15 +11532,15 @@ function extractDefs(ctx, schema) {
11532
11532
  return;
11533
11533
  }
11534
11534
  const seen = entry[1];
11535
- const { ref, defId } = makeURI(entry);
11535
+ const { ref: ref2, defId } = makeURI(entry);
11536
11536
  seen.def = { ...seen.schema };
11537
11537
  if (defId)
11538
11538
  seen.defId = defId;
11539
11539
  const schema2 = seen.schema;
11540
- for (const key2 in schema2) {
11541
- delete schema2[key2];
11540
+ for (const key3 in schema2) {
11541
+ delete schema2[key3];
11542
11542
  }
11543
- schema2.$ref = ref;
11543
+ schema2.$ref = ref2;
11544
11544
  };
11545
11545
  if (ctx.cycles === "throw") {
11546
11546
  for (const entry of ctx.seen.entries()) {
@@ -11592,11 +11592,11 @@ function finalize(ctx, schema) {
11592
11592
  return;
11593
11593
  const schema2 = seen.def ?? seen.schema;
11594
11594
  const _cached = { ...schema2 };
11595
- const ref = seen.ref;
11595
+ const ref2 = seen.ref;
11596
11596
  seen.ref = null;
11597
- if (ref) {
11598
- flattenRef(ref);
11599
- const refSeen = ctx.seen.get(ref);
11597
+ if (ref2) {
11598
+ flattenRef(ref2);
11599
+ const refSeen = ctx.seen.get(ref2);
11600
11600
  const refSchema = refSeen.schema;
11601
11601
  if (refSchema.$ref && (ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0")) {
11602
11602
  schema2.allOf = schema2.allOf ?? [];
@@ -11605,38 +11605,38 @@ function finalize(ctx, schema) {
11605
11605
  Object.assign(schema2, refSchema);
11606
11606
  }
11607
11607
  Object.assign(schema2, _cached);
11608
- const isParentRef = zodSchema._zod.parent === ref;
11608
+ const isParentRef = zodSchema._zod.parent === ref2;
11609
11609
  if (isParentRef) {
11610
- for (const key2 in schema2) {
11611
- if (key2 === "$ref" || key2 === "allOf")
11610
+ for (const key3 in schema2) {
11611
+ if (key3 === "$ref" || key3 === "allOf")
11612
11612
  continue;
11613
- if (!(key2 in _cached)) {
11614
- delete schema2[key2];
11613
+ if (!(key3 in _cached)) {
11614
+ delete schema2[key3];
11615
11615
  }
11616
11616
  }
11617
11617
  }
11618
11618
  if (refSchema.$ref && refSeen.def) {
11619
- for (const key2 in schema2) {
11620
- if (key2 === "$ref" || key2 === "allOf")
11619
+ for (const key3 in schema2) {
11620
+ if (key3 === "$ref" || key3 === "allOf")
11621
11621
  continue;
11622
- if (key2 in refSeen.def && JSON.stringify(schema2[key2]) === JSON.stringify(refSeen.def[key2])) {
11623
- delete schema2[key2];
11622
+ if (key3 in refSeen.def && JSON.stringify(schema2[key3]) === JSON.stringify(refSeen.def[key3])) {
11623
+ delete schema2[key3];
11624
11624
  }
11625
11625
  }
11626
11626
  }
11627
11627
  }
11628
11628
  const parent = zodSchema._zod.parent;
11629
- if (parent && parent !== ref) {
11629
+ if (parent && parent !== ref2) {
11630
11630
  flattenRef(parent);
11631
11631
  const parentSeen = ctx.seen.get(parent);
11632
11632
  if (parentSeen?.schema.$ref) {
11633
11633
  schema2.$ref = parentSeen.schema.$ref;
11634
11634
  if (parentSeen.def) {
11635
- for (const key2 in schema2) {
11636
- if (key2 === "$ref" || key2 === "allOf")
11635
+ for (const key3 in schema2) {
11636
+ if (key3 === "$ref" || key3 === "allOf")
11637
11637
  continue;
11638
- if (key2 in parentSeen.def && JSON.stringify(schema2[key2]) === JSON.stringify(parentSeen.def[key2])) {
11639
- delete schema2[key2];
11638
+ if (key3 in parentSeen.def && JSON.stringify(schema2[key3]) === JSON.stringify(parentSeen.def[key3])) {
11639
+ delete schema2[key3];
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 key2 in def.shape) {
11741
- if (isTransforming(def.shape[key2], ctx))
11740
+ for (const key3 in def.shape) {
11741
+ if (isTransforming(def.shape[key3], 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 key2 in shape) {
12031
- json2.properties[key2] = process2(shape[key2], ctx, {
12030
+ for (const key3 in shape) {
12031
+ json2.properties[key3] = process2(shape[key3], ctx, {
12032
12032
  ...params,
12033
- path: [...params.path, "properties", key2]
12033
+ path: [...params.path, "properties", key3]
12034
12034
  });
12035
12035
  }
12036
12036
  const allKeys = new Set(Object.keys(shape));
12037
- const requiredKeys = new Set([...allKeys].filter((key2) => {
12038
- const v = def.shape[key2]._zod;
12037
+ const requiredKeys = new Set([...allKeys].filter((key3) => {
12038
+ const v = def.shape[key3]._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 [key2, schema] = entry;
12304
+ const [key3, schema] = entry;
12305
12305
  extractDefs(ctx2, schema);
12306
- schemas[key2] = finalize(ctx2, schema);
12306
+ schemas[key3] = 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 key2 in methods) {
12713
- const fn = methods[key2];
12714
- Object.defineProperty(proto, key2, {
12712
+ for (const key3 in methods) {
12713
+ const fn = methods[key3];
12714
+ Object.defineProperty(proto, key3, {
12715
12715
  configurable: true,
12716
12716
  enumerable: false,
12717
12717
  get() {
12718
12718
  const bound = fn.bind(this);
12719
- Object.defineProperty(this, key2, {
12719
+ Object.defineProperty(this, key3, {
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, key2, {
12728
+ Object.defineProperty(this, key3, {
12729
12729
  configurable: true,
12730
12730
  writable: true,
12731
12731
  enumerable: true,
@@ -14103,23 +14103,23 @@ function detectVersion(schema, defaultTarget) {
14103
14103
  }
14104
14104
  return defaultTarget ?? "draft-2020-12";
14105
14105
  }
14106
- function resolveRef(ref, ctx) {
14107
- if (!ref.startsWith("#")) {
14106
+ function resolveRef(ref2, ctx) {
14107
+ if (!ref2.startsWith("#")) {
14108
14108
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14109
14109
  }
14110
- const path8 = ref.slice(1).split("/").filter(Boolean);
14110
+ const path8 = ref2.slice(1).split("/").filter(Boolean);
14111
14111
  if (path8.length === 0) {
14112
14112
  return ctx.rootSchema;
14113
14113
  }
14114
14114
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14115
14115
  if (path8[0] === defsKey) {
14116
- const key2 = path8[1];
14117
- if (!key2 || !ctx.defs[key2]) {
14118
- throw new Error(`Reference not found: ${ref}`);
14116
+ const key3 = path8[1];
14117
+ if (!key3 || !ctx.defs[key3]) {
14118
+ throw new Error(`Reference not found: ${ref2}`);
14119
14119
  }
14120
- return ctx.defs[key2];
14120
+ return ctx.defs[key3];
14121
14121
  }
14122
- throw new Error(`Reference not found: ${ref}`);
14122
+ throw new Error(`Reference not found: ${ref2}`);
14123
14123
  }
14124
14124
  function convertBaseSchema(schema, ctx) {
14125
14125
  if (schema.not !== void 0) {
@@ -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 [key2, propSchema] of Object.entries(properties)) {
14306
+ for (const [key3, propSchema] of Object.entries(properties)) {
14307
14307
  const propZodSchema = convertSchema(propSchema, ctx);
14308
- shape[key2] = requiredSet.has(key2) ? propZodSchema : propZodSchema.optional();
14308
+ shape[key3] = requiredSet.has(key3) ? 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 key2 of coreMetadataKeys) {
14450
- if (key2 in schema) {
14451
- extraMeta[key2] = schema[key2];
14449
+ for (const key3 of coreMetadataKeys) {
14450
+ if (key3 in schema) {
14451
+ extraMeta[key3] = schema[key3];
14452
14452
  }
14453
14453
  }
14454
14454
  const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
14455
- for (const key2 of contentMetadataKeys) {
14456
- if (key2 in schema) {
14457
- extraMeta[key2] = schema[key2];
14455
+ for (const key3 of contentMetadataKeys) {
14456
+ if (key3 in schema) {
14457
+ extraMeta[key3] = schema[key3];
14458
14458
  }
14459
14459
  }
14460
- for (const key2 of Object.keys(schema)) {
14461
- if (!RECOGNIZED_KEYS.has(key2)) {
14462
- extraMeta[key2] = schema[key2];
14460
+ for (const key3 of Object.keys(schema)) {
14461
+ if (!RECOGNIZED_KEYS.has(key3)) {
14462
+ extraMeta[key3] = schema[key3];
14463
14463
  }
14464
14464
  }
14465
14465
  if (Object.keys(extraMeta).length > 0) {
@@ -15164,29 +15164,29 @@ function parseMapping(lines, startIdx, indent) {
15164
15164
  i++;
15165
15165
  continue;
15166
15166
  }
15167
- const key2 = stripKeyQuotes(line.text.slice(0, colon).trim());
15168
- if (key2 === "") {
15167
+ const key3 = stripKeyQuotes(line.text.slice(0, colon).trim());
15168
+ if (key3 === "") {
15169
15169
  i++;
15170
15170
  continue;
15171
15171
  }
15172
15172
  const rest = line.text.slice(colon + 1).trim();
15173
15173
  if (rest !== "") {
15174
- out[key2] = parseFlowValue(rest);
15174
+ out[key3] = parseFlowValue(rest);
15175
15175
  i++;
15176
15176
  } else {
15177
15177
  const childIndent = lines[i + 1]?.indent ?? line.indent + 1;
15178
15178
  let j = i + 1;
15179
15179
  while (j < lines.length && (lines[j]?.indent ?? -1) >= childIndent) j++;
15180
15180
  if (j === i + 1) {
15181
- out[key2] = null;
15181
+ out[key3] = null;
15182
15182
  i++;
15183
15183
  } else {
15184
15184
  const childBlock = lines.slice(i + 1, j);
15185
15185
  const firstChild = childBlock[0];
15186
15186
  if (firstChild?.text.trimStart().startsWith("- ")) {
15187
- out[key2] = parseSequence(childBlock, childIndent);
15187
+ out[key3] = parseSequence(childBlock, childIndent);
15188
15188
  } else {
15189
- out[key2] = parseMapping(childBlock, 0, childIndent).value;
15189
+ out[key3] = parseMapping(childBlock, 0, childIndent).value;
15190
15190
  }
15191
15191
  i = j;
15192
15192
  }
@@ -15298,24 +15298,24 @@ function setFrontmatterOptions(content, options) {
15298
15298
  for (let i = 0; i < lines.length; i++) {
15299
15299
  const m = /^([A-Za-z0-9_-]+):[ \t]*(.*)$/.exec(lines[i] ?? "");
15300
15300
  if (!m) continue;
15301
- const key2 = m[1] ?? "";
15302
- if (!(key2 in options)) continue;
15303
- handled.add(key2);
15301
+ const key3 = m[1] ?? "";
15302
+ if (!(key3 in options)) continue;
15303
+ handled.add(key3);
15304
15304
  let end = i + 1;
15305
15305
  while (end < lines.length && /^[ \t]+/.test(lines[end] ?? "")) end++;
15306
- const value = options[key2];
15306
+ const value = options[key3];
15307
15307
  if (value === null || value === void 0) {
15308
15308
  lines.splice(i, end - i);
15309
15309
  i--;
15310
15310
  } else {
15311
- lines.splice(i, end - i, `${key2}: ${serializeOptionValue(value)}`);
15311
+ lines.splice(i, end - i, `${key3}: ${serializeOptionValue(value)}`);
15312
15312
  }
15313
15313
  }
15314
15314
  const appended = [];
15315
- for (const [key2, value] of Object.entries(options)) {
15316
- if (handled.has(key2)) continue;
15315
+ for (const [key3, value] of Object.entries(options)) {
15316
+ if (handled.has(key3)) continue;
15317
15317
  if (value === null || value === void 0) continue;
15318
- appended.push(`${key2}: ${serializeOptionValue(value)}`);
15318
+ appended.push(`${key3}: ${serializeOptionValue(value)}`);
15319
15319
  }
15320
15320
  const nextBlock = appended.length > 0 ? lines.join(eol) + eol + appended.join(eol) : lines.join(eol);
15321
15321
  if (nextBlock === block) return content;
@@ -15753,49 +15753,8 @@ async function captureStack(paths, name, options = {}) {
15753
15753
  return { name, path: dest, agents: Object.keys(agents).length };
15754
15754
  }
15755
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
- }
15756
+ // src/quota-fallback-v2.ts
15757
+ import { createHash } from "crypto";
15799
15758
 
15800
15759
  // src/core/quota-preflight.ts
15801
15760
  import { Rpc } from "@opencode/plugin/rpc";
@@ -15876,12 +15835,301 @@ function createQuotaQuery(query, deadlineMs = 3e3, capacity = 16) {
15876
15835
  };
15877
15836
  }
15878
15837
 
15838
+ // src/quota-fallback-v2.ts
15839
+ var QuotaFallbackOptions = external_exports.object({
15840
+ enabled: external_exports.boolean().default(false),
15841
+ allowPaidFallbacks: external_exports.boolean().default(false),
15842
+ maxSwitches: external_exports.number().int().min(1).max(8).default(8)
15843
+ }).strict();
15844
+ var key = (m) => `${m.providerID}/${m.id}#${m.variant === "default" ? "" : m.variant ?? ""}`;
15845
+ var ref = (m) => ({
15846
+ ...quotaCandidate(m),
15847
+ ...m.variant && m.variant !== "default" ? { variant: m.variant } : {}
15848
+ });
15849
+ var TTL = 5e3;
15850
+ var clock = () => performance.now();
15851
+ var CAP = 1024;
15852
+ var digest = (text) => createHash("sha256").update(text).digest("hex");
15853
+ function createQuotaFallback(ctx, routes, admission, current, selected = () => {
15854
+ }) {
15855
+ const parsed = QuotaFallbackOptions.safeParse(ctx.options?.quotaFallback ?? {});
15856
+ if (!parsed.success || !parsed.data.enabled) return void 0;
15857
+ const options = parsed.data;
15858
+ const query = createQuotaQuery((input, request) => ctx.rpc(UsageQuota).query(input, request));
15859
+ const turns = /* @__PURE__ */ new Map();
15860
+ const observations = /* @__PURE__ */ new Map();
15861
+ const requests = /* @__PURE__ */ new WeakMap();
15862
+ const poisoned = /* @__PURE__ */ new Set();
15863
+ const busy = /* @__PURE__ */ new Set();
15864
+ const tickets = /* @__PURE__ */ new Map();
15865
+ const claiming = /* @__PURE__ */ new Map();
15866
+ let disposed = false;
15867
+ let saturated = false;
15868
+ let childSaturated = false;
15869
+ const poison = (id) => {
15870
+ if (poisoned.has(id) || poisoned.size < CAP) poisoned.add(id);
15871
+ else saturated = true;
15872
+ };
15873
+ const prune = () => {
15874
+ const cutoff = clock() - TTL;
15875
+ for (const [id, value] of observations) {
15876
+ if (value.at >= cutoff) continue;
15877
+ if (value.ambiguous || value.status === void 0 || value.status >= 400) poison(id);
15878
+ observations.delete(id);
15879
+ }
15880
+ for (const [id, value] of tickets) if (value.at < cutoff) tickets.delete(id);
15881
+ };
15882
+ const timer = setInterval(prune, TTL);
15883
+ timer.unref();
15884
+ const stop = (id) => {
15885
+ turns.delete(id);
15886
+ observations.delete(id);
15887
+ poisoned.delete(id);
15888
+ claiming.delete(id);
15889
+ };
15890
+ return {
15891
+ stop,
15892
+ admit(id, agent, model) {
15893
+ stop(id);
15894
+ if (turns.size < CAP)
15895
+ turns.set(id, { agent, model, switches: 0, selected: false, generation: 0 });
15896
+ },
15897
+ // Keep only a digest of the automatic admission, never prompt text.
15898
+ ticket(id, parent, agent, model, prompt) {
15899
+ prune();
15900
+ if (tickets.size < CAP)
15901
+ tickets.set(`${parent}/${id}`, {
15902
+ parent,
15903
+ agent,
15904
+ model,
15905
+ callID: id,
15906
+ promptHash: prompt === void 0 ? void 0 : digest(`You are a subagent spawned by another session.
15907
+ ${prompt}`),
15908
+ at: clock()
15909
+ });
15910
+ else childSaturated = true;
15911
+ },
15912
+ async child(id, agent, model) {
15913
+ if (childSaturated || turns.has(id) || claiming.has(id) || claiming.size >= 64 || disposed || !current())
15914
+ return;
15915
+ prune();
15916
+ const claim = {};
15917
+ claiming.set(id, claim);
15918
+ try {
15919
+ const session = await ctx.session.get({ sessionID: id });
15920
+ if (!session.parentID || session.agent !== agent || !session.model || key(session.model) !== key(model))
15921
+ return;
15922
+ const candidates = [...tickets].filter(([, t]) => t.parent === session.parentID);
15923
+ if (candidates.length !== 1 || await admission.isPinned(id)) return;
15924
+ const messages = await ctx.session.context({ sessionID: session.parentID });
15925
+ const calls = messages.flatMap((m) => "content" in m ? m.content : []);
15926
+ const childMessages = await ctx.session.context({ sessionID: id });
15927
+ const users = childMessages.filter((m) => m.type === "user");
15928
+ const user = users.length === 1 ? users[0] : void 0;
15929
+ if (!user) return;
15930
+ const matched = candidates.filter(
15931
+ ([, t]) => t.agent === agent && t.promptHash && digest(user.text) === t.promptHash && // Positive native association beats a matching automatic prompt fingerprint.
15932
+ !calls.some(
15933
+ (call) => call.name === "subagent" && call.id !== t.callID && call.state?.metadata?.sessionID === id
15934
+ ) && calls.some(
15935
+ (call) => call.id === t.callID && call.name === "subagent" && call.state?.status === "running" && (!call.state.metadata?.sessionID || call.state.metadata.sessionID === id)
15936
+ ) && (!t.model || t.model === `${model.providerID}/${model.id}${model.variant && model.variant !== "default" ? `#${model.variant}` : ""}`)
15937
+ );
15938
+ const match = matched.length === 1 ? matched[0] : void 0;
15939
+ if (!match) return;
15940
+ const latest = await ctx.session.get({ sessionID: id });
15941
+ if (disposed || childSaturated || !current() || claiming.get(id) !== claim || latest.agent !== agent || !latest.model || key(latest.model) !== key(model) || await admission.isPinned(id) || claiming.get(id) !== claim || childSaturated || clock() - match[1].at > TTL)
15942
+ return;
15943
+ tickets.delete(match[0]);
15944
+ if (admission.claim(id, agent, model) && turns.size < CAP) {
15945
+ turns.set(id, { agent, model, switches: 0, selected: false, generation: 0 });
15946
+ selected(id, agent, model, user.id);
15947
+ }
15948
+ } finally {
15949
+ if (claiming.get(id) === claim) claiming.delete(id);
15950
+ }
15951
+ },
15952
+ model(event) {
15953
+ prune();
15954
+ const turn = turns.get(event.sessionID);
15955
+ if (turn) turn.generation++;
15956
+ const previous = observations.get(event.sessionID);
15957
+ if (!previous && observations.size >= CAP) {
15958
+ poison(event.sessionID);
15959
+ return;
15960
+ }
15961
+ if (event.kind !== "primary" || previous?.ambiguous || previous && (previous.status === void 0 || previous.status >= 400)) {
15962
+ poison(event.sessionID);
15963
+ }
15964
+ const observed = {
15965
+ model: key(event.model),
15966
+ agent: event.agent,
15967
+ kind: event.kind,
15968
+ at: clock(),
15969
+ ambiguous: event.kind !== "primary" || poisoned.has(event.sessionID)
15970
+ };
15971
+ try {
15972
+ const url2 = new URL(event.baseURL ?? "");
15973
+ if (!["http:", "https:"].includes(url2.protocol) || url2.username || url2.password || url2.search || url2.hash)
15974
+ observed.ambiguous = true;
15975
+ else {
15976
+ observed.origin = url2.origin;
15977
+ const base = url2.pathname.replace(/\/$/, "");
15978
+ observed.paths = ["/chat/completions", "/responses", "/messages"].map((p) => base + p);
15979
+ }
15980
+ } catch {
15981
+ observed.ambiguous = true;
15982
+ }
15983
+ observations.set(event.sessionID, observed);
15984
+ },
15985
+ request(event) {
15986
+ prune();
15987
+ const observed = observations.get(event.sessionID);
15988
+ if (!observed) return;
15989
+ const url2 = new URL(event.request.url);
15990
+ if (observed.sent || observed.model !== key(event.model) || observed.agent !== event.agent || observed.kind !== event.kind || url2.username || url2.password || url2.search || url2.hash || url2.origin !== observed.origin || !observed.paths?.includes(url2.pathname))
15991
+ observed.ambiguous = true;
15992
+ observed.sent = true;
15993
+ requests.set(event.request, observed);
15994
+ const turn = turns.get(event.sessionID);
15995
+ if (turn?.selected && event.kind === "primary" && key(turn.model) === key(event.model)) {
15996
+ turn.selected = false;
15997
+ admission.reason(event.sessionID, "quota_fallback_attempt_dispatched", event.model);
15998
+ }
15999
+ },
16000
+ response(event) {
16001
+ const observed = observations.get(event.sessionID);
16002
+ if (!observed) return;
16003
+ if (requests.get(event.request) !== observed || observed.model !== key(event.model) || observed.agent !== event.agent || observed.kind !== event.kind)
16004
+ observed.ambiguous = true;
16005
+ else observed.status = event.response.status;
16006
+ },
16007
+ unsupported(id) {
16008
+ const observed = observations.get(id);
16009
+ poison(id);
16010
+ if (observed) observed.ambiguous = true;
16011
+ },
16012
+ async retry(event) {
16013
+ const id = event.sessionID;
16014
+ prune();
16015
+ const observed = observations.get(id);
16016
+ if (observed && (observed.ambiguous || observed.status === void 0)) poison(id);
16017
+ observations.delete(id);
16018
+ const turn = turns.get(id);
16019
+ const generation = turn?.generation;
16020
+ const live = () => !disposed && current() && turns.get(id) === turn && turn?.generation === generation && !!observed && clock() - observed.at <= TTL;
16021
+ if (disposed || saturated || !current() || busy.has(id) || busy.size >= 64 || !turn || !observed || observed.ambiguous || poisoned.has(id) || observed.kind !== "primary" || observed.agent !== event.agent || observed.model !== key(event.model) || turn.agent !== event.agent || key(turn.model) !== key(event.model) || event.error.type !== "provider.quota" || ![402, 429].includes(observed.status ?? 0) || event.error.status !== observed.status)
16022
+ return false;
16023
+ if (!options.allowPaidFallbacks || turn.switches >= options.maxSwitches) return true;
16024
+ const route = routes[turn.agent];
16025
+ if (!route) return true;
16026
+ const chain = [route, ...route.fallbacks ?? []].map(ref);
16027
+ const index = chain.findIndex((m) => key(m) === key(event.model));
16028
+ if (index < 0) return true;
16029
+ busy.add(id);
16030
+ try {
16031
+ const before = await ctx.session.get({ sessionID: id });
16032
+ if (before.agent !== turn.agent || !admission.owns(id, before) || before.model && key(before.model) !== key(event.model) || await admission.isPinned(id) || !live())
16033
+ return true;
16034
+ const results = await query.read(
16035
+ chain.slice(index + 1).map(({ providerID, id: id2 }) => ({ providerID, id: id2 }))
16036
+ );
16037
+ const next = chain.slice(index + 1).find(
16038
+ (m) => (
16039
+ // Do not revisit a model, even if it occurs twice in the configured chain.
16040
+ !chain.slice(0, index + 1).some((old) => key(old) === key(m)) && effectiveQuotaStatus(m, results).status !== "exhausted"
16041
+ )
16042
+ );
16043
+ if (!next) return true;
16044
+ const latest = await ctx.session.get({ sessionID: id });
16045
+ if (!live() || clock() - observed.at > TTL || !admission.owns(id, latest) || await admission.isPinned(id) || latest.agent !== before.agent || (latest.model ? key(latest.model) : "") !== (before.model ? key(before.model) : "") || !live())
16046
+ return true;
16047
+ if (!await admission.select(id, turn.agent, next, live)) return true;
16048
+ turn.model = next;
16049
+ turn.switches++;
16050
+ turn.selected = true;
16051
+ admission.reason(
16052
+ id,
16053
+ live() ? "quota_fallback_selected_retry_requested_not_confirmed" : "quota_fallback_selected_retry_not_requested_control_changed",
16054
+ next
16055
+ );
16056
+ if (live()) {
16057
+ selected(id, turn.agent, next);
16058
+ event.decision = { retry: true, delay: 0 };
16059
+ }
16060
+ return true;
16061
+ } catch {
16062
+ admission.reason(id, "quota_fallback_selection_failed_retry_not_requested");
16063
+ return true;
16064
+ } finally {
16065
+ busy.delete(id);
16066
+ }
16067
+ },
16068
+ dispose() {
16069
+ disposed = true;
16070
+ clearInterval(timer);
16071
+ query.dispose();
16072
+ turns.clear();
16073
+ observations.clear();
16074
+ tickets.clear();
16075
+ poisoned.clear();
16076
+ claiming.clear();
16077
+ }
16078
+ };
16079
+ }
16080
+
16081
+ // src/core/pin-store.ts
16082
+ var Pins = external_exports.object({ version: external_exports.literal(1), sessionIDs: external_exports.array(external_exports.string().min(1)).max(1024) }).strict();
16083
+ var PIN_STORE_KEY = "quota-pins-v1";
16084
+ function createPinStore(storage) {
16085
+ let lane = Promise.resolve();
16086
+ let pending = 0;
16087
+ const read = async () => {
16088
+ const value = await storage.get(PIN_STORE_KEY);
16089
+ return new Set(value === void 0 ? [] : Pins.parse(value).sessionIDs);
16090
+ };
16091
+ const mutate = (sessionID, add, valid) => {
16092
+ if (pending >= 65) return Promise.reject(new Error("Session pin storage is busy; try again."));
16093
+ pending++;
16094
+ const operation = lane.then(async () => {
16095
+ const pins = await read();
16096
+ if (!valid()) throw new Error("Session pin operation was cancelled.");
16097
+ if (add) {
16098
+ if (!pins.has(sessionID) && pins.size >= 1024)
16099
+ throw new Error("Session pin capacity reached.");
16100
+ pins.add(sessionID);
16101
+ } else if (!pins.delete(sessionID)) return;
16102
+ await storage.set(PIN_STORE_KEY, { version: 1, sessionIDs: [...pins] });
16103
+ });
16104
+ lane = operation.then(
16105
+ () => {
16106
+ pending--;
16107
+ },
16108
+ () => {
16109
+ pending--;
16110
+ }
16111
+ );
16112
+ return operation;
16113
+ };
16114
+ return {
16115
+ async has(sessionID) {
16116
+ await lane;
16117
+ return (await read()).has(sessionID);
16118
+ },
16119
+ add: (sessionID, valid) => mutate(sessionID, true, valid),
16120
+ remove: (sessionID, valid = () => true) => mutate(sessionID, false, valid),
16121
+ drain: () => lane
16122
+ };
16123
+ }
16124
+
15879
16125
  // src/quota-v2.ts
15880
- var key = (model) => model ? `${model.providerID}/${model.id}#${model.variant === "default" ? "" : model.variant ?? ""}` : "";
16126
+ var key2 = (model) => model ? `${model.providerID}/${model.id}#${model.variant === "default" ? "" : model.variant ?? ""}` : "";
15881
16127
  function createQuotaAdmission(ctx, routes, current) {
15882
16128
  const parsed = QuotaOptions.safeParse(ctx.options?.quotaPreflight ?? {});
15883
- if (!parsed.success || !parsed.data.enabled) return void 0;
15884
- const options = parsed.data;
16129
+ const fallback = QuotaFallbackOptions.safeParse(ctx.options?.quotaFallback ?? {});
16130
+ if ((!parsed.success || !parsed.data.enabled) && (!fallback.success || !fallback.data.enabled))
16131
+ return void 0;
16132
+ const options = parsed.success ? parsed.data : { enabled: false, allowPaidFallbacks: false };
15885
16133
  const query = createQuotaQuery((input, request) => ctx.rpc(UsageQuota).query(input, request));
15886
16134
  const owned = /* @__PURE__ */ new Map();
15887
16135
  const expected = /* @__PURE__ */ new Map();
@@ -15899,7 +16147,7 @@ function createQuotaAdmission(ctx, routes, current) {
15899
16147
  const reason = (sessionID, value, model) => {
15900
16148
  if (disposed) return;
15901
16149
  if (reasons.has(sessionID) || reasons.size < 1024) reasons.set(sessionID, value);
15902
- console.info(`agent-router: [${sessionID}] ${value}${model ? ` ${key(model)}` : ""}`);
16150
+ console.info(`agent-router: [${sessionID}] ${value}${model ? ` ${key2(model)}` : ""}`);
15903
16151
  };
15904
16152
  const isPinned = async (sessionID) => {
15905
16153
  if (pinned.has(sessionID)) return true;
@@ -15915,19 +16163,19 @@ function createQuotaAdmission(ctx, routes, current) {
15915
16163
  (other) => other.providerID === entry.providerID && other.id === entry.id
15916
16164
  ) === index
15917
16165
  );
15918
- const results = await query.read(candidates);
16166
+ const results = options.enabled ? await query.read(candidates) : [];
15919
16167
  return () => {
15920
16168
  const now = Date.now();
15921
16169
  const startIndex = pending ? Math.max(
15922
16170
  0,
15923
16171
  [route, ...route.fallbacks ?? []].findIndex(
15924
- (entry) => key({
16172
+ (entry) => key2({
15925
16173
  ...quotaCandidate(entry),
15926
16174
  ...entry.variant ? { variant: entry.variant } : {}
15927
- }) === key(pending)
16175
+ }) === key2(pending)
15928
16176
  )
15929
16177
  ) : 0;
15930
- const choice = chooseQuotaRoute(route, results, options.allowPaidFallbacks, now, startIndex);
16178
+ const choice = options.enabled ? chooseQuotaRoute(route, results, options.allowPaidFallbacks, now, startIndex) : pending ? [route, ...route.fallbacks ?? []][startIndex] : route;
15931
16179
  return {
15932
16180
  choice,
15933
16181
  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"
@@ -15936,10 +16184,39 @@ function createQuotaAdmission(ctx, routes, current) {
15936
16184
  };
15937
16185
  return {
15938
16186
  isPinned,
16187
+ reason,
16188
+ owns(sessionID, session) {
16189
+ return !disposed && current() && !controls.has(sessionID) && !pinned.has(sessionID) && !!session.agent && (!session.model || owned.get(sessionID)?.agent === session.agent && owned.get(sessionID)?.model === key2(session.model));
16190
+ },
16191
+ claim(sessionID, agent, model) {
16192
+ if (disposed || !current() || controls.has(sessionID) || pinned.has(sessionID)) return false;
16193
+ if (!owned.has(sessionID) && owned.size >= 1024) return false;
16194
+ owned.set(sessionID, { agent, model: key2(model) });
16195
+ return true;
16196
+ },
16197
+ async select(sessionID, agent, model, live) {
16198
+ if (!live()) return false;
16199
+ expected.set(sessionID, key2(model));
16200
+ try {
16201
+ await ctx.session.switchModel({
16202
+ sessionID,
16203
+ model: {
16204
+ providerID: model.providerID,
16205
+ id: model.id,
16206
+ ...model.variant ? { variant: model.variant } : {}
16207
+ }
16208
+ });
16209
+ if (live()) owned.set(sessionID, { agent, model: key2(model) });
16210
+ return true;
16211
+ } catch (error51) {
16212
+ expected.delete(sessionID);
16213
+ throw error51;
16214
+ }
16215
+ },
15939
16216
  async status(sessionID) {
15940
16217
  const session = await ctx.session.get({ sessionID });
15941
16218
  const explicit = await isPinned(sessionID);
15942
- const automatic = !explicit && (!session.model || owned.get(sessionID)?.model === key(session.model));
16219
+ const automatic = !explicit && (!session.model || owned.get(sessionID)?.model === key2(session.model));
15943
16220
  const resolved = session.model ?? (session.agent ? (await ctx.agent.get({ agentID: session.agent })).data.model : void 0) ?? (await ctx.model.default()).data;
15944
16221
  return {
15945
16222
  sessionID,
@@ -15981,7 +16258,7 @@ function createQuotaAdmission(ctx, routes, current) {
15981
16258
  if (!resolved) throw new Error("No native model is resolved; routing remains pinned.");
15982
16259
  const latest = await ctx.session.get({ sessionID });
15983
16260
  if (!live()) throw new Error("Router stopped or session deleted during pinning.");
15984
- if (latest.agent !== session.agent || key(latest.model) !== key(session.model))
16261
+ if (latest.agent !== session.agent || key2(latest.model) !== key2(session.model))
15985
16262
  throw new Error(
15986
16263
  "Session selection changed while pinning; current selection remains pinned."
15987
16264
  );
@@ -16000,7 +16277,7 @@ function createQuotaAdmission(ctx, routes, current) {
16000
16277
  await pinStore.remove(sessionID, live);
16001
16278
  if (!live()) throw new Error("Router stopped; automatic routing was not resumed.");
16002
16279
  pinned.delete(sessionID);
16003
- owned.set(sessionID, { agent: session.agent, model: key(session.model) });
16280
+ owned.set(sessionID, { agent: session.agent, model: key2(session.model) });
16004
16281
  reason(sessionID, "automatic_next_explicit_turn", session.model);
16005
16282
  }
16006
16283
  } finally {
@@ -16010,7 +16287,7 @@ function createQuotaAdmission(ctx, routes, current) {
16010
16287
  },
16011
16288
  /** Called for every selection event, including before the first prompt. */
16012
16289
  event(sessionID, type, model) {
16013
- if (type === "session.model.selected" && expected.get(sessionID) === key(model)) {
16290
+ if (type === "session.model.selected" && expected.get(sessionID) === key2(model)) {
16014
16291
  expected.delete(sessionID);
16015
16292
  return true;
16016
16293
  }
@@ -16045,13 +16322,13 @@ function createQuotaAdmission(ctx, routes, current) {
16045
16322
  const route = routes[session.agent];
16046
16323
  if (!route) return;
16047
16324
  const previous = owned.get(sessionID);
16048
- if (session.model && (!previous || previous.agent !== session.agent || previous.model !== key(session.model)))
16325
+ if (session.model && (!previous || previous.agent !== session.agent || previous.model !== key2(session.model)))
16049
16326
  return;
16050
16327
  if (!owned.has(sessionID) && owned.size >= 1024) return;
16051
16328
  const choose = await evaluate(route, pending);
16052
16329
  if (disposed || !current() || (versions.get(sessionID) ?? 0) !== generation) return;
16053
16330
  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())
16331
+ if (disposed || controls.has(sessionID) || pinned.has(sessionID) || latest.agent !== session.agent || key2(latest.model) !== key2(session.model) || (versions.get(sessionID) ?? 0) !== generation || !current())
16055
16332
  return;
16056
16333
  const decision = choose();
16057
16334
  const { choice } = decision;
@@ -16063,8 +16340,8 @@ function createQuotaAdmission(ctx, routes, current) {
16063
16340
  ...quotaCandidate(choice),
16064
16341
  ...choice.variant && choice.variant !== "default" ? { variant: choice.variant } : {}
16065
16342
  };
16066
- if (key(model) !== key(session.model) && (session.model || choice.model !== route.model || choice.variant !== route.variant)) {
16067
- expected.set(sessionID, key(model));
16343
+ if (key2(model) !== key2(session.model) && (session.model || choice.model !== route.model || choice.variant !== route.variant)) {
16344
+ expected.set(sessionID, key2(model));
16068
16345
  try {
16069
16346
  await ctx.session.switchModel({ sessionID, model });
16070
16347
  } catch {
@@ -16074,7 +16351,7 @@ function createQuotaAdmission(ctx, routes, current) {
16074
16351
  }
16075
16352
  if (disposed || controls.has(sessionID) || pinned.has(sessionID) || (versions.get(sessionID) ?? 0) !== generation)
16076
16353
  return;
16077
- owned.set(sessionID, { agent: session.agent, model: key(model) });
16354
+ owned.set(sessionID, { agent: session.agent, model: key2(model) });
16078
16355
  reason(sessionID, decision.reason, model);
16079
16356
  return model;
16080
16357
  } finally {
@@ -16174,6 +16451,28 @@ async function setupV2(ctx) {
16174
16451
  const kinds = /* @__PURE__ */ new Map();
16175
16452
  const ownSelections = /* @__PURE__ */ new Map();
16176
16453
  const quota = createQuotaAdmission(ctx, routes, () => state() === initial);
16454
+ const quotaFallback = quota && createQuotaFallback(
16455
+ ctx,
16456
+ routes,
16457
+ quota,
16458
+ () => state() === initial,
16459
+ (sessionID, agent, model, messageID) => {
16460
+ const id = messageID ?? turns.get(sessionID)?.id;
16461
+ if (!id) return;
16462
+ const message = {
16463
+ id,
16464
+ agent,
16465
+ model: {
16466
+ providerID: model.providerID,
16467
+ modelID: model.id,
16468
+ variant: variant(model.variant)
16469
+ }
16470
+ };
16471
+ failover.admit(sessionID, message);
16472
+ turns.set(sessionID, message);
16473
+ kinds.set(sessionID, "primary");
16474
+ }
16475
+ );
16177
16476
  if (quota) {
16178
16477
  await ctx.tool.transform((editor) => {
16179
16478
  const input = { type: "object", properties: {}, additionalProperties: false };
@@ -16184,6 +16483,7 @@ async function setupV2(ctx) {
16184
16483
  input,
16185
16484
  async execute(_input, context) {
16186
16485
  await quota.control(context.sessionID, action, async () => {
16486
+ quotaFallback?.stop(context.sessionID);
16187
16487
  turns.delete(context.sessionID);
16188
16488
  kinds.delete(context.sessionID);
16189
16489
  await failover.event({
@@ -16217,6 +16517,15 @@ async function setupV2(ctx) {
16217
16517
  event.type === "session.model.selected" ? event.data.model : void 0
16218
16518
  ))
16219
16519
  continue;
16520
+ if ([
16521
+ "session.model.selected",
16522
+ "session.agent.selected",
16523
+ "session.execution.interrupted",
16524
+ "session.deleted",
16525
+ "session.execution.succeeded",
16526
+ "session.execution.failed"
16527
+ ].includes(event.type))
16528
+ quotaFallback?.stop(sessionID);
16220
16529
  if (!turns.has(sessionID)) continue;
16221
16530
  if (event.type === "session.model.selected") {
16222
16531
  const model = event.data.model;
@@ -16241,12 +16550,37 @@ async function setupV2(ctx) {
16241
16550
  })().catch((error51) => {
16242
16551
  if (!controller.signal.aborted) console.warn("agent-router event subscription failed", error51);
16243
16552
  });
16244
- await ctx.session.hook("model.request", (event) => {
16553
+ await ctx.session.hook("model.request", async (event) => {
16554
+ quotaFallback?.model(event);
16555
+ if (event.kind === "primary")
16556
+ await quotaFallback?.child(event.sessionID, event.agent, event.model);
16245
16557
  if (turns.has(event.sessionID)) kinds.set(event.sessionID, event.kind);
16246
16558
  });
16247
- if (quota) await ctx.tool.hook("execute.before", (event) => quota.child(event));
16559
+ if (quota)
16560
+ await ctx.tool.hook("execute.before", async (event) => {
16561
+ const input = event.input;
16562
+ const automatic = event.tool === "subagent" && input && typeof input === "object" && !["model", "sessionID", "session_id", "task_id"].some((key3) => key3 in input) && typeof input.agent === "string";
16563
+ await quota.child(event);
16564
+ if (event.tool === "subagent" && input && typeof input.agent === "string")
16565
+ quotaFallback?.ticket(
16566
+ event.id,
16567
+ event.sessionID,
16568
+ input.agent,
16569
+ typeof input.model === "string" ? input.model : void 0,
16570
+ automatic && typeof input.prompt === "string" ? input.prompt : void 0
16571
+ );
16572
+ });
16573
+ if (quotaFallback) {
16574
+ await ctx.session.hook("http.request", (event) => quotaFallback.request(event));
16575
+ await ctx.session.hook("http.response", (event) => quotaFallback.response(event));
16576
+ await ctx.session.hook(
16577
+ "experimental.ws.handshake",
16578
+ (event) => quotaFallback.unsupported(event.sessionID)
16579
+ );
16580
+ }
16248
16581
  await ctx.session.hook("prompt", async (event) => {
16249
16582
  if (turns.get(event.sessionID)?.id === event.messageID) return;
16583
+ quotaFallback?.stop(event.sessionID);
16250
16584
  if (state() !== initial) {
16251
16585
  failover.disable();
16252
16586
  turns.clear();
@@ -16285,6 +16619,7 @@ async function setupV2(ctx) {
16285
16619
  failover.admit(event.sessionID, message2);
16286
16620
  if (!failover.active(event.sessionID)) return;
16287
16621
  turns.set(event.sessionID, message2);
16622
+ if (!session.parentID) quotaFallback?.admit(event.sessionID, session.agent, selected);
16288
16623
  return;
16289
16624
  }
16290
16625
  if (!session.agent || !session.model || !routes[session.agent]) return;
@@ -16336,6 +16671,7 @@ async function setupV2(ctx) {
16336
16671
  turns.set(event.sessionID, message);
16337
16672
  });
16338
16673
  await ctx.session.hook("retry", async (event) => {
16674
+ if (await quotaFallback?.retry(event)) return;
16339
16675
  const turn = turns.get(event.sessionID);
16340
16676
  if (!turn || kinds.get(event.sessionID) !== "primary" || turn.agent !== event.agent || turn.model.providerID !== event.model.providerID || turn.model.modelID !== event.model.id)
16341
16677
  return;
@@ -16363,6 +16699,7 @@ async function setupV2(ctx) {
16363
16699
  });
16364
16700
  return async () => {
16365
16701
  controller.abort();
16702
+ quotaFallback?.dispose();
16366
16703
  await quota?.dispose();
16367
16704
  failover.disable();
16368
16705
  turns.clear();
@@ -16373,7 +16710,7 @@ async function setupV2(ctx) {
16373
16710
  }
16374
16711
 
16375
16712
  // src/version.ts
16376
- var VERSION = "2.1.1";
16713
+ var VERSION = "2.2.0";
16377
16714
 
16378
16715
  // src/plugin.ts
16379
16716
  var tool = Object.assign(