zooid 0.15.0 → 0.16.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.
@@ -14,9 +14,9 @@ var __export = (target, all) => {
14
14
  };
15
15
  var __copyProps = (to, from, except, desc) => {
16
16
  if (from && typeof from === "object" || typeof from === "function") {
17
- for (let key of __getOwnPropNames(from))
18
- if (!__hasOwnProp.call(to, key) && key !== except)
19
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ for (let key2 of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key2) && key2 !== except)
19
+ __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
20
20
  }
21
21
  return to;
22
22
  };
@@ -52,13 +52,13 @@ var require_main = __commonJS({
52
52
  const r = expression.split(splitter);
53
53
  let defaultValue;
54
54
  let value2;
55
- const key = r.shift();
55
+ const key2 = r.shift();
56
56
  if ([":+", "+"].includes(splitter)) {
57
- defaultValue = env[key] ? r.join(splitter) : "";
57
+ defaultValue = env[key2] ? r.join(splitter) : "";
58
58
  value2 = null;
59
59
  } else {
60
60
  defaultValue = r.join(splitter);
61
- value2 = env[key];
61
+ value2 = env[key2];
62
62
  }
63
63
  if (value2) {
64
64
  if (seen.has(value2)) {
@@ -69,7 +69,7 @@ var require_main = __commonJS({
69
69
  } else {
70
70
  result = result.replace(template, defaultValue);
71
71
  }
72
- if (result === runningParsed[key]) {
72
+ if (result === runningParsed[key2]) {
73
73
  break;
74
74
  }
75
75
  regex.lastIndex = 0;
@@ -82,15 +82,15 @@ var require_main = __commonJS({
82
82
  if (options && options.processEnv != null) {
83
83
  processEnv = options.processEnv;
84
84
  }
85
- for (const key in options.parsed) {
86
- let value = options.parsed[key];
87
- if (processEnv[key] && processEnv[key] !== value) {
88
- value = processEnv[key];
85
+ for (const key2 in options.parsed) {
86
+ let value = options.parsed[key2];
87
+ if (processEnv[key2] && processEnv[key2] !== value) {
88
+ value = processEnv[key2];
89
89
  } else {
90
90
  value = expandValue(value, processEnv, runningParsed);
91
91
  }
92
- options.parsed[key] = _resolveEscapeSequences(value);
93
- runningParsed[key] = _resolveEscapeSequences(value);
92
+ options.parsed[key2] = _resolveEscapeSequences(value);
93
+ runningParsed[key2] = _resolveEscapeSequences(value);
94
94
  }
95
95
  for (const processKey in options.parsed) {
96
96
  processEnv[processKey] = options.parsed[processKey];
@@ -237,15 +237,15 @@ var require_code = __commonJS({
237
237
  return JSON.stringify(x).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
238
238
  }
239
239
  exports.safeStringify = safeStringify;
240
- function getProperty(key) {
241
- return typeof key == "string" && exports.IDENTIFIER.test(key) ? new _Code(`.${key}`) : _`[${key}]`;
240
+ function getProperty(key2) {
241
+ return typeof key2 == "string" && exports.IDENTIFIER.test(key2) ? new _Code(`.${key2}`) : _`[${key2}]`;
242
242
  }
243
243
  exports.getProperty = getProperty;
244
- function getEsmExportName(key) {
245
- if (typeof key == "string" && exports.IDENTIFIER.test(key)) {
246
- return new _Code(`${key}`);
244
+ function getEsmExportName(key2) {
245
+ if (typeof key2 == "string" && exports.IDENTIFIER.test(key2)) {
246
+ return new _Code(`${key2}`);
247
247
  }
248
- throw new Error(`CodeGen: invalid export name: ${key}, use explicit $id name mapping`);
248
+ throw new Error(`CodeGen: invalid export name: ${key2}, use explicit $id name mapping`);
249
249
  }
250
250
  exports.getEsmExportName = getEsmExportName;
251
251
  function regexpCode(rx) {
@@ -520,9 +520,9 @@ var require_codegen = __commonJS({
520
520
  }
521
521
  };
522
522
  var Label = class extends Node {
523
- constructor(label) {
523
+ constructor(label2) {
524
524
  super();
525
- this.label = label;
525
+ this.label = label2;
526
526
  this.names = {};
527
527
  }
528
528
  render({ _n }) {
@@ -530,14 +530,14 @@ var require_codegen = __commonJS({
530
530
  }
531
531
  };
532
532
  var Break = class extends Node {
533
- constructor(label) {
533
+ constructor(label2) {
534
534
  super();
535
- this.label = label;
535
+ this.label = label2;
536
536
  this.names = {};
537
537
  }
538
538
  render({ _n }) {
539
- const label = this.label ? ` ${this.label}` : "";
540
- return `break${label};` + _n;
539
+ const label2 = this.label ? ` ${this.label}` : "";
540
+ return `break${label2};` + _n;
541
541
  }
542
542
  };
543
543
  var Throw = class extends Node {
@@ -872,11 +872,11 @@ var require_codegen = __commonJS({
872
872
  // returns code for object literal for the passed argument list of key-value pairs
873
873
  object(...keyValues) {
874
874
  const code = ["{"];
875
- for (const [key, value] of keyValues) {
875
+ for (const [key2, value] of keyValues) {
876
876
  if (code.length > 1)
877
877
  code.push(",");
878
- code.push(key);
879
- if (key !== value || this.opts.es5) {
878
+ code.push(key2);
879
+ if (key2 !== value || this.opts.es5) {
880
880
  code.push(":");
881
881
  (0, code_1.addCodeArg)(code, value);
882
882
  }
@@ -949,12 +949,12 @@ var require_codegen = __commonJS({
949
949
  return this._endBlockNode(For);
950
950
  }
951
951
  // `label` statement
952
- label(label) {
953
- return this._leafNode(new Label(label));
952
+ label(label2) {
953
+ return this._leafNode(new Label(label2));
954
954
  }
955
955
  // `break` statement
956
- break(label) {
957
- return this._leafNode(new Break(label));
956
+ break(label2) {
957
+ return this._leafNode(new Break(label2));
958
958
  }
959
959
  // `return` statement
960
960
  return(value) {
@@ -1151,17 +1151,17 @@ var require_util = __commonJS({
1151
1151
  if (typeof schema === "boolean")
1152
1152
  return;
1153
1153
  const rules = self.RULES.keywords;
1154
- for (const key in schema) {
1155
- if (!rules[key])
1156
- checkStrictMode(it, `unknown keyword: "${key}"`);
1154
+ for (const key2 in schema) {
1155
+ if (!rules[key2])
1156
+ checkStrictMode(it, `unknown keyword: "${key2}"`);
1157
1157
  }
1158
1158
  }
1159
1159
  exports.checkUnknownRules = checkUnknownRules;
1160
1160
  function schemaHasRules(schema, rules) {
1161
1161
  if (typeof schema == "boolean")
1162
1162
  return !schema;
1163
- for (const key in schema)
1164
- if (rules[key])
1163
+ for (const key2 in schema)
1164
+ if (rules[key2])
1165
1165
  return true;
1166
1166
  return false;
1167
1167
  }
@@ -1169,8 +1169,8 @@ var require_util = __commonJS({
1169
1169
  function schemaHasRulesButRef(schema, RULES) {
1170
1170
  if (typeof schema == "boolean")
1171
1171
  return !schema;
1172
- for (const key in schema)
1173
- if (key !== "$ref" && RULES.all[key])
1172
+ for (const key2 in schema)
1173
+ if (key2 !== "$ref" && RULES.all[key2])
1174
1174
  return true;
1175
1175
  return false;
1176
1176
  }
@@ -1748,8 +1748,8 @@ var require_defaults = __commonJS({
1748
1748
  function assignDefaults(it, ty) {
1749
1749
  const { properties, items } = it.schema;
1750
1750
  if (ty === "object" && properties) {
1751
- for (const key in properties) {
1752
- assignDefault(it, key, properties[key].default);
1751
+ for (const key2 in properties) {
1752
+ assignDefault(it, key2, properties[key2].default);
1753
1753
  }
1754
1754
  } else if (ty === "array" && Array.isArray(items)) {
1755
1755
  items.forEach((sch, i) => assignDefault(it, i, sch.default));
@@ -2133,8 +2133,8 @@ var require_fast_deep_equal = __commonJS({
2133
2133
  for (i = length; i-- !== 0; )
2134
2134
  if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
2135
2135
  for (i = length; i-- !== 0; ) {
2136
- var key = keys[i];
2137
- if (!equal(a[key], b[key])) return false;
2136
+ var key2 = keys[i];
2137
+ if (!equal(a[key2], b[key2])) return false;
2138
2138
  }
2139
2139
  return true;
2140
2140
  }
@@ -2206,20 +2206,20 @@ var require_json_schema_traverse = __commonJS({
2206
2206
  function _traverse(opts, pre, post, schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
2207
2207
  if (schema && typeof schema == "object" && !Array.isArray(schema)) {
2208
2208
  pre(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
2209
- for (var key in schema) {
2210
- var sch = schema[key];
2209
+ for (var key2 in schema) {
2210
+ var sch = schema[key2];
2211
2211
  if (Array.isArray(sch)) {
2212
- if (key in traverse.arrayKeywords) {
2212
+ if (key2 in traverse.arrayKeywords) {
2213
2213
  for (var i = 0; i < sch.length; i++)
2214
- _traverse(opts, pre, post, sch[i], jsonPtr + "/" + key + "/" + i, rootSchema, jsonPtr, key, schema, i);
2214
+ _traverse(opts, pre, post, sch[i], jsonPtr + "/" + key2 + "/" + i, rootSchema, jsonPtr, key2, schema, i);
2215
2215
  }
2216
- } else if (key in traverse.propsKeywords) {
2216
+ } else if (key2 in traverse.propsKeywords) {
2217
2217
  if (sch && typeof sch == "object") {
2218
2218
  for (var prop in sch)
2219
- _traverse(opts, pre, post, sch[prop], jsonPtr + "/" + key + "/" + escapeJsonPtr(prop), rootSchema, jsonPtr, key, schema, prop);
2219
+ _traverse(opts, pre, post, sch[prop], jsonPtr + "/" + key2 + "/" + escapeJsonPtr(prop), rootSchema, jsonPtr, key2, schema, prop);
2220
2220
  }
2221
- } else if (key in traverse.keywords || opts.allKeys && !(key in traverse.skipKeywords)) {
2222
- _traverse(opts, pre, post, sch, jsonPtr + "/" + key, rootSchema, jsonPtr, key, schema);
2221
+ } else if (key2 in traverse.keywords || opts.allKeys && !(key2 in traverse.skipKeywords)) {
2222
+ _traverse(opts, pre, post, sch, jsonPtr + "/" + key2, rootSchema, jsonPtr, key2, schema);
2223
2223
  }
2224
2224
  }
2225
2225
  post(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
@@ -2276,10 +2276,10 @@ var require_resolve = __commonJS({
2276
2276
  "$dynamicAnchor"
2277
2277
  ]);
2278
2278
  function hasRef(schema) {
2279
- for (const key in schema) {
2280
- if (REF_KEYWORDS.has(key))
2279
+ for (const key2 in schema) {
2280
+ if (REF_KEYWORDS.has(key2))
2281
2281
  return true;
2282
- const sch = schema[key];
2282
+ const sch = schema[key2];
2283
2283
  if (Array.isArray(sch) && sch.some(hasRef))
2284
2284
  return true;
2285
2285
  if (typeof sch == "object" && hasRef(sch))
@@ -2289,14 +2289,14 @@ var require_resolve = __commonJS({
2289
2289
  }
2290
2290
  function countKeys(schema) {
2291
2291
  let count = 0;
2292
- for (const key in schema) {
2293
- if (key === "$ref")
2292
+ for (const key2 in schema) {
2293
+ if (key2 === "$ref")
2294
2294
  return Infinity;
2295
2295
  count++;
2296
- if (SIMPLE_INLINED.has(key))
2296
+ if (SIMPLE_INLINED.has(key2))
2297
2297
  continue;
2298
- if (typeof schema[key] == "object") {
2299
- (0, util_1.eachItem)(schema[key], (sch) => count += countKeys(sch));
2298
+ if (typeof schema[key2] == "object") {
2299
+ (0, util_1.eachItem)(schema[key2], (sch) => count += countKeys(sch));
2300
2300
  }
2301
2301
  if (count === Infinity)
2302
2302
  return Infinity;
@@ -2485,8 +2485,8 @@ var require_validate = __commonJS({
2485
2485
  function schemaCxtHasRules({ schema, self }) {
2486
2486
  if (typeof schema == "boolean")
2487
2487
  return !schema;
2488
- for (const key in schema)
2489
- if (self.RULES.all[key])
2488
+ for (const key2 in schema)
2489
+ if (self.RULES.all[key2])
2490
2490
  return true;
2491
2491
  return false;
2492
2492
  }
@@ -4215,7 +4215,7 @@ var require_core = __commonJS({
4215
4215
  }
4216
4216
  }
4217
4217
  // Adds schema to the instance
4218
- addSchema(schema, key, _meta, _validateSchema = this.opts.validateSchema) {
4218
+ addSchema(schema, key2, _meta, _validateSchema = this.opts.validateSchema) {
4219
4219
  if (Array.isArray(schema)) {
4220
4220
  for (const sch of schema)
4221
4221
  this.addSchema(sch, void 0, _meta, _validateSchema);
@@ -4229,15 +4229,15 @@ var require_core = __commonJS({
4229
4229
  throw new Error(`schema ${schemaId} must be string`);
4230
4230
  }
4231
4231
  }
4232
- key = (0, resolve_1.normalizeId)(key || id);
4233
- this._checkUnique(key);
4234
- this.schemas[key] = this._addSchema(schema, _meta, key, _validateSchema, true);
4232
+ key2 = (0, resolve_1.normalizeId)(key2 || id);
4233
+ this._checkUnique(key2);
4234
+ this.schemas[key2] = this._addSchema(schema, _meta, key2, _validateSchema, true);
4235
4235
  return this;
4236
4236
  }
4237
4237
  // Add schema that will be used to validate other schemas
4238
4238
  // options in META_IGNORE_OPTIONS are alway set to false
4239
- addMetaSchema(schema, key, _validateSchema = this.opts.validateSchema) {
4240
- this.addSchema(schema, key, true, _validateSchema);
4239
+ addMetaSchema(schema, key2, _validateSchema = this.opts.validateSchema) {
4240
+ this.addSchema(schema, key2, true, _validateSchema);
4241
4241
  return this;
4242
4242
  }
4243
4243
  // Validate schema against its meta-schema
@@ -4393,14 +4393,14 @@ var require_core = __commonJS({
4393
4393
  let keywords = metaSchema;
4394
4394
  for (const seg of segments)
4395
4395
  keywords = keywords[seg];
4396
- for (const key in rules) {
4397
- const rule = rules[key];
4396
+ for (const key2 in rules) {
4397
+ const rule = rules[key2];
4398
4398
  if (typeof rule != "object")
4399
4399
  continue;
4400
4400
  const { $data } = rule.definition;
4401
- const schema = keywords[key];
4401
+ const schema = keywords[key2];
4402
4402
  if ($data && schema)
4403
- keywords[key] = schemaOrData(schema);
4403
+ keywords[key2] = schemaOrData(schema);
4404
4404
  }
4405
4405
  }
4406
4406
  return metaSchema;
@@ -4473,10 +4473,10 @@ var require_core = __commonJS({
4473
4473
  Ajv.MissingRefError = ref_error_1.default;
4474
4474
  exports.default = Ajv;
4475
4475
  function checkOptions(checkOpts, options, msg, log = "error") {
4476
- for (const key in checkOpts) {
4477
- const opt = key;
4476
+ for (const key2 in checkOpts) {
4477
+ const opt = key2;
4478
4478
  if (opt in options)
4479
- this.logger[log](`${msg}: option ${key}. ${checkOpts[opt]}`);
4479
+ this.logger[log](`${msg}: option ${key2}. ${checkOpts[opt]}`);
4480
4480
  }
4481
4481
  }
4482
4482
  function getSchEnv(keyRef) {
@@ -4490,8 +4490,8 @@ var require_core = __commonJS({
4490
4490
  if (Array.isArray(optsSchemas))
4491
4491
  this.addSchema(optsSchemas);
4492
4492
  else
4493
- for (const key in optsSchemas)
4494
- this.addSchema(optsSchemas[key], key);
4493
+ for (const key2 in optsSchemas)
4494
+ this.addSchema(optsSchemas[key2], key2);
4495
4495
  }
4496
4496
  function addInitialFormats() {
4497
4497
  for (const name in this.opts.formats) {
@@ -5539,11 +5539,11 @@ var require_dependencies = __commonJS({
5539
5539
  function splitDependencies({ schema }) {
5540
5540
  const propertyDeps = {};
5541
5541
  const schemaDeps = {};
5542
- for (const key in schema) {
5543
- if (key === "__proto__")
5542
+ for (const key2 in schema) {
5543
+ if (key2 === "__proto__")
5544
5544
  continue;
5545
- const deps = Array.isArray(schema[key]) ? propertyDeps : schemaDeps;
5546
- deps[key] = schema[key];
5545
+ const deps = Array.isArray(schema[key2]) ? propertyDeps : schemaDeps;
5546
+ deps[key2] = schema[key2];
5547
5547
  }
5548
5548
  return [propertyDeps, schemaDeps];
5549
5549
  }
@@ -5620,13 +5620,13 @@ var require_propertyNames = __commonJS({
5620
5620
  if ((0, util_1.alwaysValidSchema)(it, schema))
5621
5621
  return;
5622
5622
  const valid = gen.name("valid");
5623
- gen.forIn("key", data, (key) => {
5624
- cxt.setParams({ propertyName: key });
5623
+ gen.forIn("key", data, (key2) => {
5624
+ cxt.setParams({ propertyName: key2 });
5625
5625
  cxt.subschema({
5626
5626
  keyword: "propertyNames",
5627
- data: key,
5627
+ data: key2,
5628
5628
  dataTypes: ["string"],
5629
- propertyName: key,
5629
+ propertyName: key2,
5630
5630
  compositeRule: true
5631
5631
  }, valid);
5632
5632
  gen.if((0, codegen_1.not)(valid), () => {
@@ -5675,38 +5675,38 @@ var require_additionalProperties = __commonJS({
5675
5675
  checkAdditionalProperties();
5676
5676
  cxt.ok((0, codegen_1._)`${errsCount} === ${names_1.default.errors}`);
5677
5677
  function checkAdditionalProperties() {
5678
- gen.forIn("key", data, (key) => {
5678
+ gen.forIn("key", data, (key2) => {
5679
5679
  if (!props.length && !patProps.length)
5680
- additionalPropertyCode(key);
5680
+ additionalPropertyCode(key2);
5681
5681
  else
5682
- gen.if(isAdditional(key), () => additionalPropertyCode(key));
5682
+ gen.if(isAdditional(key2), () => additionalPropertyCode(key2));
5683
5683
  });
5684
5684
  }
5685
- function isAdditional(key) {
5685
+ function isAdditional(key2) {
5686
5686
  let definedProp;
5687
5687
  if (props.length > 8) {
5688
5688
  const propsSchema = (0, util_1.schemaRefOrVal)(it, parentSchema.properties, "properties");
5689
- definedProp = (0, code_1.isOwnProperty)(gen, propsSchema, key);
5689
+ definedProp = (0, code_1.isOwnProperty)(gen, propsSchema, key2);
5690
5690
  } else if (props.length) {
5691
- definedProp = (0, codegen_1.or)(...props.map((p) => (0, codegen_1._)`${key} === ${p}`));
5691
+ definedProp = (0, codegen_1.or)(...props.map((p) => (0, codegen_1._)`${key2} === ${p}`));
5692
5692
  } else {
5693
5693
  definedProp = codegen_1.nil;
5694
5694
  }
5695
5695
  if (patProps.length) {
5696
- definedProp = (0, codegen_1.or)(definedProp, ...patProps.map((p) => (0, codegen_1._)`${(0, code_1.usePattern)(cxt, p)}.test(${key})`));
5696
+ definedProp = (0, codegen_1.or)(definedProp, ...patProps.map((p) => (0, codegen_1._)`${(0, code_1.usePattern)(cxt, p)}.test(${key2})`));
5697
5697
  }
5698
5698
  return (0, codegen_1.not)(definedProp);
5699
5699
  }
5700
- function deleteAdditional(key) {
5701
- gen.code((0, codegen_1._)`delete ${data}[${key}]`);
5700
+ function deleteAdditional(key2) {
5701
+ gen.code((0, codegen_1._)`delete ${data}[${key2}]`);
5702
5702
  }
5703
- function additionalPropertyCode(key) {
5703
+ function additionalPropertyCode(key2) {
5704
5704
  if (opts.removeAdditional === "all" || opts.removeAdditional && schema === false) {
5705
- deleteAdditional(key);
5705
+ deleteAdditional(key2);
5706
5706
  return;
5707
5707
  }
5708
5708
  if (schema === false) {
5709
- cxt.setParams({ additionalProperty: key });
5709
+ cxt.setParams({ additionalProperty: key2 });
5710
5710
  cxt.error();
5711
5711
  if (!allErrors)
5712
5712
  gen.break();
@@ -5715,22 +5715,22 @@ var require_additionalProperties = __commonJS({
5715
5715
  if (typeof schema == "object" && !(0, util_1.alwaysValidSchema)(it, schema)) {
5716
5716
  const valid = gen.name("valid");
5717
5717
  if (opts.removeAdditional === "failing") {
5718
- applyAdditionalSchema(key, valid, false);
5718
+ applyAdditionalSchema(key2, valid, false);
5719
5719
  gen.if((0, codegen_1.not)(valid), () => {
5720
5720
  cxt.reset();
5721
- deleteAdditional(key);
5721
+ deleteAdditional(key2);
5722
5722
  });
5723
5723
  } else {
5724
- applyAdditionalSchema(key, valid);
5724
+ applyAdditionalSchema(key2, valid);
5725
5725
  if (!allErrors)
5726
5726
  gen.if((0, codegen_1.not)(valid), () => gen.break());
5727
5727
  }
5728
5728
  }
5729
5729
  }
5730
- function applyAdditionalSchema(key, valid, errors) {
5730
+ function applyAdditionalSchema(key2, valid, errors) {
5731
5731
  const subschema = {
5732
5732
  keyword: "additionalProperties",
5733
- dataProp: key,
5733
+ dataProp: key2,
5734
5734
  dataPropType: util_1.Type.Str
5735
5735
  };
5736
5736
  if (errors === false) {
@@ -5855,19 +5855,19 @@ var require_patternProperties = __commonJS({
5855
5855
  }
5856
5856
  }
5857
5857
  function validateProperties(pat) {
5858
- gen.forIn("key", data, (key) => {
5859
- gen.if((0, codegen_1._)`${(0, code_1.usePattern)(cxt, pat)}.test(${key})`, () => {
5858
+ gen.forIn("key", data, (key2) => {
5859
+ gen.if((0, codegen_1._)`${(0, code_1.usePattern)(cxt, pat)}.test(${key2})`, () => {
5860
5860
  const alwaysValid = alwaysValidPatterns.includes(pat);
5861
5861
  if (!alwaysValid) {
5862
5862
  cxt.subschema({
5863
5863
  keyword: "patternProperties",
5864
5864
  schemaProp: pat,
5865
- dataProp: key,
5865
+ dataProp: key2,
5866
5866
  dataPropType: util_2.Type.Str
5867
5867
  }, valid);
5868
5868
  }
5869
5869
  if (it.opts.unevaluated && props !== true) {
5870
- gen.assign((0, codegen_1._)`${props}[${key}]`, true);
5870
+ gen.assign((0, codegen_1._)`${props}[${key2}]`, true);
5871
5871
  } else if (!alwaysValid && !it.allErrors) {
5872
5872
  gen.if((0, codegen_1.not)(valid), () => gen.break());
5873
5873
  }
@@ -7742,9 +7742,9 @@ function floatSafeRemainder(val, step) {
7742
7742
  return ratio - roundedRatio;
7743
7743
  }
7744
7744
  var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
7745
- function defineLazy(object3, key, getter) {
7745
+ function defineLazy(object3, key2, getter) {
7746
7746
  let value = void 0;
7747
- Object.defineProperty(object3, key, {
7747
+ Object.defineProperty(object3, key2, {
7748
7748
  get() {
7749
7749
  if (value === EVALUATING) {
7750
7750
  return void 0;
@@ -7756,7 +7756,7 @@ function defineLazy(object3, key, getter) {
7756
7756
  return value;
7757
7757
  },
7758
7758
  set(v) {
7759
- Object.defineProperty(object3, key, {
7759
+ Object.defineProperty(object3, key2, {
7760
7760
  value: v
7761
7761
  // configurable: true,
7762
7762
  });
@@ -7789,11 +7789,11 @@ function cloneDef(schema) {
7789
7789
  function getElementAtPath(obj, path) {
7790
7790
  if (!path)
7791
7791
  return obj;
7792
- return path.reduce((acc, key) => acc?.[key], obj);
7792
+ return path.reduce((acc, key2) => acc?.[key2], obj);
7793
7793
  }
7794
7794
  function promiseAllObject(promisesObj) {
7795
7795
  const keys = Object.keys(promisesObj);
7796
- const promises = keys.map((key) => promisesObj[key]);
7796
+ const promises = keys.map((key2) => promisesObj[key2]);
7797
7797
  return Promise.all(promises).then((results) => {
7798
7798
  const resolvedObj = {};
7799
7799
  for (let i = 0; i < keys.length; i++) {
@@ -7865,8 +7865,8 @@ function shallowClone(o) {
7865
7865
  }
7866
7866
  function numKeys(data) {
7867
7867
  let keyCount = 0;
7868
- for (const key in data) {
7869
- if (Object.prototype.hasOwnProperty.call(data, key)) {
7868
+ for (const key2 in data) {
7869
+ if (Object.prototype.hasOwnProperty.call(data, key2)) {
7870
7870
  keyCount++;
7871
7871
  }
7872
7872
  }
@@ -8016,13 +8016,13 @@ function pick(schema, mask) {
8016
8016
  const def = mergeDefs(schema._zod.def, {
8017
8017
  get shape() {
8018
8018
  const newShape = {};
8019
- for (const key in mask) {
8020
- if (!(key in currDef.shape)) {
8021
- throw new Error(`Unrecognized key: "${key}"`);
8019
+ for (const key2 in mask) {
8020
+ if (!(key2 in currDef.shape)) {
8021
+ throw new Error(`Unrecognized key: "${key2}"`);
8022
8022
  }
8023
- if (!mask[key])
8023
+ if (!mask[key2])
8024
8024
  continue;
8025
- newShape[key] = currDef.shape[key];
8025
+ newShape[key2] = currDef.shape[key2];
8026
8026
  }
8027
8027
  assignProp(this, "shape", newShape);
8028
8028
  return newShape;
@@ -8041,13 +8041,13 @@ function omit(schema, mask) {
8041
8041
  const def = mergeDefs(schema._zod.def, {
8042
8042
  get shape() {
8043
8043
  const newShape = { ...schema._zod.def.shape };
8044
- for (const key in mask) {
8045
- if (!(key in currDef.shape)) {
8046
- throw new Error(`Unrecognized key: "${key}"`);
8044
+ for (const key2 in mask) {
8045
+ if (!(key2 in currDef.shape)) {
8046
+ throw new Error(`Unrecognized key: "${key2}"`);
8047
8047
  }
8048
- if (!mask[key])
8048
+ if (!mask[key2])
8049
8049
  continue;
8050
- delete newShape[key];
8050
+ delete newShape[key2];
8051
8051
  }
8052
8052
  assignProp(this, "shape", newShape);
8053
8053
  return newShape;
@@ -8064,8 +8064,8 @@ function extend(schema, shape) {
8064
8064
  const hasChecks = checks && checks.length > 0;
8065
8065
  if (hasChecks) {
8066
8066
  const existingShape = schema._zod.def.shape;
8067
- for (const key in shape) {
8068
- if (Object.getOwnPropertyDescriptor(existingShape, key) !== void 0) {
8067
+ for (const key2 in shape) {
8068
+ if (Object.getOwnPropertyDescriptor(existingShape, key2) !== void 0) {
8069
8069
  throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.");
8070
8070
  }
8071
8071
  }
@@ -8121,23 +8121,23 @@ function partial(Class3, schema, mask) {
8121
8121
  const oldShape = schema._zod.def.shape;
8122
8122
  const shape = { ...oldShape };
8123
8123
  if (mask) {
8124
- for (const key in mask) {
8125
- if (!(key in oldShape)) {
8126
- throw new Error(`Unrecognized key: "${key}"`);
8124
+ for (const key2 in mask) {
8125
+ if (!(key2 in oldShape)) {
8126
+ throw new Error(`Unrecognized key: "${key2}"`);
8127
8127
  }
8128
- if (!mask[key])
8128
+ if (!mask[key2])
8129
8129
  continue;
8130
- shape[key] = Class3 ? new Class3({
8130
+ shape[key2] = Class3 ? new Class3({
8131
8131
  type: "optional",
8132
- innerType: oldShape[key]
8133
- }) : oldShape[key];
8132
+ innerType: oldShape[key2]
8133
+ }) : oldShape[key2];
8134
8134
  }
8135
8135
  } else {
8136
- for (const key in oldShape) {
8137
- shape[key] = Class3 ? new Class3({
8136
+ for (const key2 in oldShape) {
8137
+ shape[key2] = Class3 ? new Class3({
8138
8138
  type: "optional",
8139
- innerType: oldShape[key]
8140
- }) : oldShape[key];
8139
+ innerType: oldShape[key2]
8140
+ }) : oldShape[key2];
8141
8141
  }
8142
8142
  }
8143
8143
  assignProp(this, "shape", shape);
@@ -8153,22 +8153,22 @@ function required(Class3, schema, mask) {
8153
8153
  const oldShape = schema._zod.def.shape;
8154
8154
  const shape = { ...oldShape };
8155
8155
  if (mask) {
8156
- for (const key in mask) {
8157
- if (!(key in shape)) {
8158
- throw new Error(`Unrecognized key: "${key}"`);
8156
+ for (const key2 in mask) {
8157
+ if (!(key2 in shape)) {
8158
+ throw new Error(`Unrecognized key: "${key2}"`);
8159
8159
  }
8160
- if (!mask[key])
8160
+ if (!mask[key2])
8161
8161
  continue;
8162
- shape[key] = new Class3({
8162
+ shape[key2] = new Class3({
8163
8163
  type: "nonoptional",
8164
- innerType: oldShape[key]
8164
+ innerType: oldShape[key2]
8165
8165
  });
8166
8166
  }
8167
8167
  } else {
8168
- for (const key in oldShape) {
8169
- shape[key] = new Class3({
8168
+ for (const key2 in oldShape) {
8169
+ shape[key2] = new Class3({
8170
8170
  type: "nonoptional",
8171
- innerType: oldShape[key]
8171
+ innerType: oldShape[key2]
8172
8172
  });
8173
8173
  }
8174
8174
  }
@@ -9949,13 +9949,13 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
9949
9949
  return payload;
9950
9950
  };
9951
9951
  });
9952
- function handlePropertyResult(result, final, key, input, isOptionalIn, isOptionalOut) {
9953
- const isPresent = key in input;
9952
+ function handlePropertyResult(result, final, key2, input, isOptionalIn, isOptionalOut) {
9953
+ const isPresent = key2 in input;
9954
9954
  if (result.issues.length) {
9955
9955
  if (isOptionalIn && isOptionalOut && !isPresent) {
9956
9956
  return;
9957
9957
  }
9958
- final.issues.push(...prefixIssues(key, result.issues));
9958
+ final.issues.push(...prefixIssues(key2, result.issues));
9959
9959
  }
9960
9960
  if (!isPresent && !isOptionalIn) {
9961
9961
  if (!result.issues.length) {
@@ -9963,17 +9963,17 @@ function handlePropertyResult(result, final, key, input, isOptionalIn, isOptiona
9963
9963
  code: "invalid_type",
9964
9964
  expected: "nonoptional",
9965
9965
  input: void 0,
9966
- path: [key]
9966
+ path: [key2]
9967
9967
  });
9968
9968
  }
9969
9969
  return;
9970
9970
  }
9971
9971
  if (result.value === void 0) {
9972
9972
  if (isPresent) {
9973
- final.value[key] = void 0;
9973
+ final.value[key2] = void 0;
9974
9974
  }
9975
9975
  } else {
9976
- final.value[key] = result.value;
9976
+ final.value[key2] = result.value;
9977
9977
  }
9978
9978
  }
9979
9979
  function normalizeDef(def) {
@@ -9999,20 +9999,20 @@ function handleCatchall(proms, input, payload, ctx, def, inst) {
9999
9999
  const t = _catchall.def.type;
10000
10000
  const isOptionalIn = _catchall.optin === "optional";
10001
10001
  const isOptionalOut = _catchall.optout === "optional";
10002
- for (const key in input) {
10003
- if (key === "__proto__")
10002
+ for (const key2 in input) {
10003
+ if (key2 === "__proto__")
10004
10004
  continue;
10005
- if (keySet.has(key))
10005
+ if (keySet.has(key2))
10006
10006
  continue;
10007
10007
  if (t === "never") {
10008
- unrecognized.push(key);
10008
+ unrecognized.push(key2);
10009
10009
  continue;
10010
10010
  }
10011
- const r = _catchall.run({ value: input[key], issues: [] }, ctx);
10011
+ const r = _catchall.run({ value: input[key2], issues: [] }, ctx);
10012
10012
  if (r instanceof Promise) {
10013
- proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input, isOptionalIn, isOptionalOut)));
10013
+ proms.push(r.then((r2) => handlePropertyResult(r2, payload, key2, input, isOptionalIn, isOptionalOut)));
10014
10014
  } else {
10015
- handlePropertyResult(r, payload, key, input, isOptionalIn, isOptionalOut);
10015
+ handlePropertyResult(r, payload, key2, input, isOptionalIn, isOptionalOut);
10016
10016
  }
10017
10017
  }
10018
10018
  if (unrecognized.length) {
@@ -10048,12 +10048,12 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
10048
10048
  defineLazy(inst._zod, "propValues", () => {
10049
10049
  const shape = def.shape;
10050
10050
  const propValues = {};
10051
- for (const key in shape) {
10052
- const field = shape[key]._zod;
10051
+ for (const key2 in shape) {
10052
+ const field = shape[key2]._zod;
10053
10053
  if (field.values) {
10054
- propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
10054
+ propValues[key2] ?? (propValues[key2] = /* @__PURE__ */ new Set());
10055
10055
  for (const v of field.values)
10056
- propValues[key].add(v);
10056
+ propValues[key2].add(v);
10057
10057
  }
10058
10058
  }
10059
10059
  return propValues;
@@ -10076,15 +10076,15 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
10076
10076
  payload.value = {};
10077
10077
  const proms = [];
10078
10078
  const shape = value.shape;
10079
- for (const key of value.keys) {
10080
- const el = shape[key];
10079
+ for (const key2 of value.keys) {
10080
+ const el = shape[key2];
10081
10081
  const isOptionalIn = el._zod.optin === "optional";
10082
10082
  const isOptionalOut = el._zod.optout === "optional";
10083
- const r = el._zod.run({ value: input[key], issues: [] }, ctx);
10083
+ const r = el._zod.run({ value: input[key2], issues: [] }, ctx);
10084
10084
  if (r instanceof Promise) {
10085
- proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input, isOptionalIn, isOptionalOut)));
10085
+ proms.push(r.then((r2) => handlePropertyResult(r2, payload, key2, input, isOptionalIn, isOptionalOut)));
10086
10086
  } else {
10087
- handlePropertyResult(r, payload, key, input, isOptionalIn, isOptionalOut);
10087
+ handlePropertyResult(r, payload, key2, input, isOptionalIn, isOptionalOut);
10088
10088
  }
10089
10089
  }
10090
10090
  if (!catchall) {
@@ -10100,24 +10100,24 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
10100
10100
  const generateFastpass = (shape) => {
10101
10101
  const doc = new Doc(["shape", "payload", "ctx"]);
10102
10102
  const normalized = _normalized.value;
10103
- const parseStr = (key) => {
10104
- const k = esc(key);
10103
+ const parseStr = (key2) => {
10104
+ const k = esc(key2);
10105
10105
  return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
10106
10106
  };
10107
10107
  doc.write(`const input = payload.value;`);
10108
10108
  const ids = /* @__PURE__ */ Object.create(null);
10109
10109
  let counter = 0;
10110
- for (const key of normalized.keys) {
10111
- ids[key] = `key_${counter++}`;
10110
+ for (const key2 of normalized.keys) {
10111
+ ids[key2] = `key_${counter++}`;
10112
10112
  }
10113
10113
  doc.write(`const newResult = {};`);
10114
- for (const key of normalized.keys) {
10115
- const id = ids[key];
10116
- const k = esc(key);
10117
- const schema = shape[key];
10114
+ for (const key2 of normalized.keys) {
10115
+ const id = ids[key2];
10116
+ const k = esc(key2);
10117
+ const schema = shape[key2];
10118
10118
  const isOptionalIn = schema?._zod?.optin === "optional";
10119
10119
  const isOptionalOut = schema?._zod?.optout === "optional";
10120
- doc.write(`const ${id} = ${parseStr(key)};`);
10120
+ doc.write(`const ${id} = ${parseStr(key2)};`);
10121
10121
  if (isOptionalIn && isOptionalOut) {
10122
10122
  doc.write(`
10123
10123
  if (${id}.issues.length) {
@@ -10429,17 +10429,17 @@ function mergeValues(a, b) {
10429
10429
  }
10430
10430
  if (isPlainObject(a) && isPlainObject(b)) {
10431
10431
  const bKeys = Object.keys(b);
10432
- const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
10432
+ const sharedKeys = Object.keys(a).filter((key2) => bKeys.indexOf(key2) !== -1);
10433
10433
  const newObj = { ...a, ...b };
10434
- for (const key of sharedKeys) {
10435
- const sharedValue = mergeValues(a[key], b[key]);
10434
+ for (const key2 of sharedKeys) {
10435
+ const sharedValue = mergeValues(a[key2], b[key2]);
10436
10436
  if (!sharedValue.valid) {
10437
10437
  return {
10438
10438
  valid: false,
10439
- mergeErrorPath: [key, ...sharedValue.mergeErrorPath]
10439
+ mergeErrorPath: [key2, ...sharedValue.mergeErrorPath]
10440
10440
  };
10441
10441
  }
10442
- newObj[key] = sharedValue.data;
10442
+ newObj[key2] = sharedValue.data;
10443
10443
  }
10444
10444
  return { valid: true, data: newObj };
10445
10445
  }
@@ -10574,9 +10574,9 @@ var $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
10574
10574
  return handleTupleResults(itemResults, payload, items, input, optoutStart);
10575
10575
  };
10576
10576
  });
10577
- function getTupleOptStart(items, key) {
10577
+ function getTupleOptStart(items, key2) {
10578
10578
  for (let i = items.length - 1; i >= 0; i--) {
10579
- if (items[i]._zod[key] !== "optional")
10579
+ if (items[i]._zod[key2] !== "optional")
10580
10580
  return i + 1;
10581
10581
  }
10582
10582
  return 0;
@@ -10627,10 +10627,10 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
10627
10627
  if (values) {
10628
10628
  payload.value = {};
10629
10629
  const recordKeys = /* @__PURE__ */ new Set();
10630
- for (const key of values) {
10631
- if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
10632
- recordKeys.add(typeof key === "number" ? key.toString() : key);
10633
- const keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
10630
+ for (const key2 of values) {
10631
+ if (typeof key2 === "string" || typeof key2 === "number" || typeof key2 === "symbol") {
10632
+ recordKeys.add(typeof key2 === "number" ? key2.toString() : key2);
10633
+ const keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
10634
10634
  if (keyResult instanceof Promise) {
10635
10635
  throw new Error("Async schemas not supported in object keys currently");
10636
10636
  }
@@ -10639,34 +10639,34 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
10639
10639
  code: "invalid_key",
10640
10640
  origin: "record",
10641
10641
  issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
10642
- input: key,
10643
- path: [key],
10642
+ input: key2,
10643
+ path: [key2],
10644
10644
  inst
10645
10645
  });
10646
10646
  continue;
10647
10647
  }
10648
10648
  const outKey = keyResult.value;
10649
- const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
10649
+ const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
10650
10650
  if (result instanceof Promise) {
10651
10651
  proms.push(result.then((result2) => {
10652
10652
  if (result2.issues.length) {
10653
- payload.issues.push(...prefixIssues(key, result2.issues));
10653
+ payload.issues.push(...prefixIssues(key2, result2.issues));
10654
10654
  }
10655
10655
  payload.value[outKey] = result2.value;
10656
10656
  }));
10657
10657
  } else {
10658
10658
  if (result.issues.length) {
10659
- payload.issues.push(...prefixIssues(key, result.issues));
10659
+ payload.issues.push(...prefixIssues(key2, result.issues));
10660
10660
  }
10661
10661
  payload.value[outKey] = result.value;
10662
10662
  }
10663
10663
  }
10664
10664
  }
10665
10665
  let unrecognized;
10666
- for (const key in input) {
10667
- if (!recordKeys.has(key)) {
10666
+ for (const key2 in input) {
10667
+ if (!recordKeys.has(key2)) {
10668
10668
  unrecognized = unrecognized ?? [];
10669
- unrecognized.push(key);
10669
+ unrecognized.push(key2);
10670
10670
  }
10671
10671
  }
10672
10672
  if (unrecognized && unrecognized.length > 0) {
@@ -10679,18 +10679,18 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
10679
10679
  }
10680
10680
  } else {
10681
10681
  payload.value = {};
10682
- for (const key of Reflect.ownKeys(input)) {
10683
- if (key === "__proto__")
10682
+ for (const key2 of Reflect.ownKeys(input)) {
10683
+ if (key2 === "__proto__")
10684
10684
  continue;
10685
- if (!Object.prototype.propertyIsEnumerable.call(input, key))
10685
+ if (!Object.prototype.propertyIsEnumerable.call(input, key2))
10686
10686
  continue;
10687
- let keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
10687
+ let keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
10688
10688
  if (keyResult instanceof Promise) {
10689
10689
  throw new Error("Async schemas not supported in object keys currently");
10690
10690
  }
10691
- const checkNumericKey = typeof key === "string" && number.test(key) && keyResult.issues.length;
10691
+ const checkNumericKey = typeof key2 === "string" && number.test(key2) && keyResult.issues.length;
10692
10692
  if (checkNumericKey) {
10693
- const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
10693
+ const retryResult = def.keyType._zod.run({ value: Number(key2), issues: [] }, ctx);
10694
10694
  if (retryResult instanceof Promise) {
10695
10695
  throw new Error("Async schemas not supported in object keys currently");
10696
10696
  }
@@ -10700,30 +10700,30 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
10700
10700
  }
10701
10701
  if (keyResult.issues.length) {
10702
10702
  if (def.mode === "loose") {
10703
- payload.value[key] = input[key];
10703
+ payload.value[key2] = input[key2];
10704
10704
  } else {
10705
10705
  payload.issues.push({
10706
10706
  code: "invalid_key",
10707
10707
  origin: "record",
10708
10708
  issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
10709
- input: key,
10710
- path: [key],
10709
+ input: key2,
10710
+ path: [key2],
10711
10711
  inst
10712
10712
  });
10713
10713
  }
10714
10714
  continue;
10715
10715
  }
10716
- const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
10716
+ const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
10717
10717
  if (result instanceof Promise) {
10718
10718
  proms.push(result.then((result2) => {
10719
10719
  if (result2.issues.length) {
10720
- payload.issues.push(...prefixIssues(key, result2.issues));
10720
+ payload.issues.push(...prefixIssues(key2, result2.issues));
10721
10721
  }
10722
10722
  payload.value[keyResult.value] = result2.value;
10723
10723
  }));
10724
10724
  } else {
10725
10725
  if (result.issues.length) {
10726
- payload.issues.push(...prefixIssues(key, result.issues));
10726
+ payload.issues.push(...prefixIssues(key2, result.issues));
10727
10727
  }
10728
10728
  payload.value[keyResult.value] = result.value;
10729
10729
  }
@@ -10750,15 +10750,15 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
10750
10750
  }
10751
10751
  const proms = [];
10752
10752
  payload.value = /* @__PURE__ */ new Map();
10753
- for (const [key, value] of input) {
10754
- const keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
10753
+ for (const [key2, value] of input) {
10754
+ const keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
10755
10755
  const valueResult = def.valueType._zod.run({ value, issues: [] }, ctx);
10756
10756
  if (keyResult instanceof Promise || valueResult instanceof Promise) {
10757
10757
  proms.push(Promise.all([keyResult, valueResult]).then(([keyResult2, valueResult2]) => {
10758
- handleMapResult(keyResult2, valueResult2, payload, key, input, inst, ctx);
10758
+ handleMapResult(keyResult2, valueResult2, payload, key2, input, inst, ctx);
10759
10759
  }));
10760
10760
  } else {
10761
- handleMapResult(keyResult, valueResult, payload, key, input, inst, ctx);
10761
+ handleMapResult(keyResult, valueResult, payload, key2, input, inst, ctx);
10762
10762
  }
10763
10763
  }
10764
10764
  if (proms.length)
@@ -10766,10 +10766,10 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
10766
10766
  return payload;
10767
10767
  };
10768
10768
  });
10769
- function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) {
10769
+ function handleMapResult(keyResult, valueResult, final, key2, input, inst, ctx) {
10770
10770
  if (keyResult.issues.length) {
10771
- if (propertyKeyTypes.has(typeof key)) {
10772
- final.issues.push(...prefixIssues(key, keyResult.issues));
10771
+ if (propertyKeyTypes.has(typeof key2)) {
10772
+ final.issues.push(...prefixIssues(key2, keyResult.issues));
10773
10773
  } else {
10774
10774
  final.issues.push({
10775
10775
  code: "invalid_key",
@@ -10781,15 +10781,15 @@ function handleMapResult(keyResult, valueResult, final, key, input, inst, ctx) {
10781
10781
  }
10782
10782
  }
10783
10783
  if (valueResult.issues.length) {
10784
- if (propertyKeyTypes.has(typeof key)) {
10785
- final.issues.push(...prefixIssues(key, valueResult.issues));
10784
+ if (propertyKeyTypes.has(typeof key2)) {
10785
+ final.issues.push(...prefixIssues(key2, valueResult.issues));
10786
10786
  } else {
10787
10787
  final.issues.push({
10788
10788
  origin: "map",
10789
10789
  code: "invalid_element",
10790
10790
  input,
10791
10791
  inst,
10792
- key,
10792
+ key: key2,
10793
10793
  issues: valueResult.issues.map((iss) => finalizeIssue(iss, ctx, config()))
10794
10794
  });
10795
10795
  }
@@ -18550,8 +18550,8 @@ function extractDefs(ctx, schema) {
18550
18550
  if (defId)
18551
18551
  seen.defId = defId;
18552
18552
  const schema2 = seen.schema;
18553
- for (const key in schema2) {
18554
- delete schema2[key];
18553
+ for (const key2 in schema2) {
18554
+ delete schema2[key2];
18555
18555
  }
18556
18556
  schema2.$ref = ref;
18557
18557
  };
@@ -18620,20 +18620,20 @@ function finalize(ctx, schema) {
18620
18620
  Object.assign(schema2, _cached);
18621
18621
  const isParentRef = zodSchema._zod.parent === ref;
18622
18622
  if (isParentRef) {
18623
- for (const key in schema2) {
18624
- if (key === "$ref" || key === "allOf")
18623
+ for (const key2 in schema2) {
18624
+ if (key2 === "$ref" || key2 === "allOf")
18625
18625
  continue;
18626
- if (!(key in _cached)) {
18627
- delete schema2[key];
18626
+ if (!(key2 in _cached)) {
18627
+ delete schema2[key2];
18628
18628
  }
18629
18629
  }
18630
18630
  }
18631
18631
  if (refSchema.$ref && refSeen.def) {
18632
- for (const key in schema2) {
18633
- if (key === "$ref" || key === "allOf")
18632
+ for (const key2 in schema2) {
18633
+ if (key2 === "$ref" || key2 === "allOf")
18634
18634
  continue;
18635
- if (key in refSeen.def && JSON.stringify(schema2[key]) === JSON.stringify(refSeen.def[key])) {
18636
- delete schema2[key];
18635
+ if (key2 in refSeen.def && JSON.stringify(schema2[key2]) === JSON.stringify(refSeen.def[key2])) {
18636
+ delete schema2[key2];
18637
18637
  }
18638
18638
  }
18639
18639
  }
@@ -18645,11 +18645,11 @@ function finalize(ctx, schema) {
18645
18645
  if (parentSeen?.schema.$ref) {
18646
18646
  schema2.$ref = parentSeen.schema.$ref;
18647
18647
  if (parentSeen.def) {
18648
- for (const key in schema2) {
18649
- if (key === "$ref" || key === "allOf")
18648
+ for (const key2 in schema2) {
18649
+ if (key2 === "$ref" || key2 === "allOf")
18650
18650
  continue;
18651
- if (key in parentSeen.def && JSON.stringify(schema2[key]) === JSON.stringify(parentSeen.def[key])) {
18652
- delete schema2[key];
18651
+ if (key2 in parentSeen.def && JSON.stringify(schema2[key2]) === JSON.stringify(parentSeen.def[key2])) {
18652
+ delete schema2[key2];
18653
18653
  }
18654
18654
  }
18655
18655
  }
@@ -18750,8 +18750,8 @@ function isTransforming(_schema, _ctx) {
18750
18750
  return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
18751
18751
  }
18752
18752
  if (def.type === "object") {
18753
- for (const key in def.shape) {
18754
- if (isTransforming(def.shape[key], ctx))
18753
+ for (const key2 in def.shape) {
18754
+ if (isTransforming(def.shape[key2], ctx))
18755
18755
  return true;
18756
18756
  }
18757
18757
  return false;
@@ -19040,15 +19040,15 @@ var objectProcessor = (schema, ctx, _json, params) => {
19040
19040
  json2.type = "object";
19041
19041
  json2.properties = {};
19042
19042
  const shape = def.shape;
19043
- for (const key in shape) {
19044
- json2.properties[key] = process2(shape[key], ctx, {
19043
+ for (const key2 in shape) {
19044
+ json2.properties[key2] = process2(shape[key2], ctx, {
19045
19045
  ...params,
19046
- path: [...params.path, "properties", key]
19046
+ path: [...params.path, "properties", key2]
19047
19047
  });
19048
19048
  }
19049
19049
  const allKeys = new Set(Object.keys(shape));
19050
- const requiredKeys = new Set([...allKeys].filter((key) => {
19051
- const v = def.shape[key]._zod;
19050
+ const requiredKeys = new Set([...allKeys].filter((key2) => {
19051
+ const v = def.shape[key2]._zod;
19052
19052
  if (ctx.io === "input") {
19053
19053
  return v.optin === void 0;
19054
19054
  } else {
@@ -19314,9 +19314,9 @@ function toJSONSchema(input, params) {
19314
19314
  };
19315
19315
  ctx2.external = external;
19316
19316
  for (const entry of registry3._idmap.entries()) {
19317
- const [key, schema] = entry;
19317
+ const [key2, schema] = entry;
19318
19318
  extractDefs(ctx2, schema);
19319
- schemas[key] = finalize(ctx2, schema);
19319
+ schemas[key2] = finalize(ctx2, schema);
19320
19320
  }
19321
19321
  if (Object.keys(defs).length > 0) {
19322
19322
  const defsSegment = ctx2.target === "draft-2020-12" ? "$defs" : "definitions";
@@ -19722,14 +19722,14 @@ function _installLazyMethods(inst, group, methods) {
19722
19722
  if (installed.has(group))
19723
19723
  return;
19724
19724
  installed.add(group);
19725
- for (const key in methods) {
19726
- const fn = methods[key];
19727
- Object.defineProperty(proto, key, {
19725
+ for (const key2 in methods) {
19726
+ const fn = methods[key2];
19727
+ Object.defineProperty(proto, key2, {
19728
19728
  configurable: true,
19729
19729
  enumerable: false,
19730
19730
  get() {
19731
19731
  const bound = fn.bind(this);
19732
- Object.defineProperty(this, key, {
19732
+ Object.defineProperty(this, key2, {
19733
19733
  configurable: true,
19734
19734
  writable: true,
19735
19735
  enumerable: true,
@@ -19738,7 +19738,7 @@ function _installLazyMethods(inst, group, methods) {
19738
19738
  return bound;
19739
19739
  },
19740
19740
  set(v) {
19741
- Object.defineProperty(this, key, {
19741
+ Object.defineProperty(this, key2, {
19742
19742
  configurable: true,
19743
19743
  writable: true,
19744
19744
  enumerable: true,
@@ -21126,11 +21126,11 @@ function resolveRef(ref, ctx) {
21126
21126
  }
21127
21127
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
21128
21128
  if (path[0] === defsKey) {
21129
- const key = path[1];
21130
- if (!key || !ctx.defs[key]) {
21129
+ const key2 = path[1];
21130
+ if (!key2 || !ctx.defs[key2]) {
21131
21131
  throw new Error(`Reference not found: ${ref}`);
21132
21132
  }
21133
- return ctx.defs[key];
21133
+ return ctx.defs[key2];
21134
21134
  }
21135
21135
  throw new Error(`Reference not found: ${ref}`);
21136
21136
  }
@@ -21316,9 +21316,9 @@ function convertBaseSchema(schema, ctx) {
21316
21316
  const shape = {};
21317
21317
  const properties = schema.properties || {};
21318
21318
  const requiredSet = new Set(schema.required || []);
21319
- for (const [key, propSchema] of Object.entries(properties)) {
21319
+ for (const [key2, propSchema] of Object.entries(properties)) {
21320
21320
  const propZodSchema = convertSchema(propSchema, ctx);
21321
- shape[key] = requiredSet.has(key) ? propZodSchema : propZodSchema.optional();
21321
+ shape[key2] = requiredSet.has(key2) ? propZodSchema : propZodSchema.optional();
21322
21322
  }
21323
21323
  if (schema.propertyNames) {
21324
21324
  const keySchema = convertSchema(schema.propertyNames, ctx);
@@ -21459,20 +21459,20 @@ function convertSchema(schema, ctx) {
21459
21459
  }
21460
21460
  const extraMeta = {};
21461
21461
  const coreMetadataKeys = ["$id", "id", "$comment", "$anchor", "$vocabulary", "$dynamicRef", "$dynamicAnchor"];
21462
- for (const key of coreMetadataKeys) {
21463
- if (key in schema) {
21464
- extraMeta[key] = schema[key];
21462
+ for (const key2 of coreMetadataKeys) {
21463
+ if (key2 in schema) {
21464
+ extraMeta[key2] = schema[key2];
21465
21465
  }
21466
21466
  }
21467
21467
  const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
21468
- for (const key of contentMetadataKeys) {
21469
- if (key in schema) {
21470
- extraMeta[key] = schema[key];
21468
+ for (const key2 of contentMetadataKeys) {
21469
+ if (key2 in schema) {
21470
+ extraMeta[key2] = schema[key2];
21471
21471
  }
21472
21472
  }
21473
- for (const key of Object.keys(schema)) {
21474
- if (!RECOGNIZED_KEYS.has(key)) {
21475
- extraMeta[key] = schema[key];
21473
+ for (const key2 of Object.keys(schema)) {
21474
+ if (!RECOGNIZED_KEYS.has(key2)) {
21475
+ extraMeta[key2] = schema[key2];
21476
21476
  }
21477
21477
  }
21478
21478
  if (Object.keys(extraMeta).length > 0) {
@@ -23911,6 +23911,9 @@ var SessionMap = class {
23911
23911
  delete(k) {
23912
23912
  this.inner.delete(keyOf(k));
23913
23913
  }
23914
+ clear() {
23915
+ this.inner.clear();
23916
+ }
23914
23917
  listForAgent(agentId) {
23915
23918
  const out = [];
23916
23919
  for (const v of this.inner.values()) {
@@ -24287,10 +24290,18 @@ var AcpClient = class {
24287
24290
  store = null;
24288
24291
  storeLoaded = null;
24289
24292
  agentCapabilities = {};
24293
+ lifecycle = /* @__PURE__ */ new Map();
24294
+ replay = /* @__PURE__ */ new Set();
24295
+ permissionCancels = /* @__PURE__ */ new Map();
24296
+ generation = 0;
24297
+ warnedNoClose = false;
24290
24298
  warnedNoStore = false;
24291
24299
  initialized = false;
24292
24300
  turns;
24293
24301
  async start() {
24302
+ this.generation++;
24303
+ this.clearTimers();
24304
+ this.warnedNoClose = false;
24294
24305
  const { command, args } = this.resolveSpawn();
24295
24306
  let stdout;
24296
24307
  let stdin;
@@ -24340,6 +24351,13 @@ var AcpClient = class {
24340
24351
  this.initialized = true;
24341
24352
  }
24342
24353
  async stop() {
24354
+ this.generation++;
24355
+ this.clearTimers();
24356
+ for (const cancels of this.permissionCancels.values()) for (const cancel of cancels) cancel();
24357
+ this.permissionCancels.clear();
24358
+ this.replay.clear();
24359
+ this.sessions.clear();
24360
+ this.lifecycle.clear();
24343
24361
  this.process?.kill();
24344
24362
  this.runtimeChild?.kill("SIGTERM");
24345
24363
  this.process = null;
@@ -24348,14 +24366,27 @@ var AcpClient = class {
24348
24366
  this.initialized = false;
24349
24367
  }
24350
24368
  async ensureSession(threadId, channelId, contextThreadId) {
24369
+ return this.enqueue(
24370
+ threadId,
24371
+ () => this.ensureSessionLocked(threadId, channelId, contextThreadId)
24372
+ );
24373
+ }
24374
+ async ensureSessionLocked(threadId, channelId, contextThreadId) {
24351
24375
  if (!this.connection || !this.initialized) {
24352
24376
  throw new Error("AcpClient.start() must be called before ensureSession()");
24353
24377
  }
24378
+ const generation = this.generation;
24354
24379
  await this.ensureStoreLoaded();
24355
- const key = { threadId, agentId: this.options.agent.id };
24356
- const cached3 = this.sessions.get(key);
24357
- if (cached3) return cached3.sessionId;
24380
+ if (generation !== this.generation) throw new Error("ACP connection changed during session setup");
24381
+ const key2 = { threadId, agentId: this.options.agent.id };
24382
+ const cached3 = this.sessions.get(key2);
24383
+ if (cached3) {
24384
+ this.emitLifecycle(threadId, cached3.sessionId, "recovered", void 0, "cached");
24385
+ this.scheduleIdle(threadId);
24386
+ return cached3.sessionId;
24387
+ }
24358
24388
  const mcpServers = this.options.contextSpawn ? [await this.options.contextSpawn(contextThreadId ?? threadId, channelId, threadId)] : [];
24389
+ if (generation !== this.generation) throw new Error("ACP connection changed during session setup");
24359
24390
  process.stderr.write(
24360
24391
  `[acp-client:${this.options.agent.id}] ensureSession(${threadId}) mcpServers=${mcpServers.length === 0 ? "[]" : JSON.stringify(
24361
24392
  mcpServers.map((s) => ({
@@ -24367,36 +24398,158 @@ var AcpClient = class {
24367
24398
  `
24368
24399
  );
24369
24400
  const persisted = this.store?.get(threadId);
24370
- if (persisted && this.agentCapabilities.loadSession) {
24371
- let loaded;
24372
- try {
24373
- loaded = await this.connection.loadSession({
24374
- sessionId: persisted,
24375
- cwd: pathResolve(this.options.agent.cwd ?? process.cwd()),
24376
- mcpServers
24377
- });
24378
- } catch (err) {
24379
- console.warn(
24380
- `[acp-client:${this.options.agent.id}] loadSession(${persisted}) failed; falling back to newSession:`,
24381
- err
24382
- );
24383
- await this.store?.delete(threadId);
24384
- }
24385
- if (loaded) {
24386
- await this.applyMode(persisted, loaded.modes);
24387
- this.sessions.set(key, { sessionId: persisted, startedAt: Date.now() });
24388
- return persisted;
24401
+ if (persisted) {
24402
+ const request = {
24403
+ sessionId: persisted,
24404
+ cwd: pathResolve(this.options.agent.cwd ?? process.cwd()),
24405
+ mcpServers
24406
+ };
24407
+ for (const method of ["resume", "load"]) {
24408
+ if (method === "resume" && !this.agentCapabilities.sessionCapabilities?.resume) continue;
24409
+ if (method === "load" && !this.agentCapabilities.loadSession) continue;
24410
+ this.replay.add(`${generation}:${persisted}`);
24411
+ try {
24412
+ const recovered = method === "resume" ? await this.connection.resumeSession(request) : await this.connection.loadSession(request);
24413
+ if (generation !== this.generation) {
24414
+ throw new Error("ACP connection changed during recovery");
24415
+ }
24416
+ await this.applyMode(persisted, recovered.modes);
24417
+ this.sessions.set(key2, { sessionId: persisted, startedAt: Date.now() });
24418
+ this.emitLifecycle(threadId, persisted, "recovered", void 0, method);
24419
+ this.scheduleIdle(threadId);
24420
+ return persisted;
24421
+ } catch (err) {
24422
+ if (generation !== this.generation) throw err;
24423
+ console.warn(
24424
+ `[acp-client:${this.options.agent.id}] ${method}Session(${persisted}) failed for ${threadId}:`,
24425
+ err
24426
+ );
24427
+ this.emitLifecycle(threadId, persisted, "failed", void 0, method);
24428
+ } finally {
24429
+ this.replay.delete(`${generation}:${persisted}`);
24430
+ }
24389
24431
  }
24390
24432
  }
24391
24433
  const { sessionId, modes } = await this.connection.newSession({
24392
24434
  cwd: pathResolve(this.options.agent.cwd ?? process.cwd()),
24393
24435
  mcpServers
24394
24436
  });
24437
+ if (generation !== this.generation) throw new Error("ACP connection changed during session setup");
24395
24438
  await this.applyMode(sessionId, modes);
24396
- this.sessions.set(key, { sessionId, startedAt: Date.now() });
24439
+ if (generation !== this.generation) throw new Error("ACP connection changed during session setup");
24440
+ this.sessions.set(key2, { sessionId, startedAt: Date.now() });
24397
24441
  await this.store?.set(threadId, sessionId);
24442
+ this.emitLifecycle(threadId, sessionId, "recovered", void 0, "new");
24443
+ this.scheduleIdle(threadId);
24398
24444
  return sessionId;
24399
24445
  }
24446
+ state(threadId) {
24447
+ let state = this.lifecycle.get(threadId);
24448
+ if (!state) {
24449
+ state = {
24450
+ tail: Promise.resolve(),
24451
+ prompts: 0,
24452
+ activeTurns: /* @__PURE__ */ new Set(),
24453
+ humans: 0,
24454
+ resetting: false,
24455
+ closing: false
24456
+ };
24457
+ this.lifecycle.set(threadId, state);
24458
+ }
24459
+ return state;
24460
+ }
24461
+ enqueue(threadId, work) {
24462
+ const state = this.state(threadId);
24463
+ const result = state.tail.then(work, work);
24464
+ state.tail = result.catch(() => {
24465
+ });
24466
+ return result;
24467
+ }
24468
+ clearTimer(threadId) {
24469
+ const state = this.state(threadId);
24470
+ if (state.timer) clearTimeout(state.timer);
24471
+ state.timer = void 0;
24472
+ }
24473
+ clearTimers() {
24474
+ for (const threadId of this.lifecycle.keys()) this.clearTimer(threadId);
24475
+ }
24476
+ scheduleIdle(threadId) {
24477
+ const state = this.state(threadId);
24478
+ this.clearTimer(threadId);
24479
+ const timeout = this.options.sessionIdleTimeoutMs ?? 6e5;
24480
+ if (!timeout || state.prompts || state.humans || state.resetting || state.closing || !this.initialized) return;
24481
+ if (!this.sessions.get({ threadId, agentId: this.options.agent.id })) return;
24482
+ const caps = this.agentCapabilities;
24483
+ if (!caps.sessionCapabilities?.close) {
24484
+ this.warnNoIdleClose("session/close unsupported; adapter resources remain until process exit");
24485
+ return;
24486
+ }
24487
+ if (!caps.sessionCapabilities.resume && !caps.loadSession) {
24488
+ this.warnNoIdleClose("adapter cannot resume or load sessions; idle close disabled to keep context");
24489
+ return;
24490
+ }
24491
+ const generation = this.generation;
24492
+ state.timer = setTimeout(() => {
24493
+ if (generation === this.generation) void this.closeIdleSession(threadId);
24494
+ }, timeout);
24495
+ state.timer.unref?.();
24496
+ }
24497
+ warnNoIdleClose(reason) {
24498
+ if (this.warnedNoClose) return;
24499
+ console.warn(`[acp-client:${this.options.agent.id}] ${reason}`);
24500
+ this.warnedNoClose = true;
24501
+ }
24502
+ emitLifecycle(sessionKey, sessionId, outcome, reason, recoveryMethod) {
24503
+ this.options.onLifecycle?.({
24504
+ agentId: this.options.agent.id,
24505
+ sessionKey,
24506
+ sessionId,
24507
+ reason,
24508
+ outcome,
24509
+ recoveryMethod
24510
+ });
24511
+ }
24512
+ setHumanRequestPending(threadId, pending) {
24513
+ const state = this.state(threadId);
24514
+ state.humans = Math.max(0, state.humans + (pending ? 1 : -1));
24515
+ if (pending) this.clearTimer(threadId);
24516
+ else this.scheduleIdle(threadId);
24517
+ }
24518
+ async closeIdleSession(threadId) {
24519
+ const claim = this.state(threadId);
24520
+ if (claim.prompts || claim.humans || claim.resetting || claim.closing) return;
24521
+ claim.closing = true;
24522
+ return this.enqueue(threadId, async () => {
24523
+ const state = this.state(threadId);
24524
+ this.clearTimer(threadId);
24525
+ try {
24526
+ if (state.humans || state.resetting) return;
24527
+ const key2 = { threadId, agentId: this.options.agent.id };
24528
+ const live = this.sessions.get(key2);
24529
+ if (!live || !this.connection || !this.initialized) return;
24530
+ if (!this.agentCapabilities.sessionCapabilities?.close) {
24531
+ this.warnNoIdleClose("session/close unsupported; adapter resources remain until process exit");
24532
+ this.emitLifecycle(threadId, live.sessionId, "unsupported", "idle");
24533
+ return;
24534
+ }
24535
+ const generation = this.generation;
24536
+ try {
24537
+ await this.connection.closeSession({ sessionId: live.sessionId });
24538
+ this.emitLifecycle(threadId, live.sessionId, "closed", "idle");
24539
+ } catch (err) {
24540
+ console.warn(
24541
+ `[acp-client:${this.options.agent.id}] idle close failed for ${threadId}/${live.sessionId}:`,
24542
+ err
24543
+ );
24544
+ this.emitLifecycle(threadId, live.sessionId, "failed", "idle");
24545
+ } finally {
24546
+ if (generation === this.generation) this.sessions.delete(key2);
24547
+ }
24548
+ } finally {
24549
+ state.closing = false;
24550
+ }
24551
+ });
24552
+ }
24400
24553
  /**
24401
24554
  * Put a freshly created or loaded session into the agent's configured mode.
24402
24555
  * Mode ids are adapter-defined, so an id the adapter doesn't list is a
@@ -24451,31 +24604,94 @@ var AcpClient = class {
24451
24604
  await this.connection.cancel({ sessionId });
24452
24605
  }
24453
24606
  /**
24454
- * Drop the session for the given thread so the next prompt starts fresh.
24455
- * No ACP-side cancellation — callers should ensure no prompt is in flight.
24607
+ * Cancel outstanding work, close the live ACP session when supported, and
24608
+ * forget the durable pointer so the next prompt starts fresh.
24456
24609
  */
24457
- endSession(threadId) {
24458
- this.sessions.delete({ threadId, agentId: this.options.agent.id });
24459
- void this.store?.delete(threadId);
24610
+ async endSession(threadId) {
24611
+ const state = this.state(threadId);
24612
+ state.resetting = true;
24613
+ this.clearTimer(threadId);
24614
+ const key2 = { threadId, agentId: this.options.agent.id };
24615
+ const live = this.sessions.get(key2);
24616
+ return this.enqueue(threadId, async () => {
24617
+ try {
24618
+ if (live) {
24619
+ for (const cancel of this.permissionCancels.get(live.sessionId) ?? []) cancel();
24620
+ if (state.activeTurns.size) {
24621
+ try {
24622
+ await this.cancel(live.sessionId);
24623
+ } catch (err) {
24624
+ console.warn(
24625
+ `[acp-client:${this.options.agent.id}] cancel failed for ${threadId}/${live.sessionId}:`,
24626
+ err
24627
+ );
24628
+ }
24629
+ await Promise.allSettled([...state.activeTurns]);
24630
+ }
24631
+ }
24632
+ await this.ensureStoreLoaded();
24633
+ const current = this.sessions.get(key2);
24634
+ if (current && this.connection && this.initialized && this.agentCapabilities.sessionCapabilities?.close) {
24635
+ try {
24636
+ await this.connection.closeSession({ sessionId: current.sessionId });
24637
+ this.emitLifecycle(threadId, current.sessionId, "closed", "clear");
24638
+ } catch (err) {
24639
+ console.warn(
24640
+ `[acp-client:${this.options.agent.id}] clear close failed for ${threadId}/${current.sessionId}:`,
24641
+ err
24642
+ );
24643
+ this.emitLifecycle(threadId, current.sessionId, "failed", "clear");
24644
+ }
24645
+ } else if (current) {
24646
+ this.warnNoIdleClose("session/close unsupported; adapter resources remain until process exit");
24647
+ this.emitLifecycle(threadId, current.sessionId, "unsupported", "clear");
24648
+ }
24649
+ this.sessions.delete(key2);
24650
+ await this.store?.delete(threadId);
24651
+ } finally {
24652
+ state.humans = 0;
24653
+ state.resetting = false;
24654
+ }
24655
+ });
24460
24656
  }
24461
24657
  async prompt(input) {
24658
+ const generation = this.generation;
24659
+ const state = this.state(input.threadId);
24660
+ state.prompts++;
24661
+ this.clearTimer(input.threadId);
24462
24662
  let sessionId = null;
24463
24663
  let turnId = null;
24464
24664
  try {
24465
- sessionId = await this.ensureSession(input.threadId, input.channelId, input.contextThreadId);
24466
- const promptText = stringifyPromptForLog(input.content);
24467
- turnId = this.turns?.startTurn({ sessionId, promptText }) ?? null;
24468
- debugLog(this.options.agent.id, "prompt \u2192", {
24469
- sessionId,
24470
- content: input.content
24471
- });
24472
- const result = await this.connection.prompt({
24473
- sessionId,
24474
- prompt: input.content
24665
+ const launched = await this.enqueue(input.threadId, async () => {
24666
+ const id = await this.ensureSessionLocked(
24667
+ input.threadId,
24668
+ input.channelId,
24669
+ input.contextThreadId
24670
+ );
24671
+ sessionId = id;
24672
+ const promptText = stringifyPromptForLog(input.content);
24673
+ turnId = this.turns?.startTurn({ sessionId: id, promptText }) ?? null;
24674
+ debugLog(this.options.agent.id, "prompt \u2192", {
24675
+ sessionId: id,
24676
+ content: input.content
24677
+ });
24678
+ let finish;
24679
+ const completed = new Promise((resolve) => {
24680
+ finish = resolve;
24681
+ });
24682
+ const result2 = this.connection.prompt({ sessionId: id, prompt: input.content });
24683
+ state.activeTurns.add(completed);
24684
+ void result2.finally(() => {
24685
+ state.activeTurns.delete(completed);
24686
+ finish();
24687
+ }).catch(() => {
24688
+ });
24689
+ return { id, result: result2 };
24475
24690
  });
24476
- this.turns?.endTurn({ sessionId, stopReason: result.stopReason });
24691
+ const result = await launched.result;
24692
+ this.turns?.endTurn({ sessionId: launched.id, stopReason: result.stopReason });
24477
24693
  debugLog(this.options.agent.id, "prompt \u2190", {
24478
- sessionId,
24694
+ sessionId: launched.id,
24479
24695
  stopReason: result.stopReason
24480
24696
  });
24481
24697
  return { stopReason: result.stopReason };
@@ -24494,6 +24710,9 @@ var AcpClient = class {
24494
24710
  });
24495
24711
  if (sessionId) this.turns?.endTurn({ sessionId, stopReason: "error" });
24496
24712
  throw err;
24713
+ } finally {
24714
+ state.prompts--;
24715
+ if (generation === this.generation) this.scheduleIdle(input.threadId);
24497
24716
  }
24498
24717
  }
24499
24718
  resolveSpawn() {
@@ -24508,8 +24727,12 @@ var AcpClient = class {
24508
24727
  }
24509
24728
  buildClient() {
24510
24729
  const agentId = this.options.agent.id;
24730
+ const generation = this.generation;
24511
24731
  return {
24512
24732
  sessionUpdate: async (params) => {
24733
+ if (generation !== this.generation || this.replay.has(`${generation}:${params.sessionId}`)) {
24734
+ return;
24735
+ }
24513
24736
  this.turns?.observeUpdate(params.sessionId, params.update);
24514
24737
  debugLog(agentId, "sessionUpdate", params);
24515
24738
  const event = acpUpdateToAgentEvent(params);
@@ -24517,22 +24740,43 @@ var AcpClient = class {
24517
24740
  else debugLog(agentId, "sessionUpdate dropped (unmapped)", params);
24518
24741
  },
24519
24742
  requestPermission: async (params) => {
24743
+ if (generation !== this.generation) return { outcome: { outcome: "cancelled" } };
24520
24744
  debugLog(agentId, "requestPermission", params);
24521
24745
  const tc = params.toolCall;
24522
- const decision = await this.options.onApprovalRequest({
24523
- sessionId: params.sessionId,
24524
- toolCallId: tc.toolCallId,
24525
- toolKind: tc.kind,
24526
- toolTitle: tc.title,
24527
- toolInput: tc.rawInput,
24528
- options: params.options.map((o) => ({
24529
- optionId: o.optionId,
24530
- name: o.name,
24531
- kind: o.kind
24532
- }))
24746
+ const threadId = [...this.lifecycle.keys()].find(
24747
+ (key2) => this.sessions.get({ threadId: key2, agentId })?.sessionId === params.sessionId
24748
+ );
24749
+ if (threadId) this.setHumanRequestPending(threadId, true);
24750
+ let cancel;
24751
+ const cancelled = new Promise((resolve) => {
24752
+ cancel = () => resolve({ decision: "cancel" });
24533
24753
  });
24534
- debugLog(agentId, "requestPermission \u2190", decision);
24535
- return approvalDecisionToPermissionResponse(decision);
24754
+ const pending = this.permissionCancels.get(params.sessionId) ?? /* @__PURE__ */ new Set();
24755
+ pending.add(cancel);
24756
+ this.permissionCancels.set(params.sessionId, pending);
24757
+ try {
24758
+ const decision = await Promise.race([
24759
+ this.options.onApprovalRequest({
24760
+ sessionId: params.sessionId,
24761
+ toolCallId: tc.toolCallId,
24762
+ toolKind: tc.kind,
24763
+ toolTitle: tc.title,
24764
+ toolInput: tc.rawInput,
24765
+ options: params.options.map((o) => ({
24766
+ optionId: o.optionId,
24767
+ name: o.name,
24768
+ kind: o.kind
24769
+ }))
24770
+ }),
24771
+ cancelled
24772
+ ]);
24773
+ debugLog(agentId, "requestPermission \u2190", decision);
24774
+ return approvalDecisionToPermissionResponse(decision);
24775
+ } finally {
24776
+ pending.delete(cancel);
24777
+ if (!pending.size) this.permissionCancels.delete(params.sessionId);
24778
+ if (threadId) this.setHumanRequestPending(threadId, false);
24779
+ }
24536
24780
  }
24537
24781
  };
24538
24782
  }
@@ -24544,9 +24788,9 @@ function stringifyPromptForLog(content) {
24544
24788
  return "<unstringifiable>";
24545
24789
  }
24546
24790
  }
24547
- function debugLog(agentId, label, payload) {
24791
+ function debugLog(agentId, label2, payload) {
24548
24792
  if (payload === void 0) {
24549
- process.stderr.write(`[${agentId}] ${label}
24793
+ process.stderr.write(`[${agentId}] ${label2}
24550
24794
  `);
24551
24795
  return;
24552
24796
  }
@@ -24557,7 +24801,7 @@ function debugLog(agentId, label, payload) {
24557
24801
  s = String(payload);
24558
24802
  }
24559
24803
  if (s.length > 2e3) s = s.slice(0, 2e3) + "\u2026";
24560
- process.stderr.write(`[${agentId}] ${label} ${s}
24804
+ process.stderr.write(`[${agentId}] ${label2} ${s}
24561
24805
  `);
24562
24806
  }
24563
24807
  function forwardStderr(stream, agentId) {
@@ -24585,15 +24829,15 @@ var EnvInterpolationError = class extends Error {
24585
24829
  };
24586
24830
  var isDenied = (name) => name === "ZOOID_TOKEN" || name.startsWith("ZOOID_");
24587
24831
  function interpolateEnv(parsed, processEnv, scope) {
24588
- for (const [key, val] of Object.entries(parsed)) {
24589
- if (isDenied(key)) {
24832
+ for (const [key2, val] of Object.entries(parsed)) {
24833
+ if (isDenied(key2)) {
24590
24834
  throw new EnvInterpolationError(
24591
- `${scope}.${key}: keys in the ZOOID_* namespace are not allowed`
24835
+ `${scope}.${key2}: keys in the ZOOID_* namespace are not allowed`
24592
24836
  );
24593
24837
  }
24594
24838
  if (typeof val !== "string") {
24595
24839
  throw new EnvInterpolationError(
24596
- `${scope}.${key}: env values must be strings (got ${typeof val})`
24840
+ `${scope}.${key2}: env values must be strings (got ${typeof val})`
24597
24841
  );
24598
24842
  }
24599
24843
  REF_RE.lastIndex = 0;
@@ -24602,14 +24846,14 @@ function interpolateEnv(parsed, processEnv, scope) {
24602
24846
  const ref = m[1] ?? m[2];
24603
24847
  if (isDenied(ref)) {
24604
24848
  throw new EnvInterpolationError(
24605
- `${scope}.${key}: references to ZOOID_* vars are not allowed (saw \${${ref}})`
24849
+ `${scope}.${key2}: references to ZOOID_* vars are not allowed (saw \${${ref}})`
24606
24850
  );
24607
24851
  }
24608
24852
  }
24609
24853
  }
24610
24854
  const out = {};
24611
- for (const [key, val] of Object.entries(parsed)) {
24612
- out[key] = interpolateString(val, processEnv);
24855
+ for (const [key2, val] of Object.entries(parsed)) {
24856
+ out[key2] = interpolateString(val, processEnv);
24613
24857
  }
24614
24858
  return out;
24615
24859
  }
@@ -25896,14 +26140,14 @@ function checkListItem(field, index, value) {
25896
26140
  }
25897
26141
  return void 0;
25898
26142
  }
25899
- function checkMapEntry(field, key, value) {
25900
- const checkKey = checkScalarValue(field.mapKey)(key);
26143
+ function checkMapEntry(field, key2, value) {
26144
+ const checkKey = checkScalarValue(field.mapKey)(key2);
25901
26145
  if (checkKey !== true) {
25902
- return new FieldError(field, `invalid map key: ${reasonSingular({ scalar: field.mapKey }, key, checkKey)}`);
26146
+ return new FieldError(field, `invalid map key: ${reasonSingular({ scalar: field.mapKey }, key2, checkKey)}`);
25903
26147
  }
25904
26148
  const checkVal = checkSingular(field, value);
25905
26149
  if (checkVal !== true) {
25906
- return new FieldError(field, `map entry ${formatVal(key)}: ${reasonSingular(field, value, checkVal)}`);
26150
+ return new FieldError(field, `map entry ${formatVal(key2)}: ${reasonSingular(field, value, checkVal)}`);
25907
26151
  }
25908
26152
  return void 0;
25909
26153
  }
@@ -26616,18 +26860,18 @@ var ReflectMapImpl = class {
26616
26860
  field() {
26617
26861
  return this._field;
26618
26862
  }
26619
- set(key, value) {
26863
+ set(key2, value) {
26620
26864
  if (this.check) {
26621
- const err = checkMapEntry(this._field, key, value);
26865
+ const err = checkMapEntry(this._field, key2, value);
26622
26866
  if (err) {
26623
26867
  throw err;
26624
26868
  }
26625
26869
  }
26626
- this.obj[mapKeyToLocal(key)] = mapValueToLocal(this._field, value);
26870
+ this.obj[mapKeyToLocal(key2)] = mapValueToLocal(this._field, value);
26627
26871
  return this;
26628
26872
  }
26629
- delete(key) {
26630
- const k = mapKeyToLocal(key);
26873
+ delete(key2) {
26874
+ const k = mapKeyToLocal(key2);
26631
26875
  const has = Object.prototype.hasOwnProperty.call(this.obj, k);
26632
26876
  if (has) {
26633
26877
  delete this.obj[k];
@@ -26635,19 +26879,19 @@ var ReflectMapImpl = class {
26635
26879
  return has;
26636
26880
  }
26637
26881
  clear() {
26638
- for (const key of Object.keys(this.obj)) {
26639
- delete this.obj[key];
26882
+ for (const key2 of Object.keys(this.obj)) {
26883
+ delete this.obj[key2];
26640
26884
  }
26641
26885
  }
26642
- get(key) {
26643
- let val = this.obj[mapKeyToLocal(key)];
26886
+ get(key2) {
26887
+ let val = this.obj[mapKeyToLocal(key2)];
26644
26888
  if (val !== void 0) {
26645
26889
  val = mapValueToReflect(this._field, val, this.check);
26646
26890
  }
26647
26891
  return val;
26648
26892
  }
26649
- has(key) {
26650
- return Object.prototype.hasOwnProperty.call(this.obj, mapKeyToLocal(key));
26893
+ has(key2) {
26894
+ return Object.prototype.hasOwnProperty.call(this.obj, mapKeyToLocal(key2));
26651
26895
  }
26652
26896
  *keys() {
26653
26897
  for (const objKey of Object.keys(this.obj)) {
@@ -26728,26 +26972,26 @@ function mapValueToReflect(field, value, check3) {
26728
26972
  }
26729
26973
  return value;
26730
26974
  }
26731
- function mapKeyToLocal(key) {
26732
- return typeof key == "string" || typeof key == "number" ? key : String(key);
26975
+ function mapKeyToLocal(key2) {
26976
+ return typeof key2 == "string" || typeof key2 == "number" ? key2 : String(key2);
26733
26977
  }
26734
- function mapKeyToReflect(key, type) {
26978
+ function mapKeyToReflect(key2, type) {
26735
26979
  switch (type) {
26736
26980
  case ScalarType.STRING:
26737
- return key;
26981
+ return key2;
26738
26982
  case ScalarType.INT32:
26739
26983
  case ScalarType.FIXED32:
26740
26984
  case ScalarType.UINT32:
26741
26985
  case ScalarType.SFIXED32:
26742
26986
  case ScalarType.SINT32: {
26743
- const n = Number.parseInt(key);
26987
+ const n = Number.parseInt(key2);
26744
26988
  if (Number.isFinite(n)) {
26745
26989
  return n;
26746
26990
  }
26747
26991
  break;
26748
26992
  }
26749
26993
  case ScalarType.BOOL:
26750
- switch (key) {
26994
+ switch (key2) {
26751
26995
  case "true":
26752
26996
  return true;
26753
26997
  case "false":
@@ -26757,18 +27001,18 @@ function mapKeyToReflect(key, type) {
26757
27001
  case ScalarType.UINT64:
26758
27002
  case ScalarType.FIXED64:
26759
27003
  try {
26760
- return protoInt64.uParse(key);
27004
+ return protoInt64.uParse(key2);
26761
27005
  } catch (_a3) {
26762
27006
  }
26763
27007
  break;
26764
27008
  default:
26765
27009
  try {
26766
- return protoInt64.parse(key);
27010
+ return protoInt64.parse(key2);
26767
27011
  } catch (_b) {
26768
27012
  }
26769
27013
  break;
26770
27014
  }
26771
- return key;
27015
+ return key2;
26772
27016
  }
26773
27017
  function longToReflect(field, value) {
26774
27018
  switch (field.scalar) {
@@ -27677,15 +27921,15 @@ function newField(proto, parentOrFile, reg, oneof, mapEntries) {
27677
27921
  enumerable: true,
27678
27922
  configurable: true
27679
27923
  });
27680
- const label = proto.label;
27924
+ const label2 = proto.label;
27681
27925
  const type = proto.type;
27682
27926
  const jstype = (_c = proto.options) === null || _c === void 0 ? void 0 : _c.jstype;
27683
- if (label === LABEL_REPEATED) {
27927
+ if (label2 === LABEL_REPEATED) {
27684
27928
  const mapEntry = type == TYPE_MESSAGE ? mapEntries === null || mapEntries === void 0 ? void 0 : mapEntries.get(trimLeadingDot(proto.typeName)) : void 0;
27685
27929
  if (mapEntry) {
27686
27930
  field.fieldKind = "map";
27687
- const { key, value } = findMapEntryFields(mapEntry);
27688
- field.mapKey = key.scalar;
27931
+ const { key: key2, value } = findMapEntryFields(mapEntry);
27932
+ field.mapKey = key2.scalar;
27689
27933
  field.mapKind = value.fieldKind;
27690
27934
  field.message = value.message;
27691
27935
  field.delimitedEncoding = false;
@@ -27859,10 +28103,10 @@ function isPackedField(proto, parent) {
27859
28103
  });
27860
28104
  }
27861
28105
  function findMapEntryFields(mapEntry) {
27862
- const key = mapEntry.fields.find((f) => f.number === 1);
28106
+ const key2 = mapEntry.fields.find((f) => f.number === 1);
27863
28107
  const value = mapEntry.fields.find((f) => f.number === 2);
27864
- assert2(key && key.fieldKind == "scalar" && key.scalar != ScalarType.BYTES && key.scalar != ScalarType.FLOAT && key.scalar != ScalarType.DOUBLE && value && value.fieldKind != "list" && value.fieldKind != "map");
27865
- return { key, value };
28108
+ assert2(key2 && key2.fieldKind == "scalar" && key2.scalar != ScalarType.BYTES && key2.scalar != ScalarType.FLOAT && key2.scalar != ScalarType.DOUBLE && value && value.fieldKind != "list" && value.fieldKind != "map");
28109
+ return { key: key2, value };
27866
28110
  }
27867
28111
  function isEnumOpen(desc) {
27868
28112
  var _a3;
@@ -28401,7 +28645,7 @@ function compileMapFieldReader(field) {
28401
28645
  }
28402
28646
  return (message, reader, ctx) => {
28403
28647
  const record3 = message[localName];
28404
- let key;
28648
+ let key2;
28405
28649
  let val;
28406
28650
  const len = reader.uint32();
28407
28651
  const end = reader.pos + len;
@@ -28409,20 +28653,20 @@ function compileMapFieldReader(field) {
28409
28653
  const [fieldNo] = reader.tag();
28410
28654
  switch (fieldNo) {
28411
28655
  case 1:
28412
- key = readKey(reader);
28656
+ key2 = readKey(reader);
28413
28657
  break;
28414
28658
  case 2:
28415
28659
  val = readValue(reader, ctx);
28416
28660
  break;
28417
28661
  }
28418
28662
  }
28419
- if (key === void 0) {
28420
- key = keyZero;
28663
+ if (key2 === void 0) {
28664
+ key2 = keyZero;
28421
28665
  }
28422
28666
  if (val === void 0) {
28423
28667
  val = valueDefault();
28424
28668
  }
28425
- record3[key] = val;
28669
+ record3[key2] = val;
28426
28670
  };
28427
28671
  }
28428
28672
  function compileScalarReader(type, utf8Validation, longAsString) {
@@ -28718,11 +28962,11 @@ function compileMapField(field) {
28718
28962
  const record3 = message[localName];
28719
28963
  const keys = Object.keys(record3);
28720
28964
  for (let i = 0; i < keys.length; i++) {
28721
- const key = keys[i];
28965
+ const key2 = keys[i];
28722
28966
  writer.tag(fieldNo, WireType.LengthDelimited).fork();
28723
- writeKey(writer, key);
28967
+ writeKey(writer, key2);
28724
28968
  writer.tag(2, WireType.LengthDelimited).fork();
28725
- writeMessage(writer, opts, toMessage(record3[key]));
28969
+ writeMessage(writer, opts, toMessage(record3[key2]));
28726
28970
  writer.join();
28727
28971
  writer.join();
28728
28972
  }
@@ -28735,11 +28979,11 @@ function compileMapField(field) {
28735
28979
  const record3 = message[localName];
28736
28980
  const keys = Object.keys(record3);
28737
28981
  for (let i = 0; i < keys.length; i++) {
28738
- const key = keys[i];
28982
+ const key2 = keys[i];
28739
28983
  writer.tag(fieldNo, WireType.LengthDelimited).fork();
28740
- writeKey(writer, key);
28984
+ writeKey(writer, key2);
28741
28985
  writer.tag(2, valueWireType);
28742
- writeScalar(writer, record3[key]);
28986
+ writeScalar(writer, record3[key2]);
28743
28987
  writer.join();
28744
28988
  }
28745
28989
  };
@@ -28748,40 +28992,40 @@ function compileMapKey(field) {
28748
28992
  const wireType = writeTypeOfScalar(field.mapKey);
28749
28993
  const writeScalar = compileScalarValue(field.mapKey, field.parent.typeName, field.name);
28750
28994
  const convertKey = compileMapKeyConverter(field.mapKey);
28751
- return (writer, key) => {
28995
+ return (writer, key2) => {
28752
28996
  writer.tag(1, wireType);
28753
- writeScalar(writer, convertKey(key));
28997
+ writeScalar(writer, convertKey(key2));
28754
28998
  };
28755
28999
  }
28756
29000
  function compileMapKeyConverter(type) {
28757
29001
  switch (type) {
28758
29002
  case ScalarType.STRING:
28759
- return (key) => key;
29003
+ return (key2) => key2;
28760
29004
  case ScalarType.BOOL:
28761
- return (key) => key === "true" ? true : key === "false" ? false : key;
29005
+ return (key2) => key2 === "true" ? true : key2 === "false" ? false : key2;
28762
29006
  case ScalarType.UINT64:
28763
29007
  case ScalarType.FIXED64:
28764
- return (key) => {
29008
+ return (key2) => {
28765
29009
  try {
28766
- return protoInt64.uParse(key);
29010
+ return protoInt64.uParse(key2);
28767
29011
  } catch (_a3) {
28768
- return key;
29012
+ return key2;
28769
29013
  }
28770
29014
  };
28771
29015
  case ScalarType.INT64:
28772
29016
  case ScalarType.SFIXED64:
28773
29017
  case ScalarType.SINT64:
28774
- return (key) => {
29018
+ return (key2) => {
28775
29019
  try {
28776
- return protoInt64.parse(key);
29020
+ return protoInt64.parse(key2);
28777
29021
  } catch (_a3) {
28778
- return key;
29022
+ return key2;
28779
29023
  }
28780
29024
  };
28781
29025
  default:
28782
- return (key) => {
28783
- const n = Number.parseInt(key);
28784
- return Number.isFinite(n) ? n : key;
29026
+ return (key2) => {
29027
+ const n = Number.parseInt(key2);
29028
+ return Number.isFinite(n) ? n : key2;
28785
29029
  };
28786
29030
  }
28787
29031
  }
@@ -29057,9 +29301,9 @@ function fieldEquals(f, a, b, opts) {
29057
29301
  return false;
29058
29302
  }
29059
29303
  }
29060
- for (const key of keys) {
29061
- const va = mapA.get(key);
29062
- const vb = mapB.get(key);
29304
+ for (const key2 of keys) {
29305
+ const va = mapA.get(key2);
29306
+ const vb = mapB.get(key2);
29063
29307
  if (va === vb) {
29064
29308
  continue;
29065
29309
  }
@@ -29424,8 +29668,8 @@ function compileMapValue(field) {
29424
29668
  }
29425
29669
  const jsonObject = {};
29426
29670
  for (let i = 0; i < keys.length; i++) {
29427
- const key = keys[i];
29428
- jsonObject[key] = writeMapValue(opts, record3[key]);
29671
+ const key2 = keys[i];
29672
+ jsonObject[key2] = writeMapValue(opts, record3[key2]);
29429
29673
  }
29430
29674
  return jsonObject;
29431
29675
  };
@@ -29620,8 +29864,8 @@ function structToJson(val) {
29620
29864
  const json2 = {};
29621
29865
  const keys = Object.keys(val.fields);
29622
29866
  for (let i = 0; i < keys.length; i++) {
29623
- const key = keys[i];
29624
- json2[key] = valueToJson(val.fields[key]);
29867
+ const key2 = keys[i];
29868
+ json2[key2] = valueToJson(val.fields[key2]);
29625
29869
  }
29626
29870
  return json2;
29627
29871
  }
@@ -30061,11 +30305,11 @@ function compileMapFieldReader2(field) {
30061
30305
  for (let i = 0; i < jsonMapKeys.length; i++) {
30062
30306
  const jsonMapKey = jsonMapKeys[i];
30063
30307
  const jsonMapValue = json2[jsonMapKey];
30064
- const key = parseMapKey(jsonMapKey);
30065
- if (seen.has(key)) {
30308
+ const key2 = parseMapKey(jsonMapKey);
30309
+ if (seen.has(key2)) {
30066
30310
  throw new FieldError(field, `duplicate map key "${jsonMapKey}"`);
30067
30311
  }
30068
- seen.add(key);
30312
+ seen.add(key2);
30069
30313
  if (jsonMapValue === null && nullResets) {
30070
30314
  throw new FieldError(field, "map value must not be null");
30071
30315
  }
@@ -30073,17 +30317,17 @@ function compileMapFieldReader2(field) {
30073
30317
  if (value === tokenIgnoredUnknownEnum) {
30074
30318
  continue;
30075
30319
  }
30076
- const checkKey = checkMapKey(key);
30320
+ const checkKey = checkMapKey(key2);
30077
30321
  if (checkKey !== true) {
30078
- throw new FieldError(field, `invalid map key: ${reasonSingular({ scalar: mapKey }, key, checkKey)}`);
30322
+ throw new FieldError(field, `invalid map key: ${reasonSingular({ scalar: mapKey }, key2, checkKey)}`);
30079
30323
  }
30080
30324
  if (checkValue !== void 0) {
30081
30325
  const check3 = checkValue(value);
30082
30326
  if (check3 !== true) {
30083
- throw new FieldError(field, `map entry ${formatVal(key)}: ${reasonSingular(field, value, check3)}`);
30327
+ throw new FieldError(field, `map entry ${formatVal(key2)}: ${reasonSingular(field, value, check3)}`);
30084
30328
  }
30085
30329
  }
30086
- record3[key] = toLocalValue(value);
30330
+ record3[key2] = toLocalValue(value);
30087
30331
  }
30088
30332
  };
30089
30333
  }
@@ -30362,10 +30606,10 @@ function structFromJson(struct, json2, ctx) {
30362
30606
  }
30363
30607
  const keys = Object.keys(json2);
30364
30608
  for (let i = 0; i < keys.length; i++) {
30365
- const key = keys[i];
30609
+ const key2 = keys[i];
30366
30610
  const parsedValue = create(ValueSchema);
30367
- valueFromJson(parsedValue, json2[key], ctx);
30368
- struct.fields[key] = parsedValue;
30611
+ valueFromJson(parsedValue, json2[key2], ctx);
30612
+ struct.fields[key2] = parsedValue;
30369
30613
  }
30370
30614
  }
30371
30615
  function valueFromJson(value, json2, ctx) {
@@ -30588,15 +30832,15 @@ var CelScalar = {
30588
30832
  };
30589
30833
  var TIMESTAMP = objectType(TimestampSchema);
30590
30834
  var DURATION = objectType(DurationSchema);
30591
- function mapType(key, value) {
30835
+ function mapType(key2, value) {
30592
30836
  return {
30593
30837
  [privateSymbol4]: {},
30594
30838
  kind: "map",
30595
- key,
30839
+ key: key2,
30596
30840
  value,
30597
30841
  name: "map",
30598
30842
  toString() {
30599
- return `map(${key}, ${value})`;
30843
+ return `map(${key2}, ${value})`;
30600
30844
  }
30601
30845
  };
30602
30846
  }
@@ -30889,41 +31133,41 @@ var NativeMap = class {
30889
31133
  get size() {
30890
31134
  return this._map.size;
30891
31135
  }
30892
- get(key) {
30893
- if (isCelUint(key)) {
30894
- key = key.value;
31136
+ get(key2) {
31137
+ if (isCelUint(key2)) {
31138
+ key2 = key2.value;
30895
31139
  }
30896
- if (typeof key === "number") {
30897
- if (!Number.isInteger(key)) {
31140
+ if (typeof key2 === "number") {
31141
+ if (!Number.isInteger(key2)) {
30898
31142
  return void 0;
30899
31143
  }
30900
- key = BigInt(key);
31144
+ key2 = BigInt(key2);
30901
31145
  }
30902
- const value = this._map.get(key);
31146
+ const value = this._map.get(key2);
30903
31147
  if (value !== void 0) {
30904
31148
  return toCel(value);
30905
31149
  }
30906
- if (typeof key === "bigint") {
31150
+ if (typeof key2 === "bigint") {
30907
31151
  for (const mapKey of this._map.keys()) {
30908
31152
  if (!isCelUint(mapKey)) {
30909
31153
  continue;
30910
31154
  }
30911
- if (mapKey.value === key) {
31155
+ if (mapKey.value === key2) {
30912
31156
  return toCel(this._map.get(mapKey));
30913
31157
  }
30914
31158
  }
30915
31159
  }
30916
31160
  return void 0;
30917
31161
  }
30918
- has(key) {
30919
- return this.get(key) != void 0;
31162
+ has(key2) {
31163
+ return this.get(key2) != void 0;
30920
31164
  }
30921
31165
  forEach(callback, thisArg) {
30922
- this._map.forEach((value, key, _) => callback.call(thisArg, toCel(value), key, this));
31166
+ this._map.forEach((value, key2, _) => callback.call(thisArg, toCel(value), key2, this));
30923
31167
  }
30924
31168
  *entries() {
30925
- for (const [key, value] of this._map.entries()) {
30926
- yield [key, toCel(value)];
31169
+ for (const [key2, value] of this._map.entries()) {
31170
+ yield [key2, toCel(value)];
30927
31171
  }
30928
31172
  }
30929
31173
  keys() {
@@ -30947,30 +31191,30 @@ var ProtoMap = class {
30947
31191
  get size() {
30948
31192
  return this._map.size;
30949
31193
  }
30950
- get(key) {
30951
- const value = this._map.get(mapKeyFromCel(this._map.field(), key));
31194
+ get(key2) {
31195
+ const value = this._map.get(mapKeyFromCel(this._map.field(), key2));
30952
31196
  if (value === void 0) {
30953
31197
  return void 0;
30954
31198
  }
30955
31199
  return celFromMapValue(this._map.field(), value);
30956
31200
  }
30957
- has(key) {
30958
- return this._map.has(mapKeyFromCel(this._map.field(), key));
31201
+ has(key2) {
31202
+ return this._map.has(mapKeyFromCel(this._map.field(), key2));
30959
31203
  }
30960
31204
  forEach(callback, thisArg) {
30961
- this._map.forEach((value, key, _) => callback.call(thisArg, celFromMapValue(this._map.field(), value), celFromMapKey(this._map.field(), key), this));
31205
+ this._map.forEach((value, key2, _) => callback.call(thisArg, celFromMapValue(this._map.field(), value), celFromMapKey(this._map.field(), key2), this));
30962
31206
  }
30963
31207
  *entries() {
30964
- for (const [key, value] of this._map.entries()) {
31208
+ for (const [key2, value] of this._map.entries()) {
30965
31209
  yield [
30966
- celFromMapKey(this._map.field(), key),
31210
+ celFromMapKey(this._map.field(), key2),
30967
31211
  celFromMapValue(this._map.field(), value)
30968
31212
  ];
30969
31213
  }
30970
31214
  }
30971
31215
  *keys() {
30972
- for (const key of this._map.keys()) {
30973
- yield celFromMapKey(this._map.field(), key);
31216
+ for (const key2 of this._map.keys()) {
31217
+ yield celFromMapKey(this._map.field(), key2);
30974
31218
  }
30975
31219
  }
30976
31220
  *values() {
@@ -31714,17 +31958,17 @@ var LazyDecoder = class {
31714
31958
  this.initializer = initializer5;
31715
31959
  this.cache = /* @__PURE__ */ new Map();
31716
31960
  }
31717
- has(key) {
31718
- return key in this.initializer;
31961
+ has(key2) {
31962
+ return key2 in this.initializer;
31719
31963
  }
31720
- get(key) {
31721
- const cached3 = this.cache.get(key);
31722
- if (cached3 !== void 0 || this.cache.has(key)) {
31964
+ get(key2) {
31965
+ const cached3 = this.cache.get(key2);
31966
+ if (cached3 !== void 0 || this.cache.has(key2)) {
31723
31967
  return cached3 ?? null;
31724
31968
  }
31725
- const fn = this.initializer[key];
31969
+ const fn = this.initializer[key2];
31726
31970
  const val = fn ? fn() : null;
31727
- this.cache.set(key, val);
31971
+ this.cache.set(key2, val);
31728
31972
  return val;
31729
31973
  }
31730
31974
  };
@@ -36368,10 +36612,10 @@ var Builder = class {
36368
36612
  }
36369
36613
  return expr;
36370
36614
  }
36371
- newMapEntry(offset, key, value) {
36615
+ newMapEntry(offset, key2, value) {
36372
36616
  return this.nextEntry(offset, {
36373
36617
  case: "mapKey",
36374
- value: key
36618
+ value: key2
36375
36619
  }, value);
36376
36620
  }
36377
36621
  newStructExpr(offset, entries, messageName = "") {
@@ -36946,8 +37190,8 @@ function parse3(input, options = {}) {
36946
37190
  }
36947
37191
  return selector;
36948
37192
  }
36949
- function item430(offset, key, value) {
36950
- return builder.newStructEntry(offset(), key, value);
37193
+ function item430(offset, key2, value) {
37194
+ return builder.newStructEntry(offset(), key2, value);
36951
37195
  }
36952
37196
  function item437(offset, dot, name, entries) {
36953
37197
  return builder.newStructExpr(offset(), entries, (dot !== null ? dot : "") + name.join("."));
@@ -36958,8 +37202,8 @@ function parse3(input, options = {}) {
36958
37202
  function item461(offset, elements) {
36959
37203
  return builder.newListExpr(offset(), elements);
36960
37204
  }
36961
- function item475(offset, key, value) {
36962
- return builder.newMapEntry(offset(), key, value);
37205
+ function item475(offset, key2, value) {
37206
+ return builder.newMapEntry(offset(), key2, value);
36963
37207
  }
36964
37208
  function item484(offset, entries) {
36965
37209
  return builder.newStructExpr(offset(), entries);
@@ -42318,9 +42562,9 @@ var EvalAccess = class {
42318
42562
  key;
42319
42563
  factory;
42320
42564
  optional;
42321
- constructor(id, key, factory, optional3) {
42565
+ constructor(id, key2, factory, optional3) {
42322
42566
  this.id = id;
42323
- this.key = key;
42567
+ this.key = key2;
42324
42568
  this.factory = factory;
42325
42569
  this.optional = optional3;
42326
42570
  }
@@ -42328,30 +42572,30 @@ var EvalAccess = class {
42328
42572
  if (obj === void 0) {
42329
42573
  return obj;
42330
42574
  }
42331
- const key = this.key.eval(vars);
42332
- if (isCelError(key)) {
42333
- return key;
42575
+ const key2 = this.key.eval(vars);
42576
+ if (isCelError(key2)) {
42577
+ return key2;
42334
42578
  }
42335
- const access = this.factory.newAccess(this.id, key, this.optional);
42579
+ const access = this.factory.newAccess(this.id, key2, this.optional);
42336
42580
  return access.access(vars, obj);
42337
42581
  }
42338
42582
  isPresent(vars, obj) {
42339
42583
  if (obj === void 0) {
42340
42584
  return false;
42341
42585
  }
42342
- const key = this.key.eval(vars);
42343
- if (isCelError(key)) {
42344
- return key;
42586
+ const key2 = this.key.eval(vars);
42587
+ if (isCelError(key2)) {
42588
+ return key2;
42345
42589
  }
42346
- const access = this.factory.newAccess(this.id, key, this.optional);
42590
+ const access = this.factory.newAccess(this.id, key2, this.optional);
42347
42591
  return access.isPresent(vars, obj);
42348
42592
  }
42349
42593
  accessIfPresent(vars, obj, presenceOnly) {
42350
- const key = this.key.eval(vars);
42351
- if (isCelError(key)) {
42352
- return key;
42594
+ const key2 = this.key.eval(vars);
42595
+ if (isCelError(key2)) {
42596
+ return key2;
42353
42597
  }
42354
- const access = this.factory.newAccess(this.id, key, this.optional);
42598
+ const access = this.factory.newAccess(this.id, key2, this.optional);
42355
42599
  return access.accessIfPresent(vars, obj, presenceOnly);
42356
42600
  }
42357
42601
  isOptional() {
@@ -42509,16 +42753,16 @@ function copyList(list, cList) {
42509
42753
  function copyMap(map2, cMap) {
42510
42754
  const field = map2.field();
42511
42755
  for (const [k, v] of cMap.entries()) {
42512
- const key = scalarFromCel(field, field.mapKey, k);
42756
+ const key2 = scalarFromCel(field, field.mapKey, k);
42513
42757
  switch (field.mapKind) {
42514
42758
  case "enum":
42515
- map2.set(key, enumFromCel(field, v));
42759
+ map2.set(key2, enumFromCel(field, v));
42516
42760
  break;
42517
42761
  case "scalar":
42518
- map2.set(key, scalarFromCel(field, field.scalar, v));
42762
+ map2.set(key2, scalarFromCel(field, field.scalar, v));
42519
42763
  break;
42520
42764
  case "message":
42521
- map2.set(key, msgFromCel(field, v));
42765
+ map2.set(key2, msgFromCel(field, v));
42522
42766
  break;
42523
42767
  }
42524
42768
  }
@@ -43209,38 +43453,38 @@ var EvalMap = class {
43209
43453
  }
43210
43454
  entries.set(firstKey, firstVal);
43211
43455
  for (let i = 1; i < this.keys.length; i++) {
43212
- const key = this.mapKeyOrError(this.keys[i].eval(ctx));
43213
- if (isCelError(key)) {
43214
- return key;
43456
+ const key2 = this.mapKeyOrError(this.keys[i].eval(ctx));
43457
+ if (isCelError(key2)) {
43458
+ return key2;
43215
43459
  }
43216
43460
  const val = this.values[i].eval(ctx);
43217
43461
  if (isCelError(val)) {
43218
43462
  return val;
43219
43463
  }
43220
- if (entries.has(key)) {
43221
- return celError(`map key conflict: ${key}`, this.id);
43464
+ if (entries.has(key2)) {
43465
+ return celError(`map key conflict: ${key2}`, this.id);
43222
43466
  }
43223
- if (typeof key === "number" && !Number.isInteger(key)) {
43467
+ if (typeof key2 === "number" && !Number.isInteger(key2)) {
43224
43468
  return unsupportedKeyType(this.id);
43225
43469
  }
43226
- entries.set(key, val);
43470
+ entries.set(key2, val);
43227
43471
  }
43228
43472
  return celMap(entries);
43229
43473
  }
43230
- mapKeyOrError(key) {
43231
- switch (typeof key) {
43474
+ mapKeyOrError(key2) {
43475
+ switch (typeof key2) {
43232
43476
  case "boolean":
43233
43477
  case "bigint":
43234
43478
  case "string":
43235
- return key;
43479
+ return key2;
43236
43480
  case "object":
43237
- if (isCelUint(key)) {
43238
- return key;
43481
+ if (isCelUint(key2)) {
43482
+ return key2;
43239
43483
  }
43240
43484
  return unsupportedKeyType(this.id);
43241
43485
  case "number":
43242
- if (Number.isInteger(key)) {
43243
- return BigInt(key);
43486
+ if (Number.isInteger(key2)) {
43487
+ return BigInt(key2);
43244
43488
  }
43245
43489
  return unsupportedKeyType(this.id);
43246
43490
  default:
@@ -43566,6 +43810,17 @@ function parseApprovalTimeout(name, raw) {
43566
43810
  }
43567
43811
  throw new Error("unreachable");
43568
43812
  }
43813
+ function parseSessionIdleTimeout(name, raw) {
43814
+ if (raw === void 0) return 6e5;
43815
+ if (raw === 0 || raw === "0") return 0;
43816
+ const match = typeof raw === "string" ? /^(\d+)(s|m|h)$/.exec(raw) : null;
43817
+ const multiplier = match?.[2] === "s" ? 1e3 : match?.[2] === "m" ? 6e4 : 36e5;
43818
+ const milliseconds = match ? Number(match[1]) * multiplier : NaN;
43819
+ if (!Number.isSafeInteger(milliseconds)) {
43820
+ throw new Error(`agents.${name}.session_idle_timeout: expected a duration like "30s", "15m", "2h", or 0`);
43821
+ }
43822
+ return milliseconds;
43823
+ }
43569
43824
  function parseAgentContainer(name, raw, processEnv, configDir) {
43570
43825
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
43571
43826
  throw new Error(`agents.${name}.container must be a mapping`);
@@ -44060,6 +44315,7 @@ function parseAgents(raw, runtime2, transports, daemonHooks, processEnv, configD
44060
44315
  }
44061
44316
  const acp = parseAcpBlock(name, entry.acp);
44062
44317
  const approval_timeout_ms = parseApprovalTimeout(name, entry.approval_timeout);
44318
+ const session_idle_timeout_ms = parseSessionIdleTimeout(name, entry.session_idle_timeout);
44063
44319
  if (entry.docker !== void 0) {
44064
44320
  throw new Error(
44065
44321
  `agents.${name}.docker is no longer supported. Move 'image' to agents.${name}.container.image, and 'forward_env' entries to agents.${name}.container.env with \${VAR} interpolation. See [ZOD043].`
@@ -44121,7 +44377,8 @@ See [ZOD043].`
44121
44377
  workdir,
44122
44378
  hooks: agentHooks,
44123
44379
  acp,
44124
- approval_timeout_ms
44380
+ approval_timeout_ms,
44381
+ session_idle_timeout_ms
44125
44382
  };
44126
44383
  if (containerBlock) agentCfg.container = containerBlock;
44127
44384
  if (binding.matrix) agentCfg.matrix = binding.matrix;
@@ -44242,10 +44499,10 @@ function parseTriggers(raw, agents, transports, validateCron, processEnv, config
44242
44499
  }
44243
44500
  return result;
44244
44501
  }
44245
- function parseDurationMs(label, raw) {
44502
+ function parseDurationMs(label2, raw) {
44246
44503
  const m = /^(\d+)(s|m|h)$/.exec(raw);
44247
44504
  if (!m) {
44248
- throw new Error(`${label}: "${raw}" is not a valid duration (use "<n>s", "<n>m", or "<n>h")`);
44505
+ throw new Error(`${label2}: "${raw}" is not a valid duration (use "<n>s", "<n>m", or "<n>h")`);
44249
44506
  }
44250
44507
  const n = Number(m[1]);
44251
44508
  switch (m[2]) {
@@ -44270,29 +44527,29 @@ function soleMatrixTransport(transports) {
44270
44527
  return matrixTransports[0];
44271
44528
  }
44272
44529
  function parseTriggerMessage(name, index, raw, agents, transports, as, hasWebhook, ttlMs) {
44273
- const label = `triggers.${name}.messages[${index}]`;
44530
+ const label2 = `triggers.${name}.messages[${index}]`;
44274
44531
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
44275
- throw new Error(`${label}: must be a mapping`);
44532
+ throw new Error(`${label2}: must be a mapping`);
44276
44533
  }
44277
44534
  const m = raw;
44278
44535
  if (typeof m.room !== "string" || m.room.length === 0) {
44279
- throw new Error(`${label}.room: must be a non-empty string`);
44536
+ throw new Error(`${label2}.room: must be a non-empty string`);
44280
44537
  }
44281
44538
  if (!MATRIX_ROOM_IDENT_RE.test(m.room)) {
44282
- throw new Error(`${label}.room: must start with '#' or '!' (got ${JSON.stringify(m.room)})`);
44539
+ throw new Error(`${label2}.room: must start with '#' or '!' (got ${JSON.stringify(m.room)})`);
44283
44540
  }
44284
44541
  if (typeof m.mention !== "string" || m.mention.length === 0) {
44285
- throw new Error(`${label}.mention: must be a non-empty string`);
44542
+ throw new Error(`${label2}.mention: must be a non-empty string`);
44286
44543
  }
44287
44544
  if (m.mention.startsWith("@")) {
44288
44545
  if (!MATRIX_USER_ID_RE.test(m.mention)) {
44289
- throw new Error(`${label}.mention: must be a full MXID (got ${JSON.stringify(m.mention)})`);
44546
+ throw new Error(`${label2}.mention: must be a full MXID (got ${JSON.stringify(m.mention)})`);
44290
44547
  }
44291
44548
  const server = m.mention.slice(m.mention.indexOf(":") + 1);
44292
44549
  const local = deriveServerName(soleMatrixTransport(transports).user_namespace);
44293
44550
  if (server !== local) {
44294
44551
  throw new Error(
44295
- `${label}.mention: "${m.mention}" is on a different homeserver than this daemon (${local}). A trigger addresses a user on its own homeserver \u2014 see [[ZOD081]] \xA7Non-goals.`
44552
+ `${label2}.mention: "${m.mention}" is on a different homeserver than this daemon (${local}). A trigger addresses a user on its own homeserver \u2014 see [[ZOD081]] \xA7Non-goals.`
44296
44553
  );
44297
44554
  }
44298
44555
  if (as === m.mention) {
@@ -44303,11 +44560,11 @@ function parseTriggerMessage(name, index, raw, agents, transports, as, hasWebhoo
44303
44560
  } else {
44304
44561
  const mentionedAgent = agents[m.mention];
44305
44562
  if (!mentionedAgent) {
44306
- throw new Error(`${label}.mention: unknown agent "${m.mention}"`);
44563
+ throw new Error(`${label2}.mention: unknown agent "${m.mention}"`);
44307
44564
  }
44308
44565
  if (!mentionedAgent.matrix) {
44309
44566
  throw new Error(
44310
- `${label}.mention: agent "${m.mention}" has no matrix: binding \u2014 a trigger posts through Matrix, so the mentioned agent must be matrix-bound.`
44567
+ `${label2}.mention: agent "${m.mention}" has no matrix: binding \u2014 a trigger posts through Matrix, so the mentioned agent must be matrix-bound.`
44311
44568
  );
44312
44569
  }
44313
44570
  if (as === mentionedAgent.matrix.user_id) {
@@ -44317,21 +44574,21 @@ function parseTriggerMessage(name, index, raw, agents, transports, as, hasWebhoo
44317
44574
  }
44318
44575
  }
44319
44576
  if (typeof m.text !== "string" || m.text.length === 0) {
44320
- throw new Error(`${label}.text: must be a non-empty string`);
44577
+ throw new Error(`${label2}.text: must be a non-empty string`);
44321
44578
  }
44322
44579
  const message = { room: m.room, mention: m.mention, text: m.text };
44323
44580
  if (ttlMs !== void 0) message.ttlMs = ttlMs;
44324
44581
  if (m.match !== void 0) {
44325
44582
  if (typeof m.match !== "string" || m.match.length === 0) {
44326
- throw new Error(`${label}.match: must be a non-empty string`);
44583
+ throw new Error(`${label2}.match: must be a non-empty string`);
44327
44584
  }
44328
44585
  if (!hasWebhook) {
44329
- throw new Error(`${label}.match: only applies to a webhook: trigger`);
44586
+ throw new Error(`${label2}.match: only applies to a webhook: trigger`);
44330
44587
  }
44331
44588
  try {
44332
44589
  message.match = compileMatch(m.match);
44333
44590
  } catch (err) {
44334
- throw new Error(`${label}.match: ${err.message}`);
44591
+ throw new Error(`${label2}.match: ${err.message}`);
44335
44592
  }
44336
44593
  }
44337
44594
  return message;
@@ -44603,10 +44860,10 @@ var AcpAgentRegistry = class {
44603
44860
  this.opts.onSessionEstablished?.(name, threadId, sessionId);
44604
44861
  return sessionId;
44605
44862
  }
44606
- endSession(name, threadId) {
44863
+ async endSession(name, threadId) {
44607
44864
  if (!this.hasAgent(name)) return;
44608
44865
  const client = this.clients.get(name);
44609
- client?.endSession(threadId);
44866
+ await client?.endSession(threadId);
44610
44867
  }
44611
44868
  async cancelSession(name, sessionId) {
44612
44869
  if (!this.hasAgent(name)) return;
@@ -44653,6 +44910,8 @@ var AcpAgentRegistry = class {
44653
44910
  onEvent: (e) => this.onEvent(name, e),
44654
44911
  onApprovalRequest: (req) => this.onApprovalRequest(name, req),
44655
44912
  onTap: this.opts.onTap ? (e) => this.opts.onTap(name, e) : void 0,
44913
+ onLifecycle: this.opts.onLifecycle ? (e) => this.opts.onLifecycle(name, e) : void 0,
44914
+ sessionIdleTimeoutMs: cfg.session_idle_timeout_ms,
44656
44915
  contextSpawn: this.opts.contextSpawns?.[name]
44657
44916
  });
44658
44917
  await client.start();
@@ -44765,6 +45024,7 @@ var ApprovalCorrelator = class extends EventEmitter2 {
44765
45024
  };
44766
45025
 
44767
45026
  // ../core/src/task-actions.ts
45027
+ var HANDOFF_FIELD = "dev.zooid.handoff";
44768
45028
  var NO_PENDING_INPUT = {
44769
45029
  countFor: () => 0,
44770
45030
  cancelFor: () => {
@@ -45319,6 +45579,50 @@ function isExpiredTrigger(evt, now) {
45319
45579
  return now - firedAt > ttlMs;
45320
45580
  }
45321
45581
 
45582
+ // ../transport-matrix/src/handoff.ts
45583
+ function readHandoff(content) {
45584
+ const h = content?.[HANDOFF_FIELD];
45585
+ if (!h || h.version !== 1) return void 0;
45586
+ if (typeof h.call_id !== "string" || typeof h.caller !== "string" || typeof h.callee !== "string")
45587
+ return void 0;
45588
+ return { version: 1, call_id: h.call_id, caller: h.caller, callee: h.callee };
45589
+ }
45590
+ function buildHandoffContent(input) {
45591
+ return {
45592
+ ...buildMentionContent({ userId: input.callee, text: input.prompt, msgtype: "m.notice" }),
45593
+ [HANDOFF_FIELD]: {
45594
+ version: 1,
45595
+ call_id: input.callId,
45596
+ caller: input.caller,
45597
+ callee: input.callee
45598
+ }
45599
+ };
45600
+ }
45601
+ var label = (c) => c.workstation ? `${c.workstation}.${c.name}` : c.name;
45602
+ function resolveHandoffTarget(agent, roomId, candidates) {
45603
+ const q = agent.trim();
45604
+ const inRoom = candidates.filter((c) => c.rooms.includes(roomId));
45605
+ const roster = inRoom.map(label).sort().join(", ") || "none";
45606
+ let hits;
45607
+ if (q.startsWith("@") && q.includes(":")) hits = candidates.filter((c) => c.userId === q);
45608
+ else {
45609
+ const bare = q.replace(/^@/, "");
45610
+ hits = candidates.filter((c) => label(c) === bare);
45611
+ if (hits.length === 0) hits = candidates.filter((c) => c.name === bare);
45612
+ }
45613
+ if (hits.length === 0)
45614
+ return { ok: false, reason: `unknown_agent: no agent "${q}" in this workforce. Agents in this room: ${roster}` };
45615
+ if (hits.length > 1)
45616
+ return {
45617
+ ok: false,
45618
+ reason: `ambiguous_agent: "${q}" matches ${hits.map(label).sort().join(", ")} \u2014 use workstation.agent`
45619
+ };
45620
+ const target = hits[0];
45621
+ if (!target.rooms.includes(roomId))
45622
+ return { ok: false, reason: `not_in_room: "${label(target)}" is not in this room. Agents in this room: ${roster}` };
45623
+ return { ok: true, target };
45624
+ }
45625
+
45322
45626
  // ../transport-matrix/src/router.ts
45323
45627
  var MEDIA_MSGTYPES = /* @__PURE__ */ new Set(["m.image", "m.file", "m.video", "m.audio"]);
45324
45628
  function isMediaMsgtype(t) {
@@ -45348,6 +45652,7 @@ function route(event, agents, threadStates, task, knownAgentIds) {
45348
45652
  const addressesAgent = [...mentions].some(
45349
45653
  (id) => id !== event.sender && (knownAgentIds?.has(id) === true || agents.some((x) => x.userId === id && x.rooms.some((r) => r.alias === event.room_id)))
45350
45654
  );
45655
+ const handoff = readHandoff(event.content);
45351
45656
  for (const a of agents) {
45352
45657
  if (!a.rooms.some((r) => r.alias === event.room_id)) continue;
45353
45658
  if (task?.isRoot) {
@@ -45355,46 +45660,44 @@ function route(event, agents, threadStates, task, knownAgentIds) {
45355
45660
  continue;
45356
45661
  }
45357
45662
  if (event.sender === a.userId) continue;
45663
+ const called = senderIsAgent && handoff?.caller === event.sender && handoff?.callee === a.userId;
45358
45664
  if (task) {
45359
- if (mentions.has(a.userId)) {
45360
- matches2.push(a);
45361
- continue;
45362
- }
45363
45665
  if (senderIsAgent) {
45666
+ if (called) matches2.push(a);
45364
45667
  continue;
45365
- } else if (a.name === task.assignee && !addressesAgent) {
45366
- matches2.push(a);
45367
45668
  }
45669
+ if (mentions.has(a.userId)) matches2.push(a);
45670
+ else if (a.name === task.assignee && !addressesAgent) matches2.push(a);
45368
45671
  continue;
45369
45672
  }
45370
45673
  if (a.trigger === "any") {
45371
45674
  matches2.push(a);
45372
45675
  continue;
45373
45676
  }
45677
+ if (senderIsAgent) {
45678
+ if (called || isReturnRoute(event, a, threadState)) matches2.push(a);
45679
+ continue;
45680
+ }
45374
45681
  if (mentions.has(a.userId)) {
45375
45682
  matches2.push(a);
45376
45683
  continue;
45377
45684
  }
45378
- if (threadState) {
45379
- if (senderIsAgent) {
45380
- if (isReturnRoute(event, a, agents, threadState)) matches2.push(a);
45381
- } else if (!addressesAgent) {
45382
- const lastPoster = threadState.participants.at(-1);
45383
- if (lastPoster) {
45384
- if (lastPoster === a.name) matches2.push(a);
45385
- } else if (threadState.rootMentions.includes(a.name)) {
45386
- matches2.push(a);
45387
- }
45685
+ if (threadState && !addressesAgent) {
45686
+ const lastPoster = threadState.participants.at(-1);
45687
+ if (lastPoster) {
45688
+ if (lastPoster === a.name) matches2.push(a);
45689
+ } else if (threadState.rootMentions.includes(a.name)) {
45690
+ matches2.push(a);
45388
45691
  }
45389
45692
  }
45390
45693
  }
45391
45694
  return matches2;
45392
45695
  }
45393
- function isReturnRoute(event, agent, agents, threadState) {
45696
+ function isReturnRoute(event, agent, threadState) {
45394
45697
  if (!threadState || agent.trigger !== "mention") return false;
45395
- const sender = agents.find((x) => x.userId === event.sender);
45396
- if (!sender || sender.name === agent.name) return false;
45397
- return threadState.callers[sender.name] === agent.name;
45698
+ const sender = event.sender;
45699
+ if (!sender || sender === agent.userId) return false;
45700
+ return threadState.callers[sender] === agent.userId;
45398
45701
  }
45399
45702
  function wouldCycleCallers(callers, callee, caller) {
45400
45703
  const seen = /* @__PURE__ */ new Set();
@@ -45600,18 +45903,159 @@ function buildUserPowerLevels(asUserId, admins, agents, roomAlias) {
45600
45903
 
45601
45904
  // ../transport-matrix/src/transport.ts
45602
45905
  import { Hono } from "hono";
45603
- import { timingSafeEqual } from "crypto";
45906
+ import { timingSafeEqual, randomUUID as randomUUID5 } from "crypto";
45604
45907
 
45605
45908
  // ../transport-matrix/src/session-keys.ts
45606
45909
  var HANDOFF_KEY_SEP = "|";
45607
45910
  function composeHandoffKey(threadRoot, callEventId) {
45608
45911
  return `${threadRoot}${HANDOFF_KEY_SEP}${callEventId}`;
45609
45912
  }
45610
- function sessionKeyFor(agentName, threadRoot, state) {
45611
- const arc = state?.handoffs[agentName]?.at(-1);
45913
+ function sessionKeyFor(agentUserId, threadRoot, state) {
45914
+ const arc = state?.handoffs[agentUserId]?.at(-1);
45612
45915
  return arc ? composeHandoffKey(threadRoot, arc) : threadRoot;
45613
45916
  }
45614
45917
 
45918
+ // ../transport-matrix/src/pending-returns.ts
45919
+ var PendingReturns = class {
45920
+ constructor(opts) {
45921
+ this.opts = opts;
45922
+ }
45923
+ opts;
45924
+ pending = /* @__PURE__ */ new Map();
45925
+ running = /* @__PURE__ */ new Map();
45926
+ has(callee, threadRoot) {
45927
+ return this.pending.has(key(callee, threadRoot));
45928
+ }
45929
+ /** An agent→agent call: a fresh pending return, replacing any earlier one. */
45930
+ open(callee, threadRoot, roomId, caller, o = {}) {
45931
+ const k = key(callee, threadRoot);
45932
+ this.drop(k);
45933
+ this.pending.set(k, fresh(callee, threadRoot, roomId, [caller], o.remote === true));
45934
+ }
45935
+ /** A callee message routed as a return: held, never delivered on its own. */
45936
+ hold(callee, threadRoot, roomId, targets, body, o = {}) {
45937
+ const k = key(callee, threadRoot);
45938
+ let p = this.pending.get(k);
45939
+ if (!p) {
45940
+ p = fresh(callee, threadRoot, roomId, targets, o.remote === true);
45941
+ this.pending.set(k, p);
45942
+ } else if (o.remote === true) {
45943
+ p.remote = true;
45944
+ }
45945
+ for (const t of targets) p.targets.set(t.name, t);
45946
+ const text = body?.trim();
45947
+ if (text) p.text = text;
45948
+ p.waiting = false;
45949
+ this.arm(k);
45950
+ }
45951
+ /** The callee's current turn opened a call; its turn end is not a return. */
45952
+ markDelegated(callee, threadRoot) {
45953
+ const p = this.pending.get(key(callee, threadRoot));
45954
+ if (p) p.delegated = true;
45955
+ }
45956
+ /** Sender-attributable liveness (tool calls, plans): re-arms a timed hold. */
45957
+ activity(callee, threadRoot) {
45958
+ const k = key(callee, threadRoot);
45959
+ if (this.pending.get(k)?.timer) this.arm(k);
45960
+ }
45961
+ turnStarted(agent, threadRoot) {
45962
+ const k = key(agent, threadRoot);
45963
+ this.running.set(k, (this.running.get(k) ?? 0) + 1);
45964
+ const p = this.pending.get(k);
45965
+ if (p) {
45966
+ p.waiting = false;
45967
+ disarm(p);
45968
+ }
45969
+ }
45970
+ /** The in-process turn is over; if its turn.end never echoes, the fallback catches it. */
45971
+ turnFinished(agent, threadRoot) {
45972
+ const k = key(agent, threadRoot);
45973
+ const n = (this.running.get(k) ?? 1) - 1;
45974
+ if (n > 0) this.running.set(k, n);
45975
+ else this.running.delete(k);
45976
+ this.arm(k);
45977
+ }
45978
+ /** The callee's `dev.zooid.turn.end`: release, unless the turn delegated. */
45979
+ turnEnded(callee, threadRoot) {
45980
+ const k = key(callee, threadRoot);
45981
+ const p = this.pending.get(k);
45982
+ if (!p) return;
45983
+ if (p.delegated && !p.interrupted) {
45984
+ p.delegated = false;
45985
+ p.waiting = true;
45986
+ p.text = "";
45987
+ disarm(p);
45988
+ return;
45989
+ }
45990
+ this.release(k);
45991
+ }
45992
+ /**
45993
+ * A thread interrupt. Running callees are marked so their (cancelled) turn
45994
+ * end releases; with nothing running there is no turn end coming, so every
45995
+ * pending return in the thread releases now. Call before cancelling
45996
+ * sessions, or a turn that finishes first makes the thread look idle.
45997
+ */
45998
+ interrupt(threadRoot) {
45999
+ const suffix = `::${threadRoot}`;
46000
+ const anyRunning = [...this.running.keys()].some((k) => k.endsWith(suffix));
46001
+ for (const [k, p] of [...this.pending]) {
46002
+ if (p.threadRoot !== threadRoot) continue;
46003
+ if (!anyRunning) this.release(k);
46004
+ else if (this.running.has(k)) p.interrupted = true;
46005
+ }
46006
+ }
46007
+ /** `/clear`: a pre-reset return must never wake anyone later. */
46008
+ dropThread(threadRoot) {
46009
+ for (const [k, p] of [...this.pending]) if (p.threadRoot === threadRoot) this.drop(k);
46010
+ }
46011
+ arm(k) {
46012
+ const p = this.pending.get(k);
46013
+ if (!p) return;
46014
+ disarm(p);
46015
+ if (p.waiting || this.running.has(k)) return;
46016
+ const ms = p.remote ? this.opts.remoteGraceMs ?? this.opts.graceMs : this.opts.graceMs;
46017
+ p.timer = setTimeout(() => this.release(k), ms);
46018
+ p.timer.unref?.();
46019
+ }
46020
+ release(k) {
46021
+ const p = this.pending.get(k);
46022
+ if (!p) return;
46023
+ this.pending.delete(k);
46024
+ disarm(p);
46025
+ this.opts.onRelease({
46026
+ callee: p.callee,
46027
+ roomId: p.roomId,
46028
+ threadRoot: p.threadRoot,
46029
+ targets: [...p.targets.values()],
46030
+ text: p.text
46031
+ });
46032
+ }
46033
+ drop(k) {
46034
+ const p = this.pending.get(k);
46035
+ if (!p) return;
46036
+ disarm(p);
46037
+ this.pending.delete(k);
46038
+ }
46039
+ };
46040
+ var key = (agent, threadRoot) => `${agent}::${threadRoot}`;
46041
+ function fresh(callee, threadRoot, roomId, targets, remote) {
46042
+ return {
46043
+ callee,
46044
+ roomId,
46045
+ threadRoot,
46046
+ targets: new Map(targets.map((t) => [t.name, t])),
46047
+ text: "",
46048
+ delegated: false,
46049
+ waiting: false,
46050
+ interrupted: false,
46051
+ remote
46052
+ };
46053
+ }
46054
+ function disarm(p) {
46055
+ if (p.timer) clearTimeout(p.timer);
46056
+ p.timer = void 0;
46057
+ }
46058
+
45615
46059
  // ../transport-matrix/src/workforce-publisher.ts
45616
46060
  function buildWorkforceRoster(agents) {
45617
46061
  return {
@@ -45655,11 +46099,22 @@ var WorkforceDirectory = class {
45655
46099
  /** Replace one workstation's roster; empty content removes it. */
45656
46100
  apply(stateKey, content) {
45657
46101
  const agents = content?.agents;
45658
- const ids = Array.isArray(agents) ? agents.map((a) => a?.user_id).filter((id) => typeof id === "string") : [];
45659
- if (ids.length > 0) this.rosters.set(stateKey, ids);
46102
+ const entries = Array.isArray(agents) ? agents.filter((a) => typeof a?.user_id === "string").map((a) => ({
46103
+ userId: a.user_id,
46104
+ name: typeof a.name === "string" ? a.name : a.user_id,
46105
+ workstation: stateKey || void 0,
46106
+ rooms: Array.isArray(a.rooms) ? a.rooms.filter((r) => typeof r === "string") : []
46107
+ })) : [];
46108
+ if (entries.length > 0) this.rosters.set(stateKey, entries);
45660
46109
  else this.rosters.delete(stateKey);
45661
46110
  this.agentIds.clear();
45662
- for (const list of this.rosters.values()) for (const id of list) this.agentIds.add(id);
46111
+ for (const list of this.rosters.values()) for (const e of list) this.agentIds.add(e.userId);
46112
+ }
46113
+ entries() {
46114
+ return [...this.rosters.values()].flat();
46115
+ }
46116
+ nameOf(userId) {
46117
+ return this.entries().find((e) => e.userId === userId)?.name;
45663
46118
  }
45664
46119
  };
45665
46120
 
@@ -46246,15 +46701,24 @@ function renderInvocationReturn(c) {
46246
46701
  ...c.output?.text ? ["", c.output.text] : []
46247
46702
  ].join("\n");
46248
46703
  }
46704
+ function renderHandoffReturn(r) {
46705
+ const text = r.text.trim();
46706
+ return text ? `[handoff return] from ${r.callee}
46707
+
46708
+ ${text}` : `[handoff return] from ${r.callee} \u2014 ended its turn without a reply`;
46709
+ }
46249
46710
  function renderDelivery(notify) {
46250
46711
  return notify === "caller" ? "Each result returns to you as a new turn when that task completes. End your turn now \u2014 do not read the task thread to wait for it." : "No result returns to you. The task thread is the result surface; thread_id is for later reference, not something to wait on.";
46251
46712
  }
46713
+ function renderHandoffDelivery(callee) {
46714
+ return `Handed off to ${callee}. End your turn now \u2014 do not wait, poll, or post follow-ups. You will be woken with \`[handoff return] from ${callee}\` when it finishes.`;
46715
+ }
46252
46716
  function renderAssigneeEnvelope(input) {
46253
46717
  return [
46254
46718
  `[task] from ${input.parentAgent} \u2014 you are the assignee of this thread.`,
46255
46719
  "Call zooid_complete_task with a self-contained summary when you are done;",
46256
46720
  "ending your turn without one publishes your last message as the result.",
46257
- "Sibling task threads are refused here \u2014 @mention an agent in this thread to hand off.",
46721
+ "Sibling task threads are refused here \u2014 call zooid_handoff to hand off in this thread.",
46258
46722
  "",
46259
46723
  input.prompt
46260
46724
  ].join("\n");
@@ -46263,6 +46727,8 @@ function renderAssigneeEnvelope(input) {
46263
46727
  // ../transport-matrix/src/transport.ts
46264
46728
  var STARTUP_GRACE_MS = 5e3;
46265
46729
  var RETURN_GRACE_MS = 9e4;
46730
+ var REMOTE_RETURN_GRACE_MS = 30 * 6e4;
46731
+ var ACTIVITY_EVENTS = /* @__PURE__ */ new Set(["dev.zooid.tool_call", "dev.zooid.tool_call_update", "dev.zooid.plan"]);
46266
46732
  async function buildMediaBlocks(items, opts) {
46267
46733
  const blocks = [];
46268
46734
  const pathLines = [];
@@ -46367,6 +46833,7 @@ function createMatrixTransport(opts) {
46367
46833
  const drainQuietMs = opts.drainQuietMs ?? DRAIN_QUIET_MS;
46368
46834
  const drainMaxMs = opts.drainMaxMs ?? DRAIN_MAX_MS;
46369
46835
  const returnGraceMs = opts.returnGraceMs ?? RETURN_GRACE_MS;
46836
+ const remoteReturnGraceMs = opts.remoteReturnGraceMs ?? REMOTE_RETURN_GRACE_MS;
46370
46837
  const mediaClient = opts.media;
46371
46838
  const writeAttachmentFn = opts.writeAttachmentFn ?? writeAttachment;
46372
46839
  const pendingMedia = new PendingMediaStore();
@@ -46387,64 +46854,36 @@ function createMatrixTransport(opts) {
46387
46854
  const pendingInput = opts.pendingInput ?? NO_PENDING_INPUT;
46388
46855
  const bindingFor = (name) => bindings.find((b) => b.name === name);
46389
46856
  const turnQueues = /* @__PURE__ */ new Map();
46390
- const pendingReturns = /* @__PURE__ */ new Map();
46391
- const returnKey = (agentName, threadRoot) => `${agentName}::${threadRoot}`;
46392
- function stashReturn(sender, threadRoot, roomId, evt, targets) {
46393
- const key = returnKey(sender.name, threadRoot);
46394
- let pending = pendingReturns.get(key);
46395
- if (!pending) {
46396
- pending = { roomId, threadRoot, event: evt, texts: [], targets: /* @__PURE__ */ new Map() };
46397
- pendingReturns.set(key, pending);
46398
- }
46399
- pending.event = evt;
46400
- const body = evt.content?.body?.trim();
46401
- if (body) pending.texts.push(body);
46402
- for (const t of targets) pending.targets.set(t.name, t);
46403
- if (pending.timer) clearTimeout(pending.timer);
46404
- pending.timer = setTimeout(() => releaseReturn(key), returnGraceMs);
46405
- pending.timer.unref?.();
46406
- console.log(
46407
- `[matrix] holding return ${sender.name} \u2192 ${[...pending.targets.keys()].join(",")} until turn end (thread=${threadRoot})`
46408
- );
46857
+ const workforce = new WorkforceDirectory();
46858
+ const returns = new PendingReturns({ graceMs: returnGraceMs, remoteGraceMs: remoteReturnGraceMs, onRelease: deliverReturn });
46859
+ const isLocal = (userId) => bindings.some((b) => b.userId === userId);
46860
+ const agentName = (userId) => bindings.find((b) => b.userId === userId)?.name ?? workforce.nameOf(userId) ?? userId;
46861
+ const openHandoffs = /* @__PURE__ */ new Map();
46862
+ const openKey = (caller, threadRoot) => `${caller}::${threadRoot}`;
46863
+ function handoffCandidates() {
46864
+ const byId = /* @__PURE__ */ new Map();
46865
+ for (const e of workforce.entries()) byId.set(e.userId, e);
46866
+ for (const b of bindings)
46867
+ byId.set(b.userId, {
46868
+ userId: b.userId,
46869
+ name: b.name,
46870
+ workstation: byId.get(b.userId)?.workstation,
46871
+ rooms: b.rooms.map((r) => r.alias)
46872
+ });
46873
+ return [...byId.values()];
46409
46874
  }
46410
- function releaseReturn(key) {
46411
- const pending = pendingReturns.get(key);
46412
- if (!pending) return;
46413
- pendingReturns.delete(key);
46414
- if (pending.timer) clearTimeout(pending.timer);
46415
- const promptText = pending.texts.join("\n\n");
46416
- for (const target of pending.targets.values()) {
46417
- console.log(`[matrix] \u2192 ${target.name} (${target.userId}) [return]`);
46875
+ function deliverReturn(r) {
46876
+ for (const target of r.targets) {
46877
+ openHandoffs.delete(openKey(target.userId, r.threadRoot));
46878
+ console.log(`[matrix] \u2192 ${target.name} (${target.userId}) [return from ${agentName(r.callee)}]`);
46418
46879
  void enqueueTurn(target, {
46419
- roomId: pending.roomId,
46420
- threadRoot: pending.threadRoot,
46421
- sessionKey: sessionKeyFor(
46422
- target.name,
46423
- pending.threadRoot,
46424
- threadStates.get(pending.threadRoot)
46425
- ),
46426
- event: pending.event,
46427
- ...promptText ? { promptText } : {}
46880
+ roomId: r.roomId,
46881
+ threadRoot: r.threadRoot,
46882
+ sessionKey: sessionKeyFor(target.userId, r.threadRoot, threadStates.get(r.threadRoot)),
46883
+ promptText: renderHandoffReturn({ callee: agentName(r.callee), text: r.text })
46428
46884
  });
46429
46885
  }
46430
46886
  }
46431
- function dropPendingReturn(threadRoot, agentName) {
46432
- for (const [key, pending] of pendingReturns) {
46433
- if (pending.threadRoot !== threadRoot) continue;
46434
- if (!pending.targets.delete(agentName)) continue;
46435
- if (pending.targets.size === 0) {
46436
- if (pending.timer) clearTimeout(pending.timer);
46437
- pendingReturns.delete(key);
46438
- }
46439
- }
46440
- }
46441
- function dropThreadReturns(threadRoot) {
46442
- for (const [key, pending] of pendingReturns) {
46443
- if (pending.threadRoot !== threadRoot) continue;
46444
- if (pending.timer) clearTimeout(pending.timer);
46445
- pendingReturns.delete(key);
46446
- }
46447
- }
46448
46887
  const cutoffTs = mode === "client" ? Number.NEGATIVE_INFINITY : Date.now() - STARTUP_GRACE_MS;
46449
46888
  const seenEventIds = /* @__PURE__ */ new Set();
46450
46889
  const flushedCounts = /* @__PURE__ */ new Map();
@@ -46478,21 +46917,14 @@ function createMatrixTransport(opts) {
46478
46917
  lastFlushed.set(sessionId, text);
46479
46918
  flushedCounts.set(sessionId, (flushedCounts.get(sessionId) ?? 0) + 1);
46480
46919
  const content = buildTextContent(text);
46481
- const pendingInvocations = registerOutgoingHandoffs(sessionId, text);
46482
46920
  const tail = (sendQueue.get(sessionId) ?? Promise.resolve()).then(async () => {
46483
46921
  try {
46484
- const { event_id } = await client.sendMessage({
46922
+ await client.sendMessage({
46485
46923
  roomId: ctx.roomId,
46486
46924
  asUserId: ctx.agent.userId,
46487
46925
  content,
46488
46926
  threadRoot: ctx.threadRoot
46489
46927
  });
46490
- for (const invocation of pendingInvocations)
46491
- invocations.attachCallEvent(
46492
- invocation.invocationId,
46493
- event_id,
46494
- composeHandoffKey(ctx.threadRoot, event_id)
46495
- );
46496
46928
  } catch (err) {
46497
46929
  console.warn(`[matrix:${ctx.agent.name}] sendMessage flush failed:`, err);
46498
46930
  }
@@ -46500,30 +46932,6 @@ function createMatrixTransport(opts) {
46500
46932
  sendQueue.set(sessionId, tail);
46501
46933
  return true;
46502
46934
  };
46503
- function registerOutgoingHandoffs(sessionId, text) {
46504
- const ctx = sessions.get(sessionId);
46505
- if (!ctx) return [];
46506
- const task = taskRegistry.taskForRoot(ctx.threadRoot);
46507
- if (!task || task.phase !== "open") return [];
46508
- const sessionKey = sessionKeyFor(ctx.agent.name, ctx.threadRoot, threadStates.get(ctx.threadRoot));
46509
- const opened = [];
46510
- for (const userId of extractMentions({ content: { body: text } })) {
46511
- const callee = bindings.find((binding) => binding.userId === userId);
46512
- if (!callee || callee.name === ctx.agent.name) continue;
46513
- if (invocations.isOutstandingAncestor(sessionKey, callee.name)) {
46514
- void client.sendCustomEvent({
46515
- roomId: ctx.roomId,
46516
- asUserId: ctx.agent.userId,
46517
- eventType: "dev.zooid.error",
46518
- content: { body: `\u26A0 [handoff_circular] Cannot hand off to ${callee.name}: it is waiting on ${ctx.agent.name}`, code: "handoff_circular", message: `Cannot hand off to ${callee.name}: it is waiting on ${ctx.agent.name}`, transient: false, "m.relates_to": { rel_type: "m.thread", event_id: ctx.threadRoot } }
46519
- });
46520
- continue;
46521
- }
46522
- opened.push(invocations.open({ taskId: task.taskId, callerAgent: ctx.agent.name, callerSessionKey: sessionKey, calleeAgent: callee.name }));
46523
- taskRegistry.clearSummary(task.taskId);
46524
- }
46525
- return opened;
46526
- }
46527
46935
  agents.onEvent = async (name, event) => {
46528
46936
  const ctx = sessions.get(event.sessionId);
46529
46937
  if (!ctx) {
@@ -46651,8 +47059,8 @@ function createMatrixTransport(opts) {
46651
47059
  }).catch((e) => console.warn(`[matrix:${agent.name}] dev.zooid.error send failed:`, e));
46652
47060
  }
46653
47061
  function enqueueTurn(agent, input) {
46654
- const key = `${agent.name}::${input.sessionKey}`;
46655
- const chained = (turnQueues.get(key) ?? Promise.resolve()).then(() => runTurn(agent, input)).then(() => {
47062
+ const key2 = `${agent.name}::${input.sessionKey}`;
47063
+ const chained = (turnQueues.get(key2) ?? Promise.resolve()).then(() => runTurn(agent, input)).then(() => {
46656
47064
  let st = threadStates.get(input.threadRoot);
46657
47065
  if (!st) {
46658
47066
  st = {
@@ -46665,13 +47073,12 @@ function createMatrixTransport(opts) {
46665
47073
  }
46666
47074
  if (st.participants.at(-1) !== agent.name) st.participants.push(agent.name);
46667
47075
  }).catch((err) => reportTurnFailure(agent, input, err));
46668
- turnQueues.set(key, chained);
47076
+ turnQueues.set(key2, chained);
46669
47077
  void chained.finally(() => {
46670
- if (turnQueues.get(key) === chained) turnQueues.delete(key);
47078
+ if (turnQueues.get(key2) === chained) turnQueues.delete(key2);
46671
47079
  });
46672
47080
  return chained;
46673
47081
  }
46674
- const workforce = new WorkforceDirectory();
46675
47082
  let workforceSpaceId;
46676
47083
  async function handleInboundEvent(evt) {
46677
47084
  if (evt.event_id) {
@@ -46716,27 +47123,43 @@ function createMatrixTransport(opts) {
46716
47123
  return;
46717
47124
  }
46718
47125
  console.log(`[matrix] inbound dev.zooid.session_reset in ${evt.room_id} thread=${threadRoot}`);
46719
- dropThreadReturns(threadRoot);
47126
+ returns.dropThread(threadRoot);
47127
+ for (const k of [...openHandoffs.keys()]) if (k.endsWith(`::${threadRoot}`)) openHandoffs.delete(k);
46720
47128
  if (!threadStates.has(threadRoot) && evt.room_id) {
46721
47129
  try {
46722
47130
  threadStates.set(
46723
47131
  threadRoot,
46724
- await rebuildThreadState(client, evt.room_id, threadRoot, bindings)
47132
+ await rebuildThreadState(client, evt.room_id, threadRoot, bindings, workforce.agentIds)
46725
47133
  );
46726
47134
  } catch (err) {
46727
47135
  console.warn(`[matrix] failed to rebuild threadState for reset ${threadRoot}:`, err);
46728
47136
  }
46729
47137
  }
46730
47138
  const st = threadStates.get(threadRoot);
47139
+ const cleanup = [];
46731
47140
  for (const a of bindings) {
46732
- agents.endSession(a.name, threadRoot);
47141
+ cleanup.push({
47142
+ name: a.name,
47143
+ key: threadRoot,
47144
+ result: Promise.resolve().then(() => agents.endSession(a.name, threadRoot))
47145
+ });
46733
47146
  taskRegistry.bumpGeneration(a.name, threadRoot);
46734
- for (const arc of st?.handoffs[a.name] ?? []) {
46735
- const key = composeHandoffKey(threadRoot, arc);
46736
- agents.endSession(a.name, key);
46737
- taskRegistry.bumpGeneration(a.name, key);
47147
+ for (const arc of st?.handoffs[a.userId] ?? []) {
47148
+ const key2 = composeHandoffKey(threadRoot, arc);
47149
+ cleanup.push({
47150
+ name: a.name,
47151
+ key: key2,
47152
+ result: Promise.resolve().then(() => agents.endSession(a.name, key2))
47153
+ });
47154
+ taskRegistry.bumpGeneration(a.name, key2);
46738
47155
  }
46739
47156
  }
47157
+ const results = await Promise.allSettled(cleanup.map((item) => item.result));
47158
+ results.forEach((result, index) => {
47159
+ if (result.status === "rejected") {
47160
+ console.warn(`[matrix] session reset cleanup failed for ${cleanup[index].name}/${cleanup[index].key}:`, result.reason);
47161
+ }
47162
+ });
46740
47163
  return;
46741
47164
  }
46742
47165
  if (evt.type === "dev.zooid.interrupt") {
@@ -46744,6 +47167,7 @@ function createMatrixTransport(opts) {
46744
47167
  const relates = evt.content?.["m.relates_to"];
46745
47168
  const threadRoot = relates?.rel_type === "m.thread" && relates.event_id ? relates.event_id : void 0;
46746
47169
  if (threadRoot) {
47170
+ returns.interrupt(threadRoot);
46747
47171
  const targets = [];
46748
47172
  for (const [sessionId, ctx2] of sessions) {
46749
47173
  if (ctx2.threadRoot === threadRoot) {
@@ -46780,6 +47204,7 @@ function createMatrixTransport(opts) {
46780
47204
  console.log(
46781
47205
  `[matrix] interrupt session=${content.session_id} agent=${ctx.agent.name}` + (content.reason ? ` reason=${content.reason}` : "")
46782
47206
  );
47207
+ returns.interrupt(ctx.threadRoot);
46783
47208
  await agents.cancelSession(ctx.agent.name, content.session_id).catch((err) => {
46784
47209
  console.error(
46785
47210
  `[matrix] cancelSession(${ctx.agent.name}, ${content.session_id}) failed:`,
@@ -46798,12 +47223,13 @@ function createMatrixTransport(opts) {
46798
47223
  }
46799
47224
  logInbound(evt);
46800
47225
  if (evt.type === "dev.zooid.turn.end") {
46801
- const agentId = evt.content?.agent_id;
46802
47226
  const endedRoot = inboundThreadRoot2(evt);
46803
- const senderAgent = bindings.find((binding) => binding.userId === evt.sender);
46804
- if (agentId && endedRoot && senderAgent?.name === agentId) {
46805
- releaseReturn(returnKey(agentId, endedRoot));
46806
- }
47227
+ if (endedRoot && evt.sender) returns.turnEnded(evt.sender, endedRoot);
47228
+ return;
47229
+ }
47230
+ if (ACTIVITY_EVENTS.has(evt.type ?? "")) {
47231
+ const root = inboundThreadRoot2(evt);
47232
+ if (evt.sender && root) returns.activity(evt.sender, root);
46807
47233
  return;
46808
47234
  }
46809
47235
  if (evt.type === "m.room.message" && isMediaMsgtype(evt.content?.msgtype) && evt.room_id && evt.event_id && evt.sender && evt.content?.url && !bindings.some((b) => b.userId === evt.sender)) {
@@ -46854,17 +47280,21 @@ function createMatrixTransport(opts) {
46854
47280
  const invocation = invocations.byCallEvent(evt.event_id);
46855
47281
  matches2 = invocation ? matches2.filter((match) => match.name === invocation.calleeAgent) : [];
46856
47282
  }
46857
- if (evt.type === "m.room.message" && promotedRoot && evt.room_id) {
46858
- const senderBinding = bindings.find((b) => b.userId === evt.sender);
46859
- if (senderBinding) {
47283
+ if (evt.type === "m.room.message" && promotedRoot && evt.room_id && evt.sender) {
47284
+ const senderIsAgentId = isLocal(evt.sender) || workforce.agentIds.has(evt.sender);
47285
+ if (senderIsAgentId) {
46860
47286
  const st = threadStates.get(promotedRoot);
46861
- const held = matches2.filter((m) => isReturnRoute(evt, m, bindings, st));
47287
+ const held = matches2.filter((m) => isReturnRoute(evt, m, st));
46862
47288
  if (held.length > 0) {
46863
47289
  matches2 = matches2.filter((m) => !held.includes(m));
46864
- stashReturn(senderBinding, promotedRoot, evt.room_id, evt, held);
47290
+ returns.hold(evt.sender, promotedRoot, evt.room_id, held, evt.content?.body, {
47291
+ remote: !isLocal(evt.sender)
47292
+ });
47293
+ console.log(
47294
+ `[matrix] holding return ${agentName(evt.sender)} \u2192 ${held.map((m) => m.name).join(",")} until turn end (thread=${promotedRoot})`
47295
+ );
46865
47296
  }
46866
47297
  }
46867
- for (const m of matches2) dropPendingReturn(promotedRoot, m.name);
46868
47298
  }
46869
47299
  const senderIsBot = bindings.some((b) => b.userId === evt.sender);
46870
47300
  if (evt.type === "m.room.message" && matches2.length === 0 && !senderIsBot) {
@@ -46872,7 +47302,9 @@ function createMatrixTransport(opts) {
46872
47302
  `[matrix] no agent matched message in ${evt.room_id} from ${evt.sender} (bindings: ${bindings.map((b) => `${b.name}@${b.userId}[${b.trigger}]`).join(", ")})`
46873
47303
  );
46874
47304
  }
46875
- if (matches2.length > 0 && promotedRoot) {
47305
+ const handoff = readHandoff(evt.content);
47306
+ const callEdge = handoff && evt.type === "m.room.message" && handoff.caller === evt.sender && promotedRoot ? handoff : void 0;
47307
+ if (promotedRoot && (matches2.length > 0 || callEdge)) {
46876
47308
  let st = threadStates.get(promotedRoot);
46877
47309
  if (!st) {
46878
47310
  st = { participants: [], rootMentions: [], callers: {}, handoffs: {} };
@@ -46881,17 +47313,26 @@ function createMatrixTransport(opts) {
46881
47313
  if (taskCtx?.isRoot) {
46882
47314
  if (!st.rootMentions.includes(taskRec.assignee)) st.rootMentions.push(taskRec.assignee);
46883
47315
  } else {
46884
- const msgMentions = new Set(extractMentions(evt));
46885
- const senderAgent = bindings.find((b) => b.userId === evt.sender);
46886
- for (const a of bindings) {
46887
- if (!msgMentions.has(a.userId)) continue;
46888
- if (!st.rootMentions.includes(a.name)) st.rootMentions.push(a.name);
46889
- if (senderAgent && a.name !== senderAgent.name && !wouldCycleCallers(st.callers, a.name, senderAgent.name)) {
46890
- st.callers[a.name] = senderAgent.name;
46891
- if (evt.event_id) {
46892
- const arcs = st.handoffs[a.name] ??= [];
46893
- if (!arcs.includes(evt.event_id)) arcs.push(evt.event_id);
46894
- }
47316
+ const senderIsAgentId = !!evt.sender && (isLocal(evt.sender) || workforce.agentIds.has(evt.sender));
47317
+ if (!senderIsAgentId) {
47318
+ const msgMentions = new Set(extractMentions(evt));
47319
+ for (const a of bindings)
47320
+ if (msgMentions.has(a.userId) && !st.rootMentions.includes(a.name))
47321
+ st.rootMentions.push(a.name);
47322
+ }
47323
+ if (callEdge && callEdge.callee !== callEdge.caller && !wouldCycleCallers(st.callers, callEdge.callee, callEdge.caller)) {
47324
+ st.callers[callEdge.callee] = callEdge.caller;
47325
+ if (evt.event_id) {
47326
+ const arcs = st.handoffs[callEdge.callee] ??= [];
47327
+ if (!arcs.includes(evt.event_id)) arcs.push(evt.event_id);
47328
+ }
47329
+ if (!taskCtx && evt.room_id) {
47330
+ const callerBinding = bindings.find((b) => b.userId === callEdge.caller);
47331
+ if (callerBinding?.trigger === "mention")
47332
+ returns.open(callEdge.callee, promotedRoot, evt.room_id, callerBinding, {
47333
+ remote: !isLocal(callEdge.callee)
47334
+ });
47335
+ returns.markDelegated(callEdge.caller, promotedRoot);
46895
47336
  }
46896
47337
  }
46897
47338
  }
@@ -46899,7 +47340,7 @@ function createMatrixTransport(opts) {
46899
47340
  for (const a of matches2) {
46900
47341
  console.log(`[matrix] \u2192 ${a.name} (${a.userId})`);
46901
47342
  if (!promotedRoot || !evt.room_id) continue;
46902
- const sessionKey = sessionKeyFor(a.name, promotedRoot, threadStates.get(promotedRoot));
47343
+ const sessionKey = sessionKeyFor(a.userId, promotedRoot, threadStates.get(promotedRoot));
46903
47344
  const taskEnvelope = taskCtx?.isRoot && a.name === taskRec.assignee ? { parentAgent: taskRec.parent.agent } : void 0;
46904
47345
  void enqueueTurn(a, {
46905
47346
  roomId: evt.room_id,
@@ -46947,10 +47388,10 @@ function createMatrixTransport(opts) {
46947
47388
  return c.json({});
46948
47389
  });
46949
47390
  app.get("/healthz", (c) => c.text("ok"));
46950
- async function runTurn(agent, input) {
47391
+ async function runTurnBody(agent, input) {
46951
47392
  const { roomId, threadRoot, sessionKey } = input;
46952
47393
  const sessionId = await agents.ensureSession(agent.name, sessionKey, roomId, threadRoot);
46953
- sessions.set(sessionId, { agent, roomId, threadRoot });
47394
+ sessions.set(sessionId, { agent, roomId, threadRoot, sessionKey });
46954
47395
  buffers.set(sessionId, "");
46955
47396
  bufferMessageIds.delete(sessionId);
46956
47397
  flushedCounts.set(sessionId, 0);
@@ -47074,10 +47515,19 @@ function createMatrixTransport(opts) {
47074
47515
  sendQueue.delete(sessionId);
47075
47516
  }
47076
47517
  }
47518
+ async function runTurn(agent, input) {
47519
+ returns.turnStarted(agent.userId, input.threadRoot);
47520
+ try {
47521
+ await runTurnBody(agent, input);
47522
+ } finally {
47523
+ returns.turnFinished(agent.userId, input.threadRoot);
47524
+ }
47525
+ }
47077
47526
  async function finishTask(task, ctx) {
47078
47527
  const threadId = task.threadRoot;
47079
47528
  const completion = ctx.completion;
47080
47529
  if (!taskRegistry.close(task.taskId)) return;
47530
+ for (const k of [...openHandoffs.keys()]) if (k.endsWith(`::${threadId}`)) openHandoffs.delete(k);
47081
47531
  const cancelled = invocations.cancelForTask(task.taskId);
47082
47532
  pendingInput.cancelFor([threadId, ...cancelled.map((i) => i.calleeSessionKey).filter((x) => Boolean(x))]);
47083
47533
  await client.sendCustomEvent({
@@ -47149,7 +47599,7 @@ function createMatrixTransport(opts) {
47149
47599
  results[index] = {
47150
47600
  agent: spec.agent,
47151
47601
  status: "refused",
47152
- reason: "depth_limit: this thread is itself a delegated task. Do the work here, or @mention another agent in this thread to hand off."
47602
+ reason: "depth_limit: this thread is itself a delegated task. Do the work here, or call zooid_handoff to hand off in this thread."
47153
47603
  };
47154
47604
  continue;
47155
47605
  }
@@ -47266,7 +47716,86 @@ function createMatrixTransport(opts) {
47266
47716
  const openTask = taskRegistry.openTaskFor(caller.agentName, caller.threadRoot);
47267
47717
  return {
47268
47718
  is_task_assignee: openTask !== void 0 && openTask.threadRoot === caller.sessionKey,
47269
- can_start_task_threads: enclosing === void 0
47719
+ can_start_task_threads: enclosing === void 0,
47720
+ can_handoff: bindingFor(caller.agentName) !== void 0
47721
+ };
47722
+ },
47723
+ async handoff(caller, input) {
47724
+ const callerBinding = bindingFor(caller.agentName);
47725
+ if (!callerBinding) return { status: "refused", reason: "unknown_caller" };
47726
+ const prompt = input.prompt.trim();
47727
+ if (!prompt) return { status: "refused", reason: "prompt must be non-empty" };
47728
+ const resolved = resolveHandoffTarget(input.agent, caller.channelId, handoffCandidates());
47729
+ if (!resolved.ok) return { status: "refused", reason: resolved.reason };
47730
+ const target = resolved.target;
47731
+ if (target.userId === callerBinding.userId)
47732
+ return { status: "refused", reason: "self: you cannot hand off to yourself" };
47733
+ const st = threadStates.get(caller.threadRoot);
47734
+ if (st && wouldCycleCallers(st.callers, target.userId, callerBinding.userId))
47735
+ return {
47736
+ status: "refused",
47737
+ reason: `already_waiting_on_you: ${target.name} is waiting on your result. End your turn \u2014 your result returns to ${target.name} automatically.`
47738
+ };
47739
+ const task = taskRegistry.taskForRoot(caller.threadRoot);
47740
+ const inTask = task?.phase === "open";
47741
+ if (inTask && !isLocal(target.userId))
47742
+ return {
47743
+ status: "refused",
47744
+ reason: "remote_in_task: a task thread hands off only to agents on this workstation"
47745
+ };
47746
+ const key2 = openKey(callerBinding.userId, caller.threadRoot);
47747
+ const busy = inTask ? invocations.outstandingFor(caller.sessionKey).length > 0 : openHandoffs.has(key2);
47748
+ if (busy)
47749
+ return {
47750
+ status: "refused",
47751
+ reason: "already_open: you already have a handoff open in this thread. End your turn and wait for it, or use zooid_start_task_threads for parallel work."
47752
+ };
47753
+ const invocation = inTask ? invocations.open({
47754
+ taskId: task.taskId,
47755
+ callerAgent: callerBinding.name,
47756
+ callerSessionKey: caller.sessionKey,
47757
+ calleeAgent: target.name
47758
+ }) : void 0;
47759
+ if (invocation) taskRegistry.clearSummary(task.taskId);
47760
+ else openHandoffs.set(key2, target.userId);
47761
+ const callId = randomUUID5();
47762
+ const content = buildHandoffContent({
47763
+ callId,
47764
+ caller: callerBinding.userId,
47765
+ callee: target.userId,
47766
+ prompt
47767
+ });
47768
+ const liveSession = [...sessions].find(
47769
+ ([, c]) => c.agent.name === callerBinding.name && c.sessionKey === caller.sessionKey
47770
+ )?.[0];
47771
+ if (liveSession) flushBuffer(liveSession);
47772
+ let eventId;
47773
+ const send = async () => {
47774
+ const { event_id } = await client.sendMessage({
47775
+ roomId: caller.channelId,
47776
+ asUserId: callerBinding.userId,
47777
+ content,
47778
+ threadRoot: caller.threadRoot
47779
+ });
47780
+ eventId = event_id;
47781
+ };
47782
+ const tail = (liveSession ? sendQueue.get(liveSession) ?? Promise.resolve() : Promise.resolve()).then(send);
47783
+ if (liveSession) sendQueue.set(liveSession, tail.catch(() => {
47784
+ }));
47785
+ try {
47786
+ await tail;
47787
+ } catch (err) {
47788
+ openHandoffs.delete(key2);
47789
+ if (invocation) invocations.resolve(invocation.invocationId);
47790
+ return { status: "refused", reason: `post_failed: ${String(err.message)}` };
47791
+ }
47792
+ if (invocation && eventId)
47793
+ invocations.attachCallEvent(invocation.invocationId, eventId, composeHandoffKey(caller.threadRoot, eventId));
47794
+ return {
47795
+ status: "started",
47796
+ call_id: callId,
47797
+ callee: target.userId,
47798
+ delivery: renderHandoffDelivery(target.name)
47270
47799
  };
47271
47800
  }
47272
47801
  };
@@ -47349,43 +47878,35 @@ async function rebuildThreadState(client, roomId, rootEventId, bindings, knownAg
47349
47878
  };
47350
47879
  const asUser = (bindings.find((b) => b.rooms.some((r) => r.alias === roomId)) ?? bindings[0])?.userId;
47351
47880
  if (!asUser) return state;
47352
- const root = await client.fetchEvent(roomId, rootEventId, asUser);
47353
- if (root) {
47354
- const rootMentions = new Set(extractMentions(root));
47355
- const rootSender = root.sender;
47356
- const rootSenderAgent = rootSender ? bindings.find((b) => b.userId === rootSender) : void 0;
47357
- for (const a of bindings) {
47358
- if (!rootMentions.has(a.userId)) continue;
47359
- if (!state.rootMentions.includes(a.name)) state.rootMentions.push(a.name);
47360
- if (rootSenderAgent && a.name !== rootSenderAgent.name && !wouldCycleCallers(state.callers, a.name, rootSenderAgent.name)) {
47361
- state.callers[a.name] = rootSenderAgent.name;
47362
- const arcs = state.handoffs[a.name] ??= [];
47363
- if (!arcs.includes(rootEventId)) arcs.push(rootEventId);
47364
- }
47365
- }
47366
- }
47367
47881
  const { chunk: thread } = await client.fetchThreadRelations({
47368
47882
  roomId,
47369
47883
  rootEventId,
47370
47884
  asUserId: asUser
47371
47885
  });
47372
- for (const ev of thread) {
47373
- const mentions = new Set(extractMentions(ev));
47886
+ const root = await client.fetchEvent(roomId, rootEventId, asUser);
47887
+ const events = [...root ? [root] : [], ...thread];
47888
+ for (const ev of events) {
47374
47889
  const evSender = ev.sender;
47375
- const evSenderAgent = evSender ? bindings.find((b) => b.userId === evSender) : void 0;
47376
47890
  const evId = ev.event_id;
47377
- for (const a of bindings) {
47378
- if (!mentions.has(a.userId)) continue;
47379
- if (!state.rootMentions.includes(a.name)) state.rootMentions.push(a.name);
47380
- if (evSenderAgent && a.name !== evSenderAgent.name && !wouldCycleCallers(state.callers, a.name, evSenderAgent.name)) {
47381
- state.callers[a.name] = evSenderAgent.name;
47382
- if (evId) {
47383
- const arcs = state.handoffs[a.name] ??= [];
47384
- if (!arcs.includes(evId)) arcs.push(evId);
47385
- }
47891
+ const content = ev.content;
47892
+ const senderIsAgentId = !!evSender && (bindings.some((b) => b.userId === evSender) || knownAgentIds?.has(evSender) === true);
47893
+ if (!senderIsAgentId) {
47894
+ const mentions = new Set(extractMentions(ev));
47895
+ for (const a of bindings)
47896
+ if (mentions.has(a.userId) && !state.rootMentions.includes(a.name)) state.rootMentions.push(a.name);
47897
+ }
47898
+ const h = readHandoff(content);
47899
+ if (h && h.caller === evSender && h.callee !== h.caller && !wouldCycleCallers(state.callers, h.callee, h.caller)) {
47900
+ state.callers[h.callee] = h.caller;
47901
+ if (evId) {
47902
+ const arcs = state.handoffs[h.callee] ??= [];
47903
+ if (!arcs.includes(evId)) arcs.push(evId);
47386
47904
  }
47387
47905
  }
47906
+ }
47907
+ for (const ev of thread) {
47388
47908
  const type = ev.type;
47909
+ const evSender = ev.sender;
47389
47910
  if (type === "m.room.message" && evSender) {
47390
47911
  const a = bindings.find((b) => b.userId === evSender);
47391
47912
  const msgtype = ev.content?.msgtype;
@@ -47420,14 +47941,14 @@ function truncate(s, n) {
47420
47941
  }
47421
47942
 
47422
47943
  // ../context-mcp/src/spawn-registry.ts
47423
- import { randomUUID as randomUUID5 } from "crypto";
47944
+ import { randomUUID as randomUUID6 } from "crypto";
47424
47945
  var SpawnRegistry = class {
47425
47946
  bindings = /* @__PURE__ */ new Map();
47426
47947
  spawnByAgentSession = /* @__PURE__ */ new Map();
47427
47948
  spawnByAcpSession = /* @__PURE__ */ new Map();
47428
47949
  tasks;
47429
47950
  register(input) {
47430
- const spawnId = randomUUID5();
47951
+ const spawnId = randomUUID6();
47431
47952
  this.bindings.set(spawnId, { spawnId, ...input });
47432
47953
  this.spawnByAgentSession.set(this.key(input.agentName, input.sessionKey ?? input.threadRef.threadId), spawnId);
47433
47954
  return spawnId;
@@ -47437,11 +47958,11 @@ var SpawnRegistry = class {
47437
47958
  }
47438
47959
  release(spawnId) {
47439
47960
  this.bindings.delete(spawnId);
47440
- for (const [key, value] of this.spawnByAgentSession) {
47441
- if (value === spawnId) this.spawnByAgentSession.delete(key);
47961
+ for (const [key2, value] of this.spawnByAgentSession) {
47962
+ if (value === spawnId) this.spawnByAgentSession.delete(key2);
47442
47963
  }
47443
- for (const [key, value] of this.spawnByAcpSession) {
47444
- if (value === spawnId) this.spawnByAcpSession.delete(key);
47964
+ for (const [key2, value] of this.spawnByAcpSession) {
47965
+ if (value === spawnId) this.spawnByAcpSession.delete(key2);
47445
47966
  }
47446
47967
  }
47447
47968
  linkSession(agentName, sessionKey, acpSessionId) {
@@ -47582,7 +48103,7 @@ async function handleLine(line, socket, registry3, callerAgent) {
47582
48103
  result = await binding.provider.sendMessage(
47583
48104
  req.params
47584
48105
  );
47585
- } else if (req.method === "startTasks" || req.method === "completeTask" || req.method === "describeRole") {
48106
+ } else if (req.method === "startTasks" || req.method === "completeTask" || req.method === "describeRole" || req.method === "handoff") {
47586
48107
  const actions = registry3.taskActions;
47587
48108
  if (!actions) {
47588
48109
  socket.write(
@@ -47599,7 +48120,7 @@ async function handleLine(line, socket, registry3, callerAgent) {
47599
48120
  threadRoot: binding.threadRef.threadId,
47600
48121
  sessionKey: binding.sessionKey ?? binding.threadRef.threadId
47601
48122
  };
47602
- result = req.method === "startTasks" ? await actions.startTasks(caller, req.params) : req.method === "completeTask" ? await actions.completeTask(caller, req.params) : await actions.describeRole(caller);
48123
+ result = req.method === "startTasks" ? await actions.startTasks(caller, req.params) : req.method === "completeTask" ? await actions.completeTask(caller, req.params) : req.method === "describeRole" ? await actions.describeRole(caller) : await actions.handoff(caller, req.params);
47603
48124
  } else {
47604
48125
  socket.write(
47605
48126
  JSON.stringify({
@@ -47815,19 +48336,19 @@ function floatSafeRemainder2(val, step) {
47815
48336
  const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
47816
48337
  return valInt % stepInt / 10 ** decCount;
47817
48338
  }
47818
- function defineLazy2(object3, key, getter) {
48339
+ function defineLazy2(object3, key2, getter) {
47819
48340
  const set2 = false;
47820
- Object.defineProperty(object3, key, {
48341
+ Object.defineProperty(object3, key2, {
47821
48342
  get() {
47822
48343
  if (!set2) {
47823
48344
  const value = getter();
47824
- object3[key] = value;
48345
+ object3[key2] = value;
47825
48346
  return value;
47826
48347
  }
47827
48348
  throw new Error("cached value already set");
47828
48349
  },
47829
48350
  set(v) {
47830
- Object.defineProperty(object3, key, {
48351
+ Object.defineProperty(object3, key2, {
47831
48352
  value: v
47832
48353
  // configurable: true,
47833
48354
  });
@@ -47846,11 +48367,11 @@ function assignProp2(target, prop, value) {
47846
48367
  function getElementAtPath2(obj, path) {
47847
48368
  if (!path)
47848
48369
  return obj;
47849
- return path.reduce((acc, key) => acc?.[key], obj);
48370
+ return path.reduce((acc, key2) => acc?.[key2], obj);
47850
48371
  }
47851
48372
  function promiseAllObject2(promisesObj) {
47852
48373
  const keys = Object.keys(promisesObj);
47853
- const promises = keys.map((key) => promisesObj[key]);
48374
+ const promises = keys.map((key2) => promisesObj[key2]);
47854
48375
  return Promise.all(promises).then((results) => {
47855
48376
  const resolvedObj = {};
47856
48377
  for (let i = 0; i < keys.length; i++) {
@@ -47903,8 +48424,8 @@ function isPlainObject2(o) {
47903
48424
  }
47904
48425
  function numKeys2(data) {
47905
48426
  let keyCount = 0;
47906
- for (const key in data) {
47907
- if (Object.prototype.hasOwnProperty.call(data, key)) {
48427
+ for (const key2 in data) {
48428
+ if (Object.prototype.hasOwnProperty.call(data, key2)) {
47908
48429
  keyCount++;
47909
48430
  }
47910
48431
  }
@@ -48040,13 +48561,13 @@ var BIGINT_FORMAT_RANGES2 = {
48040
48561
  function pick2(schema, mask) {
48041
48562
  const newShape = {};
48042
48563
  const currDef = schema._zod.def;
48043
- for (const key in mask) {
48044
- if (!(key in currDef.shape)) {
48045
- throw new Error(`Unrecognized key: "${key}"`);
48564
+ for (const key2 in mask) {
48565
+ if (!(key2 in currDef.shape)) {
48566
+ throw new Error(`Unrecognized key: "${key2}"`);
48046
48567
  }
48047
- if (!mask[key])
48568
+ if (!mask[key2])
48048
48569
  continue;
48049
- newShape[key] = currDef.shape[key];
48570
+ newShape[key2] = currDef.shape[key2];
48050
48571
  }
48051
48572
  return clone2(schema, {
48052
48573
  ...schema._zod.def,
@@ -48057,13 +48578,13 @@ function pick2(schema, mask) {
48057
48578
  function omit2(schema, mask) {
48058
48579
  const newShape = { ...schema._zod.def.shape };
48059
48580
  const currDef = schema._zod.def;
48060
- for (const key in mask) {
48061
- if (!(key in currDef.shape)) {
48062
- throw new Error(`Unrecognized key: "${key}"`);
48581
+ for (const key2 in mask) {
48582
+ if (!(key2 in currDef.shape)) {
48583
+ throw new Error(`Unrecognized key: "${key2}"`);
48063
48584
  }
48064
- if (!mask[key])
48585
+ if (!mask[key2])
48065
48586
  continue;
48066
- delete newShape[key];
48587
+ delete newShape[key2];
48067
48588
  }
48068
48589
  return clone2(schema, {
48069
48590
  ...schema._zod.def,
@@ -48104,23 +48625,23 @@ function partial2(Class3, schema, mask) {
48104
48625
  const oldShape = schema._zod.def.shape;
48105
48626
  const shape = { ...oldShape };
48106
48627
  if (mask) {
48107
- for (const key in mask) {
48108
- if (!(key in oldShape)) {
48109
- throw new Error(`Unrecognized key: "${key}"`);
48628
+ for (const key2 in mask) {
48629
+ if (!(key2 in oldShape)) {
48630
+ throw new Error(`Unrecognized key: "${key2}"`);
48110
48631
  }
48111
- if (!mask[key])
48632
+ if (!mask[key2])
48112
48633
  continue;
48113
- shape[key] = Class3 ? new Class3({
48634
+ shape[key2] = Class3 ? new Class3({
48114
48635
  type: "optional",
48115
- innerType: oldShape[key]
48116
- }) : oldShape[key];
48636
+ innerType: oldShape[key2]
48637
+ }) : oldShape[key2];
48117
48638
  }
48118
48639
  } else {
48119
- for (const key in oldShape) {
48120
- shape[key] = Class3 ? new Class3({
48640
+ for (const key2 in oldShape) {
48641
+ shape[key2] = Class3 ? new Class3({
48121
48642
  type: "optional",
48122
- innerType: oldShape[key]
48123
- }) : oldShape[key];
48643
+ innerType: oldShape[key2]
48644
+ }) : oldShape[key2];
48124
48645
  }
48125
48646
  }
48126
48647
  return clone2(schema, {
@@ -48133,22 +48654,22 @@ function required2(Class3, schema, mask) {
48133
48654
  const oldShape = schema._zod.def.shape;
48134
48655
  const shape = { ...oldShape };
48135
48656
  if (mask) {
48136
- for (const key in mask) {
48137
- if (!(key in shape)) {
48138
- throw new Error(`Unrecognized key: "${key}"`);
48657
+ for (const key2 in mask) {
48658
+ if (!(key2 in shape)) {
48659
+ throw new Error(`Unrecognized key: "${key2}"`);
48139
48660
  }
48140
- if (!mask[key])
48661
+ if (!mask[key2])
48141
48662
  continue;
48142
- shape[key] = new Class3({
48663
+ shape[key2] = new Class3({
48143
48664
  type: "nonoptional",
48144
- innerType: oldShape[key]
48665
+ innerType: oldShape[key2]
48145
48666
  });
48146
48667
  }
48147
48668
  } else {
48148
- for (const key in oldShape) {
48149
- shape[key] = new Class3({
48669
+ for (const key2 in oldShape) {
48670
+ shape[key2] = new Class3({
48150
48671
  type: "nonoptional",
48151
- innerType: oldShape[key]
48672
+ innerType: oldShape[key2]
48152
48673
  });
48153
48674
  }
48154
48675
  }
@@ -49344,28 +49865,28 @@ var $ZodArray2 = /* @__PURE__ */ $constructor2("$ZodArray", (inst, def) => {
49344
49865
  return payload;
49345
49866
  };
49346
49867
  });
49347
- function handleObjectResult(result, final, key) {
49868
+ function handleObjectResult(result, final, key2) {
49348
49869
  if (result.issues.length) {
49349
- final.issues.push(...prefixIssues2(key, result.issues));
49870
+ final.issues.push(...prefixIssues2(key2, result.issues));
49350
49871
  }
49351
- final.value[key] = result.value;
49872
+ final.value[key2] = result.value;
49352
49873
  }
49353
- function handleOptionalObjectResult(result, final, key, input) {
49874
+ function handleOptionalObjectResult(result, final, key2, input) {
49354
49875
  if (result.issues.length) {
49355
- if (input[key] === void 0) {
49356
- if (key in input) {
49357
- final.value[key] = void 0;
49876
+ if (input[key2] === void 0) {
49877
+ if (key2 in input) {
49878
+ final.value[key2] = void 0;
49358
49879
  } else {
49359
- final.value[key] = result.value;
49880
+ final.value[key2] = result.value;
49360
49881
  }
49361
49882
  } else {
49362
- final.issues.push(...prefixIssues2(key, result.issues));
49883
+ final.issues.push(...prefixIssues2(key2, result.issues));
49363
49884
  }
49364
49885
  } else if (result.value === void 0) {
49365
- if (key in input)
49366
- final.value[key] = void 0;
49886
+ if (key2 in input)
49887
+ final.value[key2] = void 0;
49367
49888
  } else {
49368
- final.value[key] = result.value;
49889
+ final.value[key2] = result.value;
49369
49890
  }
49370
49891
  }
49371
49892
  var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
@@ -49389,12 +49910,12 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49389
49910
  defineLazy2(inst._zod, "propValues", () => {
49390
49911
  const shape = def.shape;
49391
49912
  const propValues = {};
49392
- for (const key in shape) {
49393
- const field = shape[key]._zod;
49913
+ for (const key2 in shape) {
49914
+ const field = shape[key2]._zod;
49394
49915
  if (field.values) {
49395
- propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
49916
+ propValues[key2] ?? (propValues[key2] = /* @__PURE__ */ new Set());
49396
49917
  for (const v of field.values)
49397
- propValues[key].add(v);
49918
+ propValues[key2].add(v);
49398
49919
  }
49399
49920
  }
49400
49921
  return propValues;
@@ -49402,22 +49923,22 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49402
49923
  const generateFastpass = (shape) => {
49403
49924
  const doc = new Doc2(["shape", "payload", "ctx"]);
49404
49925
  const normalized = _normalized.value;
49405
- const parseStr = (key) => {
49406
- const k = esc2(key);
49926
+ const parseStr = (key2) => {
49927
+ const k = esc2(key2);
49407
49928
  return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
49408
49929
  };
49409
49930
  doc.write(`const input = payload.value;`);
49410
49931
  const ids = /* @__PURE__ */ Object.create(null);
49411
49932
  let counter = 0;
49412
- for (const key of normalized.keys) {
49413
- ids[key] = `key_${counter++}`;
49933
+ for (const key2 of normalized.keys) {
49934
+ ids[key2] = `key_${counter++}`;
49414
49935
  }
49415
49936
  doc.write(`const newResult = {}`);
49416
- for (const key of normalized.keys) {
49417
- if (normalized.optionalKeys.has(key)) {
49418
- const id = ids[key];
49419
- doc.write(`const ${id} = ${parseStr(key)};`);
49420
- const k = esc2(key);
49937
+ for (const key2 of normalized.keys) {
49938
+ if (normalized.optionalKeys.has(key2)) {
49939
+ const id = ids[key2];
49940
+ doc.write(`const ${id} = ${parseStr(key2)};`);
49941
+ const k = esc2(key2);
49421
49942
  doc.write(`
49422
49943
  if (${id}.issues.length) {
49423
49944
  if (input[${k}] === undefined) {
@@ -49439,14 +49960,14 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49439
49960
  }
49440
49961
  `);
49441
49962
  } else {
49442
- const id = ids[key];
49443
- doc.write(`const ${id} = ${parseStr(key)};`);
49963
+ const id = ids[key2];
49964
+ doc.write(`const ${id} = ${parseStr(key2)};`);
49444
49965
  doc.write(`
49445
49966
  if (${id}.issues.length) payload.issues = payload.issues.concat(${id}.issues.map(iss => ({
49446
49967
  ...iss,
49447
- path: iss.path ? [${esc2(key)}, ...iss.path] : [${esc2(key)}]
49968
+ path: iss.path ? [${esc2(key2)}, ...iss.path] : [${esc2(key2)}]
49448
49969
  })));`);
49449
- doc.write(`newResult[${esc2(key)}] = ${id}.value`);
49970
+ doc.write(`newResult[${esc2(key2)}] = ${id}.value`);
49450
49971
  }
49451
49972
  }
49452
49973
  doc.write(`payload.value = newResult;`);
@@ -49481,16 +50002,16 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49481
50002
  } else {
49482
50003
  payload.value = {};
49483
50004
  const shape = value.shape;
49484
- for (const key of value.keys) {
49485
- const el = shape[key];
49486
- const r = el._zod.run({ value: input[key], issues: [] }, ctx);
50005
+ for (const key2 of value.keys) {
50006
+ const el = shape[key2];
50007
+ const r = el._zod.run({ value: input[key2], issues: [] }, ctx);
49487
50008
  const isOptional = el._zod.optin === "optional" && el._zod.optout === "optional";
49488
50009
  if (r instanceof Promise) {
49489
- proms.push(r.then((r2) => isOptional ? handleOptionalObjectResult(r2, payload, key, input) : handleObjectResult(r2, payload, key)));
50010
+ proms.push(r.then((r2) => isOptional ? handleOptionalObjectResult(r2, payload, key2, input) : handleObjectResult(r2, payload, key2)));
49490
50011
  } else if (isOptional) {
49491
- handleOptionalObjectResult(r, payload, key, input);
50012
+ handleOptionalObjectResult(r, payload, key2, input);
49492
50013
  } else {
49493
- handleObjectResult(r, payload, key);
50014
+ handleObjectResult(r, payload, key2);
49494
50015
  }
49495
50016
  }
49496
50017
  }
@@ -49501,18 +50022,18 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49501
50022
  const keySet = value.keySet;
49502
50023
  const _catchall = catchall._zod;
49503
50024
  const t = _catchall.def.type;
49504
- for (const key of Object.keys(input)) {
49505
- if (keySet.has(key))
50025
+ for (const key2 of Object.keys(input)) {
50026
+ if (keySet.has(key2))
49506
50027
  continue;
49507
50028
  if (t === "never") {
49508
- unrecognized.push(key);
50029
+ unrecognized.push(key2);
49509
50030
  continue;
49510
50031
  }
49511
- const r = _catchall.run({ value: input[key], issues: [] }, ctx);
50032
+ const r = _catchall.run({ value: input[key2], issues: [] }, ctx);
49512
50033
  if (r instanceof Promise) {
49513
- proms.push(r.then((r2) => handleObjectResult(r2, payload, key)));
50034
+ proms.push(r.then((r2) => handleObjectResult(r2, payload, key2)));
49514
50035
  } else {
49515
- handleObjectResult(r, payload, key);
50036
+ handleObjectResult(r, payload, key2);
49516
50037
  }
49517
50038
  }
49518
50039
  if (unrecognized.length) {
@@ -49674,17 +50195,17 @@ function mergeValues2(a, b) {
49674
50195
  }
49675
50196
  if (isPlainObject2(a) && isPlainObject2(b)) {
49676
50197
  const bKeys = Object.keys(b);
49677
- const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
50198
+ const sharedKeys = Object.keys(a).filter((key2) => bKeys.indexOf(key2) !== -1);
49678
50199
  const newObj = { ...a, ...b };
49679
- for (const key of sharedKeys) {
49680
- const sharedValue = mergeValues2(a[key], b[key]);
50200
+ for (const key2 of sharedKeys) {
50201
+ const sharedValue = mergeValues2(a[key2], b[key2]);
49681
50202
  if (!sharedValue.valid) {
49682
50203
  return {
49683
50204
  valid: false,
49684
- mergeErrorPath: [key, ...sharedValue.mergeErrorPath]
50205
+ mergeErrorPath: [key2, ...sharedValue.mergeErrorPath]
49685
50206
  };
49686
50207
  }
49687
- newObj[key] = sharedValue.data;
50208
+ newObj[key2] = sharedValue.data;
49688
50209
  }
49689
50210
  return { valid: true, data: newObj };
49690
50211
  }
@@ -49742,29 +50263,29 @@ var $ZodRecord2 = /* @__PURE__ */ $constructor2("$ZodRecord", (inst, def) => {
49742
50263
  if (def.keyType._zod.values) {
49743
50264
  const values = def.keyType._zod.values;
49744
50265
  payload.value = {};
49745
- for (const key of values) {
49746
- if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
49747
- const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
50266
+ for (const key2 of values) {
50267
+ if (typeof key2 === "string" || typeof key2 === "number" || typeof key2 === "symbol") {
50268
+ const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
49748
50269
  if (result instanceof Promise) {
49749
50270
  proms.push(result.then((result2) => {
49750
50271
  if (result2.issues.length) {
49751
- payload.issues.push(...prefixIssues2(key, result2.issues));
50272
+ payload.issues.push(...prefixIssues2(key2, result2.issues));
49752
50273
  }
49753
- payload.value[key] = result2.value;
50274
+ payload.value[key2] = result2.value;
49754
50275
  }));
49755
50276
  } else {
49756
50277
  if (result.issues.length) {
49757
- payload.issues.push(...prefixIssues2(key, result.issues));
50278
+ payload.issues.push(...prefixIssues2(key2, result.issues));
49758
50279
  }
49759
- payload.value[key] = result.value;
50280
+ payload.value[key2] = result.value;
49760
50281
  }
49761
50282
  }
49762
50283
  }
49763
50284
  let unrecognized;
49764
- for (const key in input) {
49765
- if (!values.has(key)) {
50285
+ for (const key2 in input) {
50286
+ if (!values.has(key2)) {
49766
50287
  unrecognized = unrecognized ?? [];
49767
- unrecognized.push(key);
50288
+ unrecognized.push(key2);
49768
50289
  }
49769
50290
  }
49770
50291
  if (unrecognized && unrecognized.length > 0) {
@@ -49777,10 +50298,10 @@ var $ZodRecord2 = /* @__PURE__ */ $constructor2("$ZodRecord", (inst, def) => {
49777
50298
  }
49778
50299
  } else {
49779
50300
  payload.value = {};
49780
- for (const key of Reflect.ownKeys(input)) {
49781
- if (key === "__proto__")
50301
+ for (const key2 of Reflect.ownKeys(input)) {
50302
+ if (key2 === "__proto__")
49782
50303
  continue;
49783
- const keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
50304
+ const keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
49784
50305
  if (keyResult instanceof Promise) {
49785
50306
  throw new Error("Async schemas not supported in object keys currently");
49786
50307
  }
@@ -49789,24 +50310,24 @@ var $ZodRecord2 = /* @__PURE__ */ $constructor2("$ZodRecord", (inst, def) => {
49789
50310
  origin: "record",
49790
50311
  code: "invalid_key",
49791
50312
  issues: keyResult.issues.map((iss) => finalizeIssue2(iss, ctx, config2())),
49792
- input: key,
49793
- path: [key],
50313
+ input: key2,
50314
+ path: [key2],
49794
50315
  inst
49795
50316
  });
49796
50317
  payload.value[keyResult.value] = keyResult.value;
49797
50318
  continue;
49798
50319
  }
49799
- const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
50320
+ const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
49800
50321
  if (result instanceof Promise) {
49801
50322
  proms.push(result.then((result2) => {
49802
50323
  if (result2.issues.length) {
49803
- payload.issues.push(...prefixIssues2(key, result2.issues));
50324
+ payload.issues.push(...prefixIssues2(key2, result2.issues));
49804
50325
  }
49805
50326
  payload.value[keyResult.value] = result2.value;
49806
50327
  }));
49807
50328
  } else {
49808
50329
  if (result.issues.length) {
49809
- payload.issues.push(...prefixIssues2(key, result.issues));
50330
+ payload.issues.push(...prefixIssues2(key2, result.issues));
49810
50331
  }
49811
50332
  payload.value[keyResult.value] = result.value;
49812
50333
  }
@@ -53083,6 +53604,7 @@ Set agents.<name>.container.image, top-level container.image, or use a preset th
53083
53604
  cwd: cwdByAgent,
53084
53605
  approvals: opts.approvals,
53085
53606
  onTap: opts.onTap,
53607
+ onLifecycle: opts.onLifecycle,
53086
53608
  agentsDir: opts.agentsDir,
53087
53609
  contextSpawns,
53088
53610
  onSessionEstablished: (agentName, sessionKey, sessionId) => opts.contextSpawnRegistry?.linkSession(agentName, sessionKey, sessionId)
@@ -53180,4 +53702,4 @@ export {
53180
53702
  buildAcpRegistry,
53181
53703
  contextEligibleAgents
53182
53704
  };
53183
- //# sourceMappingURL=chunk-35IKQPC5.js.map
53705
+ //# sourceMappingURL=chunk-HE7DVDJA.js.map