zooid 0.14.1 → 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,31 +24398,180 @@ var AcpClient = class {
24367
24398
  `
24368
24399
  );
24369
24400
  const persisted = this.store?.get(threadId);
24370
- if (persisted && this.agentCapabilities.loadSession) {
24371
- try {
24372
- await this.connection.loadSession({
24373
- sessionId: persisted,
24374
- cwd: pathResolve(this.options.agent.cwd ?? process.cwd()),
24375
- mcpServers
24376
- });
24377
- this.sessions.set(key, { sessionId: persisted, startedAt: Date.now() });
24378
- return persisted;
24379
- } catch (err) {
24380
- console.warn(
24381
- `[acp-client:${this.options.agent.id}] loadSession(${persisted}) failed; falling back to newSession:`,
24382
- err
24383
- );
24384
- await this.store?.delete(threadId);
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
+ }
24385
24431
  }
24386
24432
  }
24387
- const { sessionId } = await this.connection.newSession({
24433
+ const { sessionId, modes } = await this.connection.newSession({
24388
24434
  cwd: pathResolve(this.options.agent.cwd ?? process.cwd()),
24389
24435
  mcpServers
24390
24436
  });
24391
- this.sessions.set(key, { sessionId, startedAt: Date.now() });
24437
+ if (generation !== this.generation) throw new Error("ACP connection changed during session setup");
24438
+ await this.applyMode(sessionId, modes);
24439
+ if (generation !== this.generation) throw new Error("ACP connection changed during session setup");
24440
+ this.sessions.set(key2, { sessionId, startedAt: Date.now() });
24392
24441
  await this.store?.set(threadId, sessionId);
24442
+ this.emitLifecycle(threadId, sessionId, "recovered", void 0, "new");
24443
+ this.scheduleIdle(threadId);
24393
24444
  return sessionId;
24394
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
+ }
24553
+ /**
24554
+ * Put a freshly created or loaded session into the agent's configured mode.
24555
+ * Mode ids are adapter-defined, so an id the adapter doesn't list is a
24556
+ * config error: fail the session rather than run it in a mode nobody chose.
24557
+ */
24558
+ async applyMode(sessionId, modes) {
24559
+ const wanted = this.options.agent.mode;
24560
+ if (!wanted || !this.connection) return;
24561
+ if (!modes) {
24562
+ throw new Error(
24563
+ `agents.${this.options.agent.id}.acp.mode "${wanted}": this agent does not offer session modes`
24564
+ );
24565
+ }
24566
+ if (!modes.availableModes.some((m) => m.id === wanted)) {
24567
+ const offered = modes.availableModes.map((m) => m.id).join(", ");
24568
+ throw new Error(
24569
+ `agents.${this.options.agent.id}.acp.mode "${wanted}": not offered by this agent (offers: ${offered})`
24570
+ );
24571
+ }
24572
+ if (modes.currentModeId === wanted) return;
24573
+ await this.connection.setSessionMode({ sessionId, modeId: wanted });
24574
+ }
24395
24575
  async ensureStoreLoaded() {
24396
24576
  if (!this.store) {
24397
24577
  if (!this.options.agentDataDir) {
@@ -24424,31 +24604,94 @@ var AcpClient = class {
24424
24604
  await this.connection.cancel({ sessionId });
24425
24605
  }
24426
24606
  /**
24427
- * Drop the session for the given thread so the next prompt starts fresh.
24428
- * 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.
24429
24609
  */
24430
- endSession(threadId) {
24431
- this.sessions.delete({ threadId, agentId: this.options.agent.id });
24432
- 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
+ });
24433
24656
  }
24434
24657
  async prompt(input) {
24658
+ const generation = this.generation;
24659
+ const state = this.state(input.threadId);
24660
+ state.prompts++;
24661
+ this.clearTimer(input.threadId);
24435
24662
  let sessionId = null;
24436
24663
  let turnId = null;
24437
24664
  try {
24438
- sessionId = await this.ensureSession(input.threadId, input.channelId, input.contextThreadId);
24439
- const promptText = stringifyPromptForLog(input.content);
24440
- turnId = this.turns?.startTurn({ sessionId, promptText }) ?? null;
24441
- debugLog(this.options.agent.id, "prompt \u2192", {
24442
- sessionId,
24443
- content: input.content
24444
- });
24445
- const result = await this.connection.prompt({
24446
- sessionId,
24447
- 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 };
24448
24690
  });
24449
- this.turns?.endTurn({ sessionId, stopReason: result.stopReason });
24691
+ const result = await launched.result;
24692
+ this.turns?.endTurn({ sessionId: launched.id, stopReason: result.stopReason });
24450
24693
  debugLog(this.options.agent.id, "prompt \u2190", {
24451
- sessionId,
24694
+ sessionId: launched.id,
24452
24695
  stopReason: result.stopReason
24453
24696
  });
24454
24697
  return { stopReason: result.stopReason };
@@ -24467,6 +24710,9 @@ var AcpClient = class {
24467
24710
  });
24468
24711
  if (sessionId) this.turns?.endTurn({ sessionId, stopReason: "error" });
24469
24712
  throw err;
24713
+ } finally {
24714
+ state.prompts--;
24715
+ if (generation === this.generation) this.scheduleIdle(input.threadId);
24470
24716
  }
24471
24717
  }
24472
24718
  resolveSpawn() {
@@ -24481,8 +24727,12 @@ var AcpClient = class {
24481
24727
  }
24482
24728
  buildClient() {
24483
24729
  const agentId = this.options.agent.id;
24730
+ const generation = this.generation;
24484
24731
  return {
24485
24732
  sessionUpdate: async (params) => {
24733
+ if (generation !== this.generation || this.replay.has(`${generation}:${params.sessionId}`)) {
24734
+ return;
24735
+ }
24486
24736
  this.turns?.observeUpdate(params.sessionId, params.update);
24487
24737
  debugLog(agentId, "sessionUpdate", params);
24488
24738
  const event = acpUpdateToAgentEvent(params);
@@ -24490,22 +24740,43 @@ var AcpClient = class {
24490
24740
  else debugLog(agentId, "sessionUpdate dropped (unmapped)", params);
24491
24741
  },
24492
24742
  requestPermission: async (params) => {
24743
+ if (generation !== this.generation) return { outcome: { outcome: "cancelled" } };
24493
24744
  debugLog(agentId, "requestPermission", params);
24494
24745
  const tc = params.toolCall;
24495
- const decision = await this.options.onApprovalRequest({
24496
- sessionId: params.sessionId,
24497
- toolCallId: tc.toolCallId,
24498
- toolKind: tc.kind,
24499
- toolTitle: tc.title,
24500
- toolInput: tc.rawInput,
24501
- options: params.options.map((o) => ({
24502
- optionId: o.optionId,
24503
- name: o.name,
24504
- kind: o.kind
24505
- }))
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" });
24506
24753
  });
24507
- debugLog(agentId, "requestPermission \u2190", decision);
24508
- 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
+ }
24509
24780
  }
24510
24781
  };
24511
24782
  }
@@ -24517,9 +24788,9 @@ function stringifyPromptForLog(content) {
24517
24788
  return "<unstringifiable>";
24518
24789
  }
24519
24790
  }
24520
- function debugLog(agentId, label, payload) {
24791
+ function debugLog(agentId, label2, payload) {
24521
24792
  if (payload === void 0) {
24522
- process.stderr.write(`[${agentId}] ${label}
24793
+ process.stderr.write(`[${agentId}] ${label2}
24523
24794
  `);
24524
24795
  return;
24525
24796
  }
@@ -24530,7 +24801,7 @@ function debugLog(agentId, label, payload) {
24530
24801
  s = String(payload);
24531
24802
  }
24532
24803
  if (s.length > 2e3) s = s.slice(0, 2e3) + "\u2026";
24533
- process.stderr.write(`[${agentId}] ${label} ${s}
24804
+ process.stderr.write(`[${agentId}] ${label2} ${s}
24534
24805
  `);
24535
24806
  }
24536
24807
  function forwardStderr(stream, agentId) {
@@ -24558,15 +24829,15 @@ var EnvInterpolationError = class extends Error {
24558
24829
  };
24559
24830
  var isDenied = (name) => name === "ZOOID_TOKEN" || name.startsWith("ZOOID_");
24560
24831
  function interpolateEnv(parsed, processEnv, scope) {
24561
- for (const [key, val] of Object.entries(parsed)) {
24562
- if (isDenied(key)) {
24832
+ for (const [key2, val] of Object.entries(parsed)) {
24833
+ if (isDenied(key2)) {
24563
24834
  throw new EnvInterpolationError(
24564
- `${scope}.${key}: keys in the ZOOID_* namespace are not allowed`
24835
+ `${scope}.${key2}: keys in the ZOOID_* namespace are not allowed`
24565
24836
  );
24566
24837
  }
24567
24838
  if (typeof val !== "string") {
24568
24839
  throw new EnvInterpolationError(
24569
- `${scope}.${key}: env values must be strings (got ${typeof val})`
24840
+ `${scope}.${key2}: env values must be strings (got ${typeof val})`
24570
24841
  );
24571
24842
  }
24572
24843
  REF_RE.lastIndex = 0;
@@ -24575,14 +24846,14 @@ function interpolateEnv(parsed, processEnv, scope) {
24575
24846
  const ref = m[1] ?? m[2];
24576
24847
  if (isDenied(ref)) {
24577
24848
  throw new EnvInterpolationError(
24578
- `${scope}.${key}: references to ZOOID_* vars are not allowed (saw \${${ref}})`
24849
+ `${scope}.${key2}: references to ZOOID_* vars are not allowed (saw \${${ref}})`
24579
24850
  );
24580
24851
  }
24581
24852
  }
24582
24853
  }
24583
24854
  const out = {};
24584
- for (const [key, val] of Object.entries(parsed)) {
24585
- out[key] = interpolateString(val, processEnv);
24855
+ for (const [key2, val] of Object.entries(parsed)) {
24856
+ out[key2] = interpolateString(val, processEnv);
24586
24857
  }
24587
24858
  return out;
24588
24859
  }
@@ -25869,14 +26140,14 @@ function checkListItem(field, index, value) {
25869
26140
  }
25870
26141
  return void 0;
25871
26142
  }
25872
- function checkMapEntry(field, key, value) {
25873
- const checkKey = checkScalarValue(field.mapKey)(key);
26143
+ function checkMapEntry(field, key2, value) {
26144
+ const checkKey = checkScalarValue(field.mapKey)(key2);
25874
26145
  if (checkKey !== true) {
25875
- 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)}`);
25876
26147
  }
25877
26148
  const checkVal = checkSingular(field, value);
25878
26149
  if (checkVal !== true) {
25879
- 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)}`);
25880
26151
  }
25881
26152
  return void 0;
25882
26153
  }
@@ -26589,18 +26860,18 @@ var ReflectMapImpl = class {
26589
26860
  field() {
26590
26861
  return this._field;
26591
26862
  }
26592
- set(key, value) {
26863
+ set(key2, value) {
26593
26864
  if (this.check) {
26594
- const err = checkMapEntry(this._field, key, value);
26865
+ const err = checkMapEntry(this._field, key2, value);
26595
26866
  if (err) {
26596
26867
  throw err;
26597
26868
  }
26598
26869
  }
26599
- this.obj[mapKeyToLocal(key)] = mapValueToLocal(this._field, value);
26870
+ this.obj[mapKeyToLocal(key2)] = mapValueToLocal(this._field, value);
26600
26871
  return this;
26601
26872
  }
26602
- delete(key) {
26603
- const k = mapKeyToLocal(key);
26873
+ delete(key2) {
26874
+ const k = mapKeyToLocal(key2);
26604
26875
  const has = Object.prototype.hasOwnProperty.call(this.obj, k);
26605
26876
  if (has) {
26606
26877
  delete this.obj[k];
@@ -26608,19 +26879,19 @@ var ReflectMapImpl = class {
26608
26879
  return has;
26609
26880
  }
26610
26881
  clear() {
26611
- for (const key of Object.keys(this.obj)) {
26612
- delete this.obj[key];
26882
+ for (const key2 of Object.keys(this.obj)) {
26883
+ delete this.obj[key2];
26613
26884
  }
26614
26885
  }
26615
- get(key) {
26616
- let val = this.obj[mapKeyToLocal(key)];
26886
+ get(key2) {
26887
+ let val = this.obj[mapKeyToLocal(key2)];
26617
26888
  if (val !== void 0) {
26618
26889
  val = mapValueToReflect(this._field, val, this.check);
26619
26890
  }
26620
26891
  return val;
26621
26892
  }
26622
- has(key) {
26623
- return Object.prototype.hasOwnProperty.call(this.obj, mapKeyToLocal(key));
26893
+ has(key2) {
26894
+ return Object.prototype.hasOwnProperty.call(this.obj, mapKeyToLocal(key2));
26624
26895
  }
26625
26896
  *keys() {
26626
26897
  for (const objKey of Object.keys(this.obj)) {
@@ -26701,26 +26972,26 @@ function mapValueToReflect(field, value, check3) {
26701
26972
  }
26702
26973
  return value;
26703
26974
  }
26704
- function mapKeyToLocal(key) {
26705
- 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);
26706
26977
  }
26707
- function mapKeyToReflect(key, type) {
26978
+ function mapKeyToReflect(key2, type) {
26708
26979
  switch (type) {
26709
26980
  case ScalarType.STRING:
26710
- return key;
26981
+ return key2;
26711
26982
  case ScalarType.INT32:
26712
26983
  case ScalarType.FIXED32:
26713
26984
  case ScalarType.UINT32:
26714
26985
  case ScalarType.SFIXED32:
26715
26986
  case ScalarType.SINT32: {
26716
- const n = Number.parseInt(key);
26987
+ const n = Number.parseInt(key2);
26717
26988
  if (Number.isFinite(n)) {
26718
26989
  return n;
26719
26990
  }
26720
26991
  break;
26721
26992
  }
26722
26993
  case ScalarType.BOOL:
26723
- switch (key) {
26994
+ switch (key2) {
26724
26995
  case "true":
26725
26996
  return true;
26726
26997
  case "false":
@@ -26730,18 +27001,18 @@ function mapKeyToReflect(key, type) {
26730
27001
  case ScalarType.UINT64:
26731
27002
  case ScalarType.FIXED64:
26732
27003
  try {
26733
- return protoInt64.uParse(key);
27004
+ return protoInt64.uParse(key2);
26734
27005
  } catch (_a3) {
26735
27006
  }
26736
27007
  break;
26737
27008
  default:
26738
27009
  try {
26739
- return protoInt64.parse(key);
27010
+ return protoInt64.parse(key2);
26740
27011
  } catch (_b) {
26741
27012
  }
26742
27013
  break;
26743
27014
  }
26744
- return key;
27015
+ return key2;
26745
27016
  }
26746
27017
  function longToReflect(field, value) {
26747
27018
  switch (field.scalar) {
@@ -27650,15 +27921,15 @@ function newField(proto, parentOrFile, reg, oneof, mapEntries) {
27650
27921
  enumerable: true,
27651
27922
  configurable: true
27652
27923
  });
27653
- const label = proto.label;
27924
+ const label2 = proto.label;
27654
27925
  const type = proto.type;
27655
27926
  const jstype = (_c = proto.options) === null || _c === void 0 ? void 0 : _c.jstype;
27656
- if (label === LABEL_REPEATED) {
27927
+ if (label2 === LABEL_REPEATED) {
27657
27928
  const mapEntry = type == TYPE_MESSAGE ? mapEntries === null || mapEntries === void 0 ? void 0 : mapEntries.get(trimLeadingDot(proto.typeName)) : void 0;
27658
27929
  if (mapEntry) {
27659
27930
  field.fieldKind = "map";
27660
- const { key, value } = findMapEntryFields(mapEntry);
27661
- field.mapKey = key.scalar;
27931
+ const { key: key2, value } = findMapEntryFields(mapEntry);
27932
+ field.mapKey = key2.scalar;
27662
27933
  field.mapKind = value.fieldKind;
27663
27934
  field.message = value.message;
27664
27935
  field.delimitedEncoding = false;
@@ -27832,10 +28103,10 @@ function isPackedField(proto, parent) {
27832
28103
  });
27833
28104
  }
27834
28105
  function findMapEntryFields(mapEntry) {
27835
- const key = mapEntry.fields.find((f) => f.number === 1);
28106
+ const key2 = mapEntry.fields.find((f) => f.number === 1);
27836
28107
  const value = mapEntry.fields.find((f) => f.number === 2);
27837
- assert2(key && key.fieldKind == "scalar" && key.scalar != ScalarType.BYTES && key.scalar != ScalarType.FLOAT && key.scalar != ScalarType.DOUBLE && value && value.fieldKind != "list" && value.fieldKind != "map");
27838
- 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 };
27839
28110
  }
27840
28111
  function isEnumOpen(desc) {
27841
28112
  var _a3;
@@ -28374,7 +28645,7 @@ function compileMapFieldReader(field) {
28374
28645
  }
28375
28646
  return (message, reader, ctx) => {
28376
28647
  const record3 = message[localName];
28377
- let key;
28648
+ let key2;
28378
28649
  let val;
28379
28650
  const len = reader.uint32();
28380
28651
  const end = reader.pos + len;
@@ -28382,20 +28653,20 @@ function compileMapFieldReader(field) {
28382
28653
  const [fieldNo] = reader.tag();
28383
28654
  switch (fieldNo) {
28384
28655
  case 1:
28385
- key = readKey(reader);
28656
+ key2 = readKey(reader);
28386
28657
  break;
28387
28658
  case 2:
28388
28659
  val = readValue(reader, ctx);
28389
28660
  break;
28390
28661
  }
28391
28662
  }
28392
- if (key === void 0) {
28393
- key = keyZero;
28663
+ if (key2 === void 0) {
28664
+ key2 = keyZero;
28394
28665
  }
28395
28666
  if (val === void 0) {
28396
28667
  val = valueDefault();
28397
28668
  }
28398
- record3[key] = val;
28669
+ record3[key2] = val;
28399
28670
  };
28400
28671
  }
28401
28672
  function compileScalarReader(type, utf8Validation, longAsString) {
@@ -28691,11 +28962,11 @@ function compileMapField(field) {
28691
28962
  const record3 = message[localName];
28692
28963
  const keys = Object.keys(record3);
28693
28964
  for (let i = 0; i < keys.length; i++) {
28694
- const key = keys[i];
28965
+ const key2 = keys[i];
28695
28966
  writer.tag(fieldNo, WireType.LengthDelimited).fork();
28696
- writeKey(writer, key);
28967
+ writeKey(writer, key2);
28697
28968
  writer.tag(2, WireType.LengthDelimited).fork();
28698
- writeMessage(writer, opts, toMessage(record3[key]));
28969
+ writeMessage(writer, opts, toMessage(record3[key2]));
28699
28970
  writer.join();
28700
28971
  writer.join();
28701
28972
  }
@@ -28708,11 +28979,11 @@ function compileMapField(field) {
28708
28979
  const record3 = message[localName];
28709
28980
  const keys = Object.keys(record3);
28710
28981
  for (let i = 0; i < keys.length; i++) {
28711
- const key = keys[i];
28982
+ const key2 = keys[i];
28712
28983
  writer.tag(fieldNo, WireType.LengthDelimited).fork();
28713
- writeKey(writer, key);
28984
+ writeKey(writer, key2);
28714
28985
  writer.tag(2, valueWireType);
28715
- writeScalar(writer, record3[key]);
28986
+ writeScalar(writer, record3[key2]);
28716
28987
  writer.join();
28717
28988
  }
28718
28989
  };
@@ -28721,40 +28992,40 @@ function compileMapKey(field) {
28721
28992
  const wireType = writeTypeOfScalar(field.mapKey);
28722
28993
  const writeScalar = compileScalarValue(field.mapKey, field.parent.typeName, field.name);
28723
28994
  const convertKey = compileMapKeyConverter(field.mapKey);
28724
- return (writer, key) => {
28995
+ return (writer, key2) => {
28725
28996
  writer.tag(1, wireType);
28726
- writeScalar(writer, convertKey(key));
28997
+ writeScalar(writer, convertKey(key2));
28727
28998
  };
28728
28999
  }
28729
29000
  function compileMapKeyConverter(type) {
28730
29001
  switch (type) {
28731
29002
  case ScalarType.STRING:
28732
- return (key) => key;
29003
+ return (key2) => key2;
28733
29004
  case ScalarType.BOOL:
28734
- return (key) => key === "true" ? true : key === "false" ? false : key;
29005
+ return (key2) => key2 === "true" ? true : key2 === "false" ? false : key2;
28735
29006
  case ScalarType.UINT64:
28736
29007
  case ScalarType.FIXED64:
28737
- return (key) => {
29008
+ return (key2) => {
28738
29009
  try {
28739
- return protoInt64.uParse(key);
29010
+ return protoInt64.uParse(key2);
28740
29011
  } catch (_a3) {
28741
- return key;
29012
+ return key2;
28742
29013
  }
28743
29014
  };
28744
29015
  case ScalarType.INT64:
28745
29016
  case ScalarType.SFIXED64:
28746
29017
  case ScalarType.SINT64:
28747
- return (key) => {
29018
+ return (key2) => {
28748
29019
  try {
28749
- return protoInt64.parse(key);
29020
+ return protoInt64.parse(key2);
28750
29021
  } catch (_a3) {
28751
- return key;
29022
+ return key2;
28752
29023
  }
28753
29024
  };
28754
29025
  default:
28755
- return (key) => {
28756
- const n = Number.parseInt(key);
28757
- return Number.isFinite(n) ? n : key;
29026
+ return (key2) => {
29027
+ const n = Number.parseInt(key2);
29028
+ return Number.isFinite(n) ? n : key2;
28758
29029
  };
28759
29030
  }
28760
29031
  }
@@ -29030,9 +29301,9 @@ function fieldEquals(f, a, b, opts) {
29030
29301
  return false;
29031
29302
  }
29032
29303
  }
29033
- for (const key of keys) {
29034
- const va = mapA.get(key);
29035
- const vb = mapB.get(key);
29304
+ for (const key2 of keys) {
29305
+ const va = mapA.get(key2);
29306
+ const vb = mapB.get(key2);
29036
29307
  if (va === vb) {
29037
29308
  continue;
29038
29309
  }
@@ -29397,8 +29668,8 @@ function compileMapValue(field) {
29397
29668
  }
29398
29669
  const jsonObject = {};
29399
29670
  for (let i = 0; i < keys.length; i++) {
29400
- const key = keys[i];
29401
- jsonObject[key] = writeMapValue(opts, record3[key]);
29671
+ const key2 = keys[i];
29672
+ jsonObject[key2] = writeMapValue(opts, record3[key2]);
29402
29673
  }
29403
29674
  return jsonObject;
29404
29675
  };
@@ -29593,8 +29864,8 @@ function structToJson(val) {
29593
29864
  const json2 = {};
29594
29865
  const keys = Object.keys(val.fields);
29595
29866
  for (let i = 0; i < keys.length; i++) {
29596
- const key = keys[i];
29597
- json2[key] = valueToJson(val.fields[key]);
29867
+ const key2 = keys[i];
29868
+ json2[key2] = valueToJson(val.fields[key2]);
29598
29869
  }
29599
29870
  return json2;
29600
29871
  }
@@ -30034,11 +30305,11 @@ function compileMapFieldReader2(field) {
30034
30305
  for (let i = 0; i < jsonMapKeys.length; i++) {
30035
30306
  const jsonMapKey = jsonMapKeys[i];
30036
30307
  const jsonMapValue = json2[jsonMapKey];
30037
- const key = parseMapKey(jsonMapKey);
30038
- if (seen.has(key)) {
30308
+ const key2 = parseMapKey(jsonMapKey);
30309
+ if (seen.has(key2)) {
30039
30310
  throw new FieldError(field, `duplicate map key "${jsonMapKey}"`);
30040
30311
  }
30041
- seen.add(key);
30312
+ seen.add(key2);
30042
30313
  if (jsonMapValue === null && nullResets) {
30043
30314
  throw new FieldError(field, "map value must not be null");
30044
30315
  }
@@ -30046,17 +30317,17 @@ function compileMapFieldReader2(field) {
30046
30317
  if (value === tokenIgnoredUnknownEnum) {
30047
30318
  continue;
30048
30319
  }
30049
- const checkKey = checkMapKey(key);
30320
+ const checkKey = checkMapKey(key2);
30050
30321
  if (checkKey !== true) {
30051
- 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)}`);
30052
30323
  }
30053
30324
  if (checkValue !== void 0) {
30054
30325
  const check3 = checkValue(value);
30055
30326
  if (check3 !== true) {
30056
- 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)}`);
30057
30328
  }
30058
30329
  }
30059
- record3[key] = toLocalValue(value);
30330
+ record3[key2] = toLocalValue(value);
30060
30331
  }
30061
30332
  };
30062
30333
  }
@@ -30335,10 +30606,10 @@ function structFromJson(struct, json2, ctx) {
30335
30606
  }
30336
30607
  const keys = Object.keys(json2);
30337
30608
  for (let i = 0; i < keys.length; i++) {
30338
- const key = keys[i];
30609
+ const key2 = keys[i];
30339
30610
  const parsedValue = create(ValueSchema);
30340
- valueFromJson(parsedValue, json2[key], ctx);
30341
- struct.fields[key] = parsedValue;
30611
+ valueFromJson(parsedValue, json2[key2], ctx);
30612
+ struct.fields[key2] = parsedValue;
30342
30613
  }
30343
30614
  }
30344
30615
  function valueFromJson(value, json2, ctx) {
@@ -30561,15 +30832,15 @@ var CelScalar = {
30561
30832
  };
30562
30833
  var TIMESTAMP = objectType(TimestampSchema);
30563
30834
  var DURATION = objectType(DurationSchema);
30564
- function mapType(key, value) {
30835
+ function mapType(key2, value) {
30565
30836
  return {
30566
30837
  [privateSymbol4]: {},
30567
30838
  kind: "map",
30568
- key,
30839
+ key: key2,
30569
30840
  value,
30570
30841
  name: "map",
30571
30842
  toString() {
30572
- return `map(${key}, ${value})`;
30843
+ return `map(${key2}, ${value})`;
30573
30844
  }
30574
30845
  };
30575
30846
  }
@@ -30862,41 +31133,41 @@ var NativeMap = class {
30862
31133
  get size() {
30863
31134
  return this._map.size;
30864
31135
  }
30865
- get(key) {
30866
- if (isCelUint(key)) {
30867
- key = key.value;
31136
+ get(key2) {
31137
+ if (isCelUint(key2)) {
31138
+ key2 = key2.value;
30868
31139
  }
30869
- if (typeof key === "number") {
30870
- if (!Number.isInteger(key)) {
31140
+ if (typeof key2 === "number") {
31141
+ if (!Number.isInteger(key2)) {
30871
31142
  return void 0;
30872
31143
  }
30873
- key = BigInt(key);
31144
+ key2 = BigInt(key2);
30874
31145
  }
30875
- const value = this._map.get(key);
31146
+ const value = this._map.get(key2);
30876
31147
  if (value !== void 0) {
30877
31148
  return toCel(value);
30878
31149
  }
30879
- if (typeof key === "bigint") {
31150
+ if (typeof key2 === "bigint") {
30880
31151
  for (const mapKey of this._map.keys()) {
30881
31152
  if (!isCelUint(mapKey)) {
30882
31153
  continue;
30883
31154
  }
30884
- if (mapKey.value === key) {
31155
+ if (mapKey.value === key2) {
30885
31156
  return toCel(this._map.get(mapKey));
30886
31157
  }
30887
31158
  }
30888
31159
  }
30889
31160
  return void 0;
30890
31161
  }
30891
- has(key) {
30892
- return this.get(key) != void 0;
31162
+ has(key2) {
31163
+ return this.get(key2) != void 0;
30893
31164
  }
30894
31165
  forEach(callback, thisArg) {
30895
- 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));
30896
31167
  }
30897
31168
  *entries() {
30898
- for (const [key, value] of this._map.entries()) {
30899
- yield [key, toCel(value)];
31169
+ for (const [key2, value] of this._map.entries()) {
31170
+ yield [key2, toCel(value)];
30900
31171
  }
30901
31172
  }
30902
31173
  keys() {
@@ -30920,30 +31191,30 @@ var ProtoMap = class {
30920
31191
  get size() {
30921
31192
  return this._map.size;
30922
31193
  }
30923
- get(key) {
30924
- const value = this._map.get(mapKeyFromCel(this._map.field(), key));
31194
+ get(key2) {
31195
+ const value = this._map.get(mapKeyFromCel(this._map.field(), key2));
30925
31196
  if (value === void 0) {
30926
31197
  return void 0;
30927
31198
  }
30928
31199
  return celFromMapValue(this._map.field(), value);
30929
31200
  }
30930
- has(key) {
30931
- return this._map.has(mapKeyFromCel(this._map.field(), key));
31201
+ has(key2) {
31202
+ return this._map.has(mapKeyFromCel(this._map.field(), key2));
30932
31203
  }
30933
31204
  forEach(callback, thisArg) {
30934
- 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));
30935
31206
  }
30936
31207
  *entries() {
30937
- for (const [key, value] of this._map.entries()) {
31208
+ for (const [key2, value] of this._map.entries()) {
30938
31209
  yield [
30939
- celFromMapKey(this._map.field(), key),
31210
+ celFromMapKey(this._map.field(), key2),
30940
31211
  celFromMapValue(this._map.field(), value)
30941
31212
  ];
30942
31213
  }
30943
31214
  }
30944
31215
  *keys() {
30945
- for (const key of this._map.keys()) {
30946
- yield celFromMapKey(this._map.field(), key);
31216
+ for (const key2 of this._map.keys()) {
31217
+ yield celFromMapKey(this._map.field(), key2);
30947
31218
  }
30948
31219
  }
30949
31220
  *values() {
@@ -31687,17 +31958,17 @@ var LazyDecoder = class {
31687
31958
  this.initializer = initializer5;
31688
31959
  this.cache = /* @__PURE__ */ new Map();
31689
31960
  }
31690
- has(key) {
31691
- return key in this.initializer;
31961
+ has(key2) {
31962
+ return key2 in this.initializer;
31692
31963
  }
31693
- get(key) {
31694
- const cached3 = this.cache.get(key);
31695
- 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)) {
31696
31967
  return cached3 ?? null;
31697
31968
  }
31698
- const fn = this.initializer[key];
31969
+ const fn = this.initializer[key2];
31699
31970
  const val = fn ? fn() : null;
31700
- this.cache.set(key, val);
31971
+ this.cache.set(key2, val);
31701
31972
  return val;
31702
31973
  }
31703
31974
  };
@@ -36341,10 +36612,10 @@ var Builder = class {
36341
36612
  }
36342
36613
  return expr;
36343
36614
  }
36344
- newMapEntry(offset, key, value) {
36615
+ newMapEntry(offset, key2, value) {
36345
36616
  return this.nextEntry(offset, {
36346
36617
  case: "mapKey",
36347
- value: key
36618
+ value: key2
36348
36619
  }, value);
36349
36620
  }
36350
36621
  newStructExpr(offset, entries, messageName = "") {
@@ -36919,8 +37190,8 @@ function parse3(input, options = {}) {
36919
37190
  }
36920
37191
  return selector;
36921
37192
  }
36922
- function item430(offset, key, value) {
36923
- return builder.newStructEntry(offset(), key, value);
37193
+ function item430(offset, key2, value) {
37194
+ return builder.newStructEntry(offset(), key2, value);
36924
37195
  }
36925
37196
  function item437(offset, dot, name, entries) {
36926
37197
  return builder.newStructExpr(offset(), entries, (dot !== null ? dot : "") + name.join("."));
@@ -36931,8 +37202,8 @@ function parse3(input, options = {}) {
36931
37202
  function item461(offset, elements) {
36932
37203
  return builder.newListExpr(offset(), elements);
36933
37204
  }
36934
- function item475(offset, key, value) {
36935
- return builder.newMapEntry(offset(), key, value);
37205
+ function item475(offset, key2, value) {
37206
+ return builder.newMapEntry(offset(), key2, value);
36936
37207
  }
36937
37208
  function item484(offset, entries) {
36938
37209
  return builder.newStructExpr(offset(), entries);
@@ -42291,9 +42562,9 @@ var EvalAccess = class {
42291
42562
  key;
42292
42563
  factory;
42293
42564
  optional;
42294
- constructor(id, key, factory, optional3) {
42565
+ constructor(id, key2, factory, optional3) {
42295
42566
  this.id = id;
42296
- this.key = key;
42567
+ this.key = key2;
42297
42568
  this.factory = factory;
42298
42569
  this.optional = optional3;
42299
42570
  }
@@ -42301,30 +42572,30 @@ var EvalAccess = class {
42301
42572
  if (obj === void 0) {
42302
42573
  return obj;
42303
42574
  }
42304
- const key = this.key.eval(vars);
42305
- if (isCelError(key)) {
42306
- return key;
42575
+ const key2 = this.key.eval(vars);
42576
+ if (isCelError(key2)) {
42577
+ return key2;
42307
42578
  }
42308
- const access = this.factory.newAccess(this.id, key, this.optional);
42579
+ const access = this.factory.newAccess(this.id, key2, this.optional);
42309
42580
  return access.access(vars, obj);
42310
42581
  }
42311
42582
  isPresent(vars, obj) {
42312
42583
  if (obj === void 0) {
42313
42584
  return false;
42314
42585
  }
42315
- const key = this.key.eval(vars);
42316
- if (isCelError(key)) {
42317
- return key;
42586
+ const key2 = this.key.eval(vars);
42587
+ if (isCelError(key2)) {
42588
+ return key2;
42318
42589
  }
42319
- const access = this.factory.newAccess(this.id, key, this.optional);
42590
+ const access = this.factory.newAccess(this.id, key2, this.optional);
42320
42591
  return access.isPresent(vars, obj);
42321
42592
  }
42322
42593
  accessIfPresent(vars, obj, presenceOnly) {
42323
- const key = this.key.eval(vars);
42324
- if (isCelError(key)) {
42325
- return key;
42594
+ const key2 = this.key.eval(vars);
42595
+ if (isCelError(key2)) {
42596
+ return key2;
42326
42597
  }
42327
- const access = this.factory.newAccess(this.id, key, this.optional);
42598
+ const access = this.factory.newAccess(this.id, key2, this.optional);
42328
42599
  return access.accessIfPresent(vars, obj, presenceOnly);
42329
42600
  }
42330
42601
  isOptional() {
@@ -42482,16 +42753,16 @@ function copyList(list, cList) {
42482
42753
  function copyMap(map2, cMap) {
42483
42754
  const field = map2.field();
42484
42755
  for (const [k, v] of cMap.entries()) {
42485
- const key = scalarFromCel(field, field.mapKey, k);
42756
+ const key2 = scalarFromCel(field, field.mapKey, k);
42486
42757
  switch (field.mapKind) {
42487
42758
  case "enum":
42488
- map2.set(key, enumFromCel(field, v));
42759
+ map2.set(key2, enumFromCel(field, v));
42489
42760
  break;
42490
42761
  case "scalar":
42491
- map2.set(key, scalarFromCel(field, field.scalar, v));
42762
+ map2.set(key2, scalarFromCel(field, field.scalar, v));
42492
42763
  break;
42493
42764
  case "message":
42494
- map2.set(key, msgFromCel(field, v));
42765
+ map2.set(key2, msgFromCel(field, v));
42495
42766
  break;
42496
42767
  }
42497
42768
  }
@@ -43182,38 +43453,38 @@ var EvalMap = class {
43182
43453
  }
43183
43454
  entries.set(firstKey, firstVal);
43184
43455
  for (let i = 1; i < this.keys.length; i++) {
43185
- const key = this.mapKeyOrError(this.keys[i].eval(ctx));
43186
- if (isCelError(key)) {
43187
- return key;
43456
+ const key2 = this.mapKeyOrError(this.keys[i].eval(ctx));
43457
+ if (isCelError(key2)) {
43458
+ return key2;
43188
43459
  }
43189
43460
  const val = this.values[i].eval(ctx);
43190
43461
  if (isCelError(val)) {
43191
43462
  return val;
43192
43463
  }
43193
- if (entries.has(key)) {
43194
- return celError(`map key conflict: ${key}`, this.id);
43464
+ if (entries.has(key2)) {
43465
+ return celError(`map key conflict: ${key2}`, this.id);
43195
43466
  }
43196
- if (typeof key === "number" && !Number.isInteger(key)) {
43467
+ if (typeof key2 === "number" && !Number.isInteger(key2)) {
43197
43468
  return unsupportedKeyType(this.id);
43198
43469
  }
43199
- entries.set(key, val);
43470
+ entries.set(key2, val);
43200
43471
  }
43201
43472
  return celMap(entries);
43202
43473
  }
43203
- mapKeyOrError(key) {
43204
- switch (typeof key) {
43474
+ mapKeyOrError(key2) {
43475
+ switch (typeof key2) {
43205
43476
  case "boolean":
43206
43477
  case "bigint":
43207
43478
  case "string":
43208
- return key;
43479
+ return key2;
43209
43480
  case "object":
43210
- if (isCelUint(key)) {
43211
- return key;
43481
+ if (isCelUint(key2)) {
43482
+ return key2;
43212
43483
  }
43213
43484
  return unsupportedKeyType(this.id);
43214
43485
  case "number":
43215
- if (Number.isInteger(key)) {
43216
- return BigInt(key);
43486
+ if (Number.isInteger(key2)) {
43487
+ return BigInt(key2);
43217
43488
  }
43218
43489
  return unsupportedKeyType(this.id);
43219
43490
  default:
@@ -43471,6 +43742,13 @@ function parseAcpBlock(name, raw) {
43471
43742
  `agents.${name}.acp: must specify either preset or command`
43472
43743
  );
43473
43744
  }
43745
+ let mode;
43746
+ if (a.mode !== void 0) {
43747
+ if (typeof a.mode !== "string" || a.mode.trim().length === 0) {
43748
+ throw new Error(`agents.${name}.acp.mode: must be a non-empty string`);
43749
+ }
43750
+ mode = a.mode.trim();
43751
+ }
43474
43752
  if (hasPreset) {
43475
43753
  if (typeof a.preset !== "string" || a.preset.length === 0) {
43476
43754
  throw new Error(`agents.${name}.acp.preset: must be a non-empty string`);
@@ -43487,6 +43765,7 @@ function parseAcpBlock(name, raw) {
43487
43765
  }
43488
43766
  out.model = a.model.trim();
43489
43767
  }
43768
+ if (mode !== void 0) out.mode = mode;
43490
43769
  return out;
43491
43770
  }
43492
43771
  if (typeof a.command !== "string" || a.command.length === 0) {
@@ -43504,7 +43783,7 @@ function parseAcpBlock(name, raw) {
43504
43783
  args.push(v);
43505
43784
  }
43506
43785
  }
43507
- return { command: a.command, args };
43786
+ return mode === void 0 ? { command: a.command, args } : { command: a.command, args, mode };
43508
43787
  }
43509
43788
  function parseApprovalTimeout(name, raw) {
43510
43789
  if (raw === void 0) return 0;
@@ -43531,6 +43810,17 @@ function parseApprovalTimeout(name, raw) {
43531
43810
  }
43532
43811
  throw new Error("unreachable");
43533
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
+ }
43534
43824
  function parseAgentContainer(name, raw, processEnv, configDir) {
43535
43825
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
43536
43826
  throw new Error(`agents.${name}.container must be a mapping`);
@@ -44025,6 +44315,7 @@ function parseAgents(raw, runtime2, transports, daemonHooks, processEnv, configD
44025
44315
  }
44026
44316
  const acp = parseAcpBlock(name, entry.acp);
44027
44317
  const approval_timeout_ms = parseApprovalTimeout(name, entry.approval_timeout);
44318
+ const session_idle_timeout_ms = parseSessionIdleTimeout(name, entry.session_idle_timeout);
44028
44319
  if (entry.docker !== void 0) {
44029
44320
  throw new Error(
44030
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].`
@@ -44086,7 +44377,8 @@ See [ZOD043].`
44086
44377
  workdir,
44087
44378
  hooks: agentHooks,
44088
44379
  acp,
44089
- approval_timeout_ms
44380
+ approval_timeout_ms,
44381
+ session_idle_timeout_ms
44090
44382
  };
44091
44383
  if (containerBlock) agentCfg.container = containerBlock;
44092
44384
  if (binding.matrix) agentCfg.matrix = binding.matrix;
@@ -44188,8 +44480,17 @@ function parseTriggers(raw, agents, transports, validateCron, processEnv, config
44188
44480
  }
44189
44481
  rawMessages = t.messages;
44190
44482
  }
44483
+ let ttlMs;
44484
+ if (t.expires_after !== void 0) {
44485
+ if (typeof t.expires_after !== "string" || t.expires_after.length === 0) {
44486
+ throw new Error(`triggers.${name}.expires_after: must be a non-empty duration string`);
44487
+ }
44488
+ ttlMs = parseDurationMs(`triggers.${name}.expires_after`, t.expires_after);
44489
+ } else {
44490
+ ttlMs = webhook ? void 0 : 6 * 36e5;
44491
+ }
44191
44492
  const messages = rawMessages.map(
44192
- (m, i) => parseTriggerMessage(name, i, m, agents, as, !!webhook)
44493
+ (m, i) => parseTriggerMessage(name, i, m, agents, transports, as, !!webhook, ttlMs)
44193
44494
  );
44194
44495
  const entry = { as, messages };
44195
44496
  if (schedule !== void 0) entry.schedule = schedule;
@@ -44198,50 +44499,96 @@ function parseTriggers(raw, agents, transports, validateCron, processEnv, config
44198
44499
  }
44199
44500
  return result;
44200
44501
  }
44201
- function parseTriggerMessage(name, index, raw, agents, as, hasWebhook) {
44202
- const label = `triggers.${name}.messages[${index}]`;
44502
+ function parseDurationMs(label2, raw) {
44503
+ const m = /^(\d+)(s|m|h)$/.exec(raw);
44504
+ if (!m) {
44505
+ throw new Error(`${label2}: "${raw}" is not a valid duration (use "<n>s", "<n>m", or "<n>h")`);
44506
+ }
44507
+ const n = Number(m[1]);
44508
+ switch (m[2]) {
44509
+ case "s":
44510
+ return n * 1e3;
44511
+ case "m":
44512
+ return n * 6e4;
44513
+ case "h":
44514
+ return n * 60 * 6e4;
44515
+ }
44516
+ throw new Error("unreachable");
44517
+ }
44518
+ function soleMatrixTransport(transports) {
44519
+ const matrixTransports = Object.values(transports).filter(
44520
+ (t) => t.type === "matrix"
44521
+ );
44522
+ if (matrixTransports.length !== 1) {
44523
+ throw new Error(
44524
+ `triggers: a full-MXID mention requires exactly one matrix transport to validate its homeserver against (found ${matrixTransports.length})`
44525
+ );
44526
+ }
44527
+ return matrixTransports[0];
44528
+ }
44529
+ function parseTriggerMessage(name, index, raw, agents, transports, as, hasWebhook, ttlMs) {
44530
+ const label2 = `triggers.${name}.messages[${index}]`;
44203
44531
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
44204
- throw new Error(`${label}: must be a mapping`);
44532
+ throw new Error(`${label2}: must be a mapping`);
44205
44533
  }
44206
44534
  const m = raw;
44207
44535
  if (typeof m.room !== "string" || m.room.length === 0) {
44208
- throw new Error(`${label}.room: must be a non-empty string`);
44536
+ throw new Error(`${label2}.room: must be a non-empty string`);
44209
44537
  }
44210
44538
  if (!MATRIX_ROOM_IDENT_RE.test(m.room)) {
44211
- 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)})`);
44212
44540
  }
44213
44541
  if (typeof m.mention !== "string" || m.mention.length === 0) {
44214
- throw new Error(`${label}.mention: must be a non-empty string`);
44215
- }
44216
- const mentionedAgent = agents[m.mention];
44217
- if (!mentionedAgent) {
44218
- throw new Error(`${label}.mention: unknown agent "${m.mention}"`);
44542
+ throw new Error(`${label2}.mention: must be a non-empty string`);
44219
44543
  }
44220
- if (!mentionedAgent.matrix) {
44221
- throw new Error(
44222
- `${label}.mention: agent "${m.mention}" has no matrix: binding \u2014 a trigger posts through Matrix, so the mentioned agent must be matrix-bound.`
44223
- );
44224
- }
44225
- if (as === mentionedAgent.matrix.user_id) {
44226
- throw new Error(
44227
- `triggers.${name}.as: must not equal the mentioned agent's own MXID (${as}) \u2014 a message an agent sends never routes back to itself, so this trigger would silently never wake "${m.mention}". Post as a different identity (a dedicated bot, or another agent's).`
44228
- );
44544
+ if (m.mention.startsWith("@")) {
44545
+ if (!MATRIX_USER_ID_RE.test(m.mention)) {
44546
+ throw new Error(`${label2}.mention: must be a full MXID (got ${JSON.stringify(m.mention)})`);
44547
+ }
44548
+ const server = m.mention.slice(m.mention.indexOf(":") + 1);
44549
+ const local = deriveServerName(soleMatrixTransport(transports).user_namespace);
44550
+ if (server !== local) {
44551
+ throw new Error(
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.`
44553
+ );
44554
+ }
44555
+ if (as === m.mention) {
44556
+ throw new Error(
44557
+ `triggers.${name}.as: must not equal the mentioned agent's own MXID (${as}) \u2014 a message an agent sends never routes back to itself, so this trigger would silently never wake "${m.mention}". Post as a different identity (a dedicated bot, or another agent's).`
44558
+ );
44559
+ }
44560
+ } else {
44561
+ const mentionedAgent = agents[m.mention];
44562
+ if (!mentionedAgent) {
44563
+ throw new Error(`${label2}.mention: unknown agent "${m.mention}"`);
44564
+ }
44565
+ if (!mentionedAgent.matrix) {
44566
+ throw new Error(
44567
+ `${label2}.mention: agent "${m.mention}" has no matrix: binding \u2014 a trigger posts through Matrix, so the mentioned agent must be matrix-bound.`
44568
+ );
44569
+ }
44570
+ if (as === mentionedAgent.matrix.user_id) {
44571
+ throw new Error(
44572
+ `triggers.${name}.as: must not equal the mentioned agent's own MXID (${as}) \u2014 a message an agent sends never routes back to itself, so this trigger would silently never wake "${m.mention}". Post as a different identity (a dedicated bot, or another agent's).`
44573
+ );
44574
+ }
44229
44575
  }
44230
44576
  if (typeof m.text !== "string" || m.text.length === 0) {
44231
- throw new Error(`${label}.text: must be a non-empty string`);
44577
+ throw new Error(`${label2}.text: must be a non-empty string`);
44232
44578
  }
44233
44579
  const message = { room: m.room, mention: m.mention, text: m.text };
44580
+ if (ttlMs !== void 0) message.ttlMs = ttlMs;
44234
44581
  if (m.match !== void 0) {
44235
44582
  if (typeof m.match !== "string" || m.match.length === 0) {
44236
- throw new Error(`${label}.match: must be a non-empty string`);
44583
+ throw new Error(`${label2}.match: must be a non-empty string`);
44237
44584
  }
44238
44585
  if (!hasWebhook) {
44239
- throw new Error(`${label}.match: only applies to a webhook: trigger`);
44586
+ throw new Error(`${label2}.match: only applies to a webhook: trigger`);
44240
44587
  }
44241
44588
  try {
44242
44589
  message.match = compileMatch(m.match);
44243
44590
  } catch (err) {
44244
- throw new Error(`${label}.match: ${err.message}`);
44591
+ throw new Error(`${label2}.match: ${err.message}`);
44245
44592
  }
44246
44593
  }
44247
44594
  return message;
@@ -44513,10 +44860,10 @@ var AcpAgentRegistry = class {
44513
44860
  this.opts.onSessionEstablished?.(name, threadId, sessionId);
44514
44861
  return sessionId;
44515
44862
  }
44516
- endSession(name, threadId) {
44863
+ async endSession(name, threadId) {
44517
44864
  if (!this.hasAgent(name)) return;
44518
44865
  const client = this.clients.get(name);
44519
- client?.endSession(threadId);
44866
+ await client?.endSession(threadId);
44520
44867
  }
44521
44868
  async cancelSession(name, sessionId) {
44522
44869
  if (!this.hasAgent(name)) return;
@@ -44552,6 +44899,7 @@ var AcpAgentRegistry = class {
44552
44899
  id: name,
44553
44900
  command: spawn4.command,
44554
44901
  args: spawn4.args,
44902
+ mode: cfg.acp.mode,
44555
44903
  env: this.opts.env?.[name],
44556
44904
  cwd: this.resolveSpawnCwd(name),
44557
44905
  image: this.opts.image?.[name],
@@ -44562,6 +44910,8 @@ var AcpAgentRegistry = class {
44562
44910
  onEvent: (e) => this.onEvent(name, e),
44563
44911
  onApprovalRequest: (req) => this.onApprovalRequest(name, req),
44564
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,
44565
44915
  contextSpawn: this.opts.contextSpawns?.[name]
44566
44916
  });
44567
44917
  await client.start();
@@ -44674,6 +45024,7 @@ var ApprovalCorrelator = class extends EventEmitter2 {
44674
45024
  };
44675
45025
 
44676
45026
  // ../core/src/task-actions.ts
45027
+ var HANDOFF_FIELD = "dev.zooid.handoff";
44677
45028
  var NO_PENDING_INPUT = {
44678
45029
  countFor: () => 0,
44679
45030
  cancelFor: () => {
@@ -44960,6 +45311,15 @@ var MatrixClient = class {
44960
45311
  if (!r.ok) throw new Error(`sync(${opts.asUserId}) failed: ${r.status}`);
44961
45312
  return r.json();
44962
45313
  }
45314
+ async fetchRoomState(roomId, asUserId) {
45315
+ const url2 = `${this.homeserver}/_matrix/client/v3/rooms/${encodeURIComponent(roomId)}/state?user_id=${encodeURIComponent(asUserId)}`;
45316
+ const r = await this.fetch(url2, {
45317
+ method: "GET",
45318
+ headers: { Authorization: `Bearer ${this.asToken}` }
45319
+ });
45320
+ if (!r.ok) throw new Error(`fetchRoomState(${roomId}) failed: ${r.status}`);
45321
+ return await r.json();
45322
+ }
44963
45323
  async fetchRoomName(roomId, asUserId) {
44964
45324
  const url2 = `${this.homeserver}/_matrix/client/v3/rooms/${encodeURIComponent(roomId)}/state/m.room.name/?user_id=${encodeURIComponent(asUserId)}`;
44965
45325
  const r = await this.fetch(url2, {
@@ -45201,6 +45561,68 @@ function stripMention(body, userId) {
45201
45561
  return body.replace(re, " ").replace(/\s+/g, " ").trim();
45202
45562
  }
45203
45563
 
45564
+ // ../transport-matrix/src/mention-content.ts
45565
+ function buildMentionContent(input) {
45566
+ return {
45567
+ msgtype: input.msgtype,
45568
+ body: `${input.userId} ${input.text}`.trim(),
45569
+ "m.mentions": { user_ids: [input.userId] }
45570
+ };
45571
+ }
45572
+
45573
+ // ../transport-matrix/src/trigger-freshness.ts
45574
+ function isExpiredTrigger(evt, now) {
45575
+ const stamp = evt.content?.["dev.zooid.trigger"];
45576
+ if (!stamp || typeof stamp !== "object") return false;
45577
+ const { fired_at: firedAt, ttl_ms: ttlMs } = stamp;
45578
+ if (typeof firedAt !== "number" || typeof ttlMs !== "number") return false;
45579
+ return now - firedAt > ttlMs;
45580
+ }
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
+
45204
45626
  // ../transport-matrix/src/router.ts
45205
45627
  var MEDIA_MSGTYPES = /* @__PURE__ */ new Set(["m.image", "m.file", "m.video", "m.audio"]);
45206
45628
  function isMediaMsgtype(t) {
@@ -45210,14 +45632,27 @@ function inboundThreadRoot(event) {
45210
45632
  const r = event.content?.["m.relates_to"];
45211
45633
  return r?.rel_type === "m.thread" && r.event_id ? r.event_id : void 0;
45212
45634
  }
45213
- function route(event, agents, threadStates, task) {
45635
+ function route(event, agents, threadStates, task, knownAgentIds) {
45214
45636
  if (event.type !== "m.room.message") return [];
45215
45637
  if (!event.content?.msgtype) return [];
45216
45638
  if (isMediaMsgtype(event.content.msgtype)) return [];
45639
+ if (isExpiredTrigger(event, Date.now())) {
45640
+ const stamp = event.content["dev.zooid.trigger"];
45641
+ const ageMs = stamp?.fired_at !== void 0 ? Date.now() - stamp.fired_at : void 0;
45642
+ console.info(
45643
+ `[router] dropping expired trigger "${stamp?.name ?? "unknown"}"` + (ageMs !== void 0 ? ` fired ${ageMs}ms ago` : "")
45644
+ );
45645
+ return [];
45646
+ }
45217
45647
  const mentions = new Set(extractMentions(event));
45218
45648
  const matches2 = [];
45219
45649
  const threadRoot = inboundThreadRoot(event);
45220
45650
  const threadState = threadRoot ? threadStates?.get(threadRoot) : void 0;
45651
+ const senderIsAgent = agents.some((x) => x.userId === event.sender) || event.sender !== void 0 && knownAgentIds?.has(event.sender) === true || event.content.msgtype === "m.notice";
45652
+ const addressesAgent = [...mentions].some(
45653
+ (id) => id !== event.sender && (knownAgentIds?.has(id) === true || agents.some((x) => x.userId === id && x.rooms.some((r) => r.alias === event.room_id)))
45654
+ );
45655
+ const handoff = readHandoff(event.content);
45221
45656
  for (const a of agents) {
45222
45657
  if (!a.rooms.some((r) => r.alias === event.room_id)) continue;
45223
45658
  if (task?.isRoot) {
@@ -45225,48 +45660,44 @@ function route(event, agents, threadStates, task) {
45225
45660
  continue;
45226
45661
  }
45227
45662
  if (event.sender === a.userId) continue;
45663
+ const called = senderIsAgent && handoff?.caller === event.sender && handoff?.callee === a.userId;
45228
45664
  if (task) {
45229
- if (mentions.has(a.userId)) {
45230
- matches2.push(a);
45665
+ if (senderIsAgent) {
45666
+ if (called) matches2.push(a);
45231
45667
  continue;
45232
45668
  }
45233
- const senderAgent = agents.find((x) => x.userId === event.sender);
45234
- if (senderAgent) {
45235
- continue;
45236
- } else if (a.name === task.assignee) {
45237
- matches2.push(a);
45238
- }
45669
+ if (mentions.has(a.userId)) matches2.push(a);
45670
+ else if (a.name === task.assignee && !addressesAgent) matches2.push(a);
45239
45671
  continue;
45240
45672
  }
45241
45673
  if (a.trigger === "any") {
45242
45674
  matches2.push(a);
45243
45675
  continue;
45244
45676
  }
45677
+ if (senderIsAgent) {
45678
+ if (called || isReturnRoute(event, a, threadState)) matches2.push(a);
45679
+ continue;
45680
+ }
45245
45681
  if (mentions.has(a.userId)) {
45246
45682
  matches2.push(a);
45247
45683
  continue;
45248
45684
  }
45249
- if (threadState) {
45250
- const senderAgent = agents.find((x) => x.userId === event.sender);
45251
- if (senderAgent) {
45252
- if (isReturnRoute(event, a, agents, threadState)) matches2.push(a);
45253
- } else {
45254
- const lastPoster = threadState.participants.at(-1);
45255
- if (lastPoster) {
45256
- if (lastPoster === a.name) matches2.push(a);
45257
- } else if (threadState.rootMentions.includes(a.name)) {
45258
- matches2.push(a);
45259
- }
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);
45260
45691
  }
45261
45692
  }
45262
45693
  }
45263
45694
  return matches2;
45264
45695
  }
45265
- function isReturnRoute(event, agent, agents, threadState) {
45696
+ function isReturnRoute(event, agent, threadState) {
45266
45697
  if (!threadState || agent.trigger !== "mention") return false;
45267
- const sender = agents.find((x) => x.userId === event.sender);
45268
- if (!sender || sender.name === agent.name) return false;
45269
- 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;
45270
45701
  }
45271
45702
  function wouldCycleCallers(callers, callee, caller) {
45272
45703
  const seen = /* @__PURE__ */ new Set();
@@ -45472,18 +45903,221 @@ function buildUserPowerLevels(asUserId, admins, agents, roomAlias) {
45472
45903
 
45473
45904
  // ../transport-matrix/src/transport.ts
45474
45905
  import { Hono } from "hono";
45475
- import { timingSafeEqual } from "crypto";
45906
+ import { timingSafeEqual, randomUUID as randomUUID5 } from "crypto";
45476
45907
 
45477
45908
  // ../transport-matrix/src/session-keys.ts
45478
45909
  var HANDOFF_KEY_SEP = "|";
45479
45910
  function composeHandoffKey(threadRoot, callEventId) {
45480
45911
  return `${threadRoot}${HANDOFF_KEY_SEP}${callEventId}`;
45481
45912
  }
45482
- function sessionKeyFor(agentName, threadRoot, state) {
45483
- const arc = state?.handoffs[agentName]?.at(-1);
45913
+ function sessionKeyFor(agentUserId, threadRoot, state) {
45914
+ const arc = state?.handoffs[agentUserId]?.at(-1);
45484
45915
  return arc ? composeHandoffKey(threadRoot, arc) : threadRoot;
45485
45916
  }
45486
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
+
46059
+ // ../transport-matrix/src/workforce-publisher.ts
46060
+ function buildWorkforceRoster(agents) {
46061
+ return {
46062
+ version: 1,
46063
+ agents: agents.map((a) => ({
46064
+ user_id: a.userId,
46065
+ name: a.name,
46066
+ rooms: a.rooms.map((r) => r.alias)
46067
+ }))
46068
+ };
46069
+ }
46070
+ async function publishWorkforce(opts) {
46071
+ await opts.client.sendStateEvent({
46072
+ roomId: opts.spaceRoomId,
46073
+ asUserId: opts.asUserId,
46074
+ eventType: "dev.zooid.workforce",
46075
+ stateKey: opts.stateKey ?? "",
46076
+ content: buildWorkforceRoster(opts.agents)
46077
+ });
46078
+ }
46079
+ async function startWorkforcePublisher(opts) {
46080
+ await publishWorkforce({ ...opts, agents: opts.getAgents() });
46081
+ return {
46082
+ async reload() {
46083
+ await publishWorkforce({ ...opts, agents: opts.getAgents() });
46084
+ },
46085
+ async stop() {
46086
+ }
46087
+ };
46088
+ }
46089
+ var WorkforceDirectory = class {
46090
+ rosters = /* @__PURE__ */ new Map();
46091
+ agentIds = /* @__PURE__ */ new Set();
46092
+ /** Seed from a space's full state (`GET /rooms/{id}/state`). */
46093
+ load(events) {
46094
+ for (const ev of events) {
46095
+ if (ev.type === "dev.zooid.workforce" && ev.state_key !== void 0)
46096
+ this.apply(ev.state_key, ev.content);
46097
+ }
46098
+ }
46099
+ /** Replace one workstation's roster; empty content removes it. */
46100
+ apply(stateKey, content) {
46101
+ const agents = content?.agents;
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);
46109
+ else this.rosters.delete(stateKey);
46110
+ this.agentIds.clear();
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;
46118
+ }
46119
+ };
46120
+
45487
46121
  // ../transport-matrix/src/event-encoders.ts
45488
46122
  var RAW_INPUT_STR_MAX = 250;
45489
46123
  function toToolCallBody(evt) {
@@ -45763,7 +46397,33 @@ var SyncLoop = class {
45763
46397
  timeoutMs: this.opts.timeoutMs ?? 3e4
45764
46398
  });
45765
46399
  for (const [roomId, roomState] of Object.entries(res.rooms?.join ?? {})) {
45766
- for (const baseEvt of roomState.timeline?.events ?? []) {
46400
+ const tl = roomState.timeline;
46401
+ if (tl?.limited && tl.prev_batch && since) {
46402
+ const recovered = [];
46403
+ let from = tl.prev_batch;
46404
+ let pages = 0;
46405
+ const max = this.opts.maxGapPages ?? 10;
46406
+ while (from && from !== since && pages < max) {
46407
+ const page = await this.opts.client.fetchRoomMessages({
46408
+ roomId,
46409
+ asUserId: this.opts.asUserId,
46410
+ from,
46411
+ limit: 100
46412
+ });
46413
+ recovered.push(...page.chunk);
46414
+ from = page.end;
46415
+ pages++;
46416
+ }
46417
+ if (pages >= max && from !== since) {
46418
+ console.warn(`[sync-loop] gap in ${roomId} exceeded ${max} pages \u2014 older events skipped`, {
46419
+ asUserId: this.opts.asUserId
46420
+ });
46421
+ }
46422
+ for (const evt of recovered.reverse()) {
46423
+ await this.opts.onEvent({ ...evt, room_id: roomId });
46424
+ }
46425
+ }
46426
+ for (const baseEvt of tl?.events ?? []) {
45767
46427
  await this.opts.onEvent({ ...baseEvt, room_id: roomId });
45768
46428
  }
45769
46429
  }
@@ -46041,15 +46701,24 @@ function renderInvocationReturn(c) {
46041
46701
  ...c.output?.text ? ["", c.output.text] : []
46042
46702
  ].join("\n");
46043
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
+ }
46044
46710
  function renderDelivery(notify) {
46045
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.";
46046
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
+ }
46047
46716
  function renderAssigneeEnvelope(input) {
46048
46717
  return [
46049
46718
  `[task] from ${input.parentAgent} \u2014 you are the assignee of this thread.`,
46050
46719
  "Call zooid_complete_task with a self-contained summary when you are done;",
46051
46720
  "ending your turn without one publishes your last message as the result.",
46052
- "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.",
46053
46722
  "",
46054
46723
  input.prompt
46055
46724
  ].join("\n");
@@ -46058,6 +46727,8 @@ function renderAssigneeEnvelope(input) {
46058
46727
  // ../transport-matrix/src/transport.ts
46059
46728
  var STARTUP_GRACE_MS = 5e3;
46060
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"]);
46061
46732
  async function buildMediaBlocks(items, opts) {
46062
46733
  const blocks = [];
46063
46734
  const pathLines = [];
@@ -46162,6 +46833,7 @@ function createMatrixTransport(opts) {
46162
46833
  const drainQuietMs = opts.drainQuietMs ?? DRAIN_QUIET_MS;
46163
46834
  const drainMaxMs = opts.drainMaxMs ?? DRAIN_MAX_MS;
46164
46835
  const returnGraceMs = opts.returnGraceMs ?? RETURN_GRACE_MS;
46836
+ const remoteReturnGraceMs = opts.remoteReturnGraceMs ?? REMOTE_RETURN_GRACE_MS;
46165
46837
  const mediaClient = opts.media;
46166
46838
  const writeAttachmentFn = opts.writeAttachmentFn ?? writeAttachment;
46167
46839
  const pendingMedia = new PendingMediaStore();
@@ -46182,64 +46854,36 @@ function createMatrixTransport(opts) {
46182
46854
  const pendingInput = opts.pendingInput ?? NO_PENDING_INPUT;
46183
46855
  const bindingFor = (name) => bindings.find((b) => b.name === name);
46184
46856
  const turnQueues = /* @__PURE__ */ new Map();
46185
- const pendingReturns = /* @__PURE__ */ new Map();
46186
- const returnKey = (agentName, threadRoot) => `${agentName}::${threadRoot}`;
46187
- function stashReturn(sender, threadRoot, roomId, evt, targets) {
46188
- const key = returnKey(sender.name, threadRoot);
46189
- let pending = pendingReturns.get(key);
46190
- if (!pending) {
46191
- pending = { roomId, threadRoot, event: evt, texts: [], targets: /* @__PURE__ */ new Map() };
46192
- pendingReturns.set(key, pending);
46193
- }
46194
- pending.event = evt;
46195
- const body = evt.content?.body?.trim();
46196
- if (body) pending.texts.push(body);
46197
- for (const t of targets) pending.targets.set(t.name, t);
46198
- if (pending.timer) clearTimeout(pending.timer);
46199
- pending.timer = setTimeout(() => releaseReturn(key), returnGraceMs);
46200
- pending.timer.unref?.();
46201
- console.log(
46202
- `[matrix] holding return ${sender.name} \u2192 ${[...pending.targets.keys()].join(",")} until turn end (thread=${threadRoot})`
46203
- );
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()];
46204
46874
  }
46205
- function releaseReturn(key) {
46206
- const pending = pendingReturns.get(key);
46207
- if (!pending) return;
46208
- pendingReturns.delete(key);
46209
- if (pending.timer) clearTimeout(pending.timer);
46210
- const promptText = pending.texts.join("\n\n");
46211
- for (const target of pending.targets.values()) {
46212
- 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)}]`);
46213
46879
  void enqueueTurn(target, {
46214
- roomId: pending.roomId,
46215
- threadRoot: pending.threadRoot,
46216
- sessionKey: sessionKeyFor(
46217
- target.name,
46218
- pending.threadRoot,
46219
- threadStates.get(pending.threadRoot)
46220
- ),
46221
- event: pending.event,
46222
- ...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 })
46223
46884
  });
46224
46885
  }
46225
46886
  }
46226
- function dropPendingReturn(threadRoot, agentName) {
46227
- for (const [key, pending] of pendingReturns) {
46228
- if (pending.threadRoot !== threadRoot) continue;
46229
- if (!pending.targets.delete(agentName)) continue;
46230
- if (pending.targets.size === 0) {
46231
- if (pending.timer) clearTimeout(pending.timer);
46232
- pendingReturns.delete(key);
46233
- }
46234
- }
46235
- }
46236
- function dropThreadReturns(threadRoot) {
46237
- for (const [key, pending] of pendingReturns) {
46238
- if (pending.threadRoot !== threadRoot) continue;
46239
- if (pending.timer) clearTimeout(pending.timer);
46240
- pendingReturns.delete(key);
46241
- }
46242
- }
46243
46887
  const cutoffTs = mode === "client" ? Number.NEGATIVE_INFINITY : Date.now() - STARTUP_GRACE_MS;
46244
46888
  const seenEventIds = /* @__PURE__ */ new Set();
46245
46889
  const flushedCounts = /* @__PURE__ */ new Map();
@@ -46273,21 +46917,14 @@ function createMatrixTransport(opts) {
46273
46917
  lastFlushed.set(sessionId, text);
46274
46918
  flushedCounts.set(sessionId, (flushedCounts.get(sessionId) ?? 0) + 1);
46275
46919
  const content = buildTextContent(text);
46276
- const pendingInvocations = registerOutgoingHandoffs(sessionId, text);
46277
46920
  const tail = (sendQueue.get(sessionId) ?? Promise.resolve()).then(async () => {
46278
46921
  try {
46279
- const { event_id } = await client.sendMessage({
46922
+ await client.sendMessage({
46280
46923
  roomId: ctx.roomId,
46281
46924
  asUserId: ctx.agent.userId,
46282
46925
  content,
46283
46926
  threadRoot: ctx.threadRoot
46284
46927
  });
46285
- for (const invocation of pendingInvocations)
46286
- invocations.attachCallEvent(
46287
- invocation.invocationId,
46288
- event_id,
46289
- composeHandoffKey(ctx.threadRoot, event_id)
46290
- );
46291
46928
  } catch (err) {
46292
46929
  console.warn(`[matrix:${ctx.agent.name}] sendMessage flush failed:`, err);
46293
46930
  }
@@ -46295,30 +46932,6 @@ function createMatrixTransport(opts) {
46295
46932
  sendQueue.set(sessionId, tail);
46296
46933
  return true;
46297
46934
  };
46298
- function registerOutgoingHandoffs(sessionId, text) {
46299
- const ctx = sessions.get(sessionId);
46300
- if (!ctx) return [];
46301
- const task = taskRegistry.taskForRoot(ctx.threadRoot);
46302
- if (!task || task.phase !== "open") return [];
46303
- const sessionKey = sessionKeyFor(ctx.agent.name, ctx.threadRoot, threadStates.get(ctx.threadRoot));
46304
- const opened = [];
46305
- for (const userId of extractMentions({ content: { body: text } })) {
46306
- const callee = bindings.find((binding) => binding.userId === userId);
46307
- if (!callee || callee.name === ctx.agent.name) continue;
46308
- if (invocations.isOutstandingAncestor(sessionKey, callee.name)) {
46309
- void client.sendCustomEvent({
46310
- roomId: ctx.roomId,
46311
- asUserId: ctx.agent.userId,
46312
- eventType: "dev.zooid.error",
46313
- 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 } }
46314
- });
46315
- continue;
46316
- }
46317
- opened.push(invocations.open({ taskId: task.taskId, callerAgent: ctx.agent.name, callerSessionKey: sessionKey, calleeAgent: callee.name }));
46318
- taskRegistry.clearSummary(task.taskId);
46319
- }
46320
- return opened;
46321
- }
46322
46935
  agents.onEvent = async (name, event) => {
46323
46936
  const ctx = sessions.get(event.sessionId);
46324
46937
  if (!ctx) {
@@ -46446,8 +47059,8 @@ function createMatrixTransport(opts) {
46446
47059
  }).catch((e) => console.warn(`[matrix:${agent.name}] dev.zooid.error send failed:`, e));
46447
47060
  }
46448
47061
  function enqueueTurn(agent, input) {
46449
- const key = `${agent.name}::${input.sessionKey}`;
46450
- 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(() => {
46451
47064
  let st = threadStates.get(input.threadRoot);
46452
47065
  if (!st) {
46453
47066
  st = {
@@ -46460,12 +47073,13 @@ function createMatrixTransport(opts) {
46460
47073
  }
46461
47074
  if (st.participants.at(-1) !== agent.name) st.participants.push(agent.name);
46462
47075
  }).catch((err) => reportTurnFailure(agent, input, err));
46463
- turnQueues.set(key, chained);
47076
+ turnQueues.set(key2, chained);
46464
47077
  void chained.finally(() => {
46465
- if (turnQueues.get(key) === chained) turnQueues.delete(key);
47078
+ if (turnQueues.get(key2) === chained) turnQueues.delete(key2);
46466
47079
  });
46467
47080
  return chained;
46468
47081
  }
47082
+ let workforceSpaceId;
46469
47083
  async function handleInboundEvent(evt) {
46470
47084
  if (evt.event_id) {
46471
47085
  if (seenEventIds.has(evt.event_id)) {
@@ -46483,6 +47097,11 @@ function createMatrixTransport(opts) {
46483
47097
  );
46484
47098
  return;
46485
47099
  }
47100
+ if (evt.type === "dev.zooid.workforce") {
47101
+ if (evt.room_id === workforceSpaceId && evt.state_key !== void 0)
47102
+ workforce.apply(evt.state_key, evt.content);
47103
+ return;
47104
+ }
46486
47105
  if (evt.type === "m.room.member" && evt.content?.membership === "invite") {
46487
47106
  const target = evt.state_key;
46488
47107
  const inviter = evt.sender;
@@ -46504,27 +47123,43 @@ function createMatrixTransport(opts) {
46504
47123
  return;
46505
47124
  }
46506
47125
  console.log(`[matrix] inbound dev.zooid.session_reset in ${evt.room_id} thread=${threadRoot}`);
46507
- dropThreadReturns(threadRoot);
47126
+ returns.dropThread(threadRoot);
47127
+ for (const k of [...openHandoffs.keys()]) if (k.endsWith(`::${threadRoot}`)) openHandoffs.delete(k);
46508
47128
  if (!threadStates.has(threadRoot) && evt.room_id) {
46509
47129
  try {
46510
47130
  threadStates.set(
46511
47131
  threadRoot,
46512
- await rebuildThreadState(client, evt.room_id, threadRoot, bindings)
47132
+ await rebuildThreadState(client, evt.room_id, threadRoot, bindings, workforce.agentIds)
46513
47133
  );
46514
47134
  } catch (err) {
46515
47135
  console.warn(`[matrix] failed to rebuild threadState for reset ${threadRoot}:`, err);
46516
47136
  }
46517
47137
  }
46518
47138
  const st = threadStates.get(threadRoot);
47139
+ const cleanup = [];
46519
47140
  for (const a of bindings) {
46520
- 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
+ });
46521
47146
  taskRegistry.bumpGeneration(a.name, threadRoot);
46522
- for (const arc of st?.handoffs[a.name] ?? []) {
46523
- const key = composeHandoffKey(threadRoot, arc);
46524
- agents.endSession(a.name, key);
46525
- 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);
46526
47155
  }
46527
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
+ });
46528
47163
  return;
46529
47164
  }
46530
47165
  if (evt.type === "dev.zooid.interrupt") {
@@ -46532,6 +47167,7 @@ function createMatrixTransport(opts) {
46532
47167
  const relates = evt.content?.["m.relates_to"];
46533
47168
  const threadRoot = relates?.rel_type === "m.thread" && relates.event_id ? relates.event_id : void 0;
46534
47169
  if (threadRoot) {
47170
+ returns.interrupt(threadRoot);
46535
47171
  const targets = [];
46536
47172
  for (const [sessionId, ctx2] of sessions) {
46537
47173
  if (ctx2.threadRoot === threadRoot) {
@@ -46568,6 +47204,7 @@ function createMatrixTransport(opts) {
46568
47204
  console.log(
46569
47205
  `[matrix] interrupt session=${content.session_id} agent=${ctx.agent.name}` + (content.reason ? ` reason=${content.reason}` : "")
46570
47206
  );
47207
+ returns.interrupt(ctx.threadRoot);
46571
47208
  await agents.cancelSession(ctx.agent.name, content.session_id).catch((err) => {
46572
47209
  console.error(
46573
47210
  `[matrix] cancelSession(${ctx.agent.name}, ${content.session_id}) failed:`,
@@ -46586,12 +47223,13 @@ function createMatrixTransport(opts) {
46586
47223
  }
46587
47224
  logInbound(evt);
46588
47225
  if (evt.type === "dev.zooid.turn.end") {
46589
- const agentId = evt.content?.agent_id;
46590
47226
  const endedRoot = inboundThreadRoot2(evt);
46591
- const senderAgent = bindings.find((binding) => binding.userId === evt.sender);
46592
- if (agentId && endedRoot && senderAgent?.name === agentId) {
46593
- releaseReturn(returnKey(agentId, endedRoot));
46594
- }
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);
46595
47233
  return;
46596
47234
  }
46597
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)) {
@@ -46610,7 +47248,13 @@ function createMatrixTransport(opts) {
46610
47248
  const inboundRel = inboundThreadRoot2(evt);
46611
47249
  if (evt.type === "m.room.message" && inboundRel && !threadStates.has(inboundRel) && evt.room_id) {
46612
47250
  try {
46613
- const rebuilt = await rebuildThreadState(client, evt.room_id, inboundRel, bindings);
47251
+ const rebuilt = await rebuildThreadState(
47252
+ client,
47253
+ evt.room_id,
47254
+ inboundRel,
47255
+ bindings,
47256
+ workforce.agentIds
47257
+ );
46614
47258
  threadStates.set(inboundRel, rebuilt);
46615
47259
  console.log(
46616
47260
  `[matrix] rebuilt threadState for ${inboundRel}: participants=${rebuilt.participants.join(",")} rootMentions=${rebuilt.rootMentions.join(",")}`
@@ -46628,22 +47272,29 @@ function createMatrixTransport(opts) {
46628
47272
  assignee: taskRec.assignee,
46629
47273
  isRoot: !inboundRel && evt.event_id === taskRec.threadRoot
46630
47274
  } : void 0;
46631
- let matches2 = route(evt, bindings, threadStates, taskCtx);
47275
+ const inboundState = inboundRel ? threadStates.get(inboundRel) : void 0;
47276
+ if (inboundState && evt.type === "m.room.message" && evt.sender && isRemoteAgent(evt.sender, evt.content?.msgtype, bindings, workforce.agentIds) && inboundState.participants.at(-1) !== evt.sender)
47277
+ inboundState.participants.push(evt.sender);
47278
+ let matches2 = route(evt, bindings, threadStates, taskCtx, workforce.agentIds);
46632
47279
  if (taskCtx && !taskCtx.isRoot && evt.event_id && bindings.some((b) => b.userId === evt.sender)) {
46633
47280
  const invocation = invocations.byCallEvent(evt.event_id);
46634
47281
  matches2 = invocation ? matches2.filter((match) => match.name === invocation.calleeAgent) : [];
46635
47282
  }
46636
- if (evt.type === "m.room.message" && promotedRoot && evt.room_id) {
46637
- const senderBinding = bindings.find((b) => b.userId === evt.sender);
46638
- 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) {
46639
47286
  const st = threadStates.get(promotedRoot);
46640
- const held = matches2.filter((m) => isReturnRoute(evt, m, bindings, st));
47287
+ const held = matches2.filter((m) => isReturnRoute(evt, m, st));
46641
47288
  if (held.length > 0) {
46642
47289
  matches2 = matches2.filter((m) => !held.includes(m));
46643
- 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
+ );
46644
47296
  }
46645
47297
  }
46646
- for (const m of matches2) dropPendingReturn(promotedRoot, m.name);
46647
47298
  }
46648
47299
  const senderIsBot = bindings.some((b) => b.userId === evt.sender);
46649
47300
  if (evt.type === "m.room.message" && matches2.length === 0 && !senderIsBot) {
@@ -46651,7 +47302,9 @@ function createMatrixTransport(opts) {
46651
47302
  `[matrix] no agent matched message in ${evt.room_id} from ${evt.sender} (bindings: ${bindings.map((b) => `${b.name}@${b.userId}[${b.trigger}]`).join(", ")})`
46652
47303
  );
46653
47304
  }
46654
- 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)) {
46655
47308
  let st = threadStates.get(promotedRoot);
46656
47309
  if (!st) {
46657
47310
  st = { participants: [], rootMentions: [], callers: {}, handoffs: {} };
@@ -46660,17 +47313,26 @@ function createMatrixTransport(opts) {
46660
47313
  if (taskCtx?.isRoot) {
46661
47314
  if (!st.rootMentions.includes(taskRec.assignee)) st.rootMentions.push(taskRec.assignee);
46662
47315
  } else {
46663
- const msgMentions = new Set(extractMentions(evt));
46664
- const senderAgent = bindings.find((b) => b.userId === evt.sender);
46665
- for (const a of bindings) {
46666
- if (!msgMentions.has(a.userId)) continue;
46667
- if (!st.rootMentions.includes(a.name)) st.rootMentions.push(a.name);
46668
- if (senderAgent && a.name !== senderAgent.name && !wouldCycleCallers(st.callers, a.name, senderAgent.name)) {
46669
- st.callers[a.name] = senderAgent.name;
46670
- if (evt.event_id) {
46671
- const arcs = st.handoffs[a.name] ??= [];
46672
- if (!arcs.includes(evt.event_id)) arcs.push(evt.event_id);
46673
- }
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);
46674
47336
  }
46675
47337
  }
46676
47338
  }
@@ -46678,7 +47340,7 @@ function createMatrixTransport(opts) {
46678
47340
  for (const a of matches2) {
46679
47341
  console.log(`[matrix] \u2192 ${a.name} (${a.userId})`);
46680
47342
  if (!promotedRoot || !evt.room_id) continue;
46681
- const sessionKey = sessionKeyFor(a.name, promotedRoot, threadStates.get(promotedRoot));
47343
+ const sessionKey = sessionKeyFor(a.userId, promotedRoot, threadStates.get(promotedRoot));
46682
47344
  const taskEnvelope = taskCtx?.isRoot && a.name === taskRec.assignee ? { parentAgent: taskRec.parent.agent } : void 0;
46683
47345
  void enqueueTurn(a, {
46684
47346
  roomId: evt.room_id,
@@ -46726,10 +47388,10 @@ function createMatrixTransport(opts) {
46726
47388
  return c.json({});
46727
47389
  });
46728
47390
  app.get("/healthz", (c) => c.text("ok"));
46729
- async function runTurn(agent, input) {
47391
+ async function runTurnBody(agent, input) {
46730
47392
  const { roomId, threadRoot, sessionKey } = input;
46731
47393
  const sessionId = await agents.ensureSession(agent.name, sessionKey, roomId, threadRoot);
46732
- sessions.set(sessionId, { agent, roomId, threadRoot });
47394
+ sessions.set(sessionId, { agent, roomId, threadRoot, sessionKey });
46733
47395
  buffers.set(sessionId, "");
46734
47396
  bufferMessageIds.delete(sessionId);
46735
47397
  flushedCounts.set(sessionId, 0);
@@ -46853,10 +47515,19 @@ function createMatrixTransport(opts) {
46853
47515
  sendQueue.delete(sessionId);
46854
47516
  }
46855
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
+ }
46856
47526
  async function finishTask(task, ctx) {
46857
47527
  const threadId = task.threadRoot;
46858
47528
  const completion = ctx.completion;
46859
47529
  if (!taskRegistry.close(task.taskId)) return;
47530
+ for (const k of [...openHandoffs.keys()]) if (k.endsWith(`::${threadId}`)) openHandoffs.delete(k);
46860
47531
  const cancelled = invocations.cancelForTask(task.taskId);
46861
47532
  pendingInput.cancelFor([threadId, ...cancelled.map((i) => i.calleeSessionKey).filter((x) => Boolean(x))]);
46862
47533
  await client.sendCustomEvent({
@@ -46928,7 +47599,7 @@ function createMatrixTransport(opts) {
46928
47599
  results[index] = {
46929
47600
  agent: spec.agent,
46930
47601
  status: "refused",
46931
- 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."
46932
47603
  };
46933
47604
  continue;
46934
47605
  }
@@ -47045,7 +47716,86 @@ function createMatrixTransport(opts) {
47045
47716
  const openTask = taskRegistry.openTaskFor(caller.agentName, caller.threadRoot);
47046
47717
  return {
47047
47718
  is_task_assignee: openTask !== void 0 && openTask.threadRoot === caller.sessionKey,
47048
- 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)
47049
47799
  };
47050
47800
  }
47051
47801
  };
@@ -47099,6 +47849,15 @@ function createMatrixTransport(opts) {
47099
47849
  syncLoops,
47100
47850
  bootstrap: async (bootstrapOpts = {}) => {
47101
47851
  await pool.bootstrap({ adminUserId, ...bootstrapOpts });
47852
+ const { spaceRoomId, asUserId } = bootstrapOpts;
47853
+ if (spaceRoomId && asUserId) {
47854
+ workforceSpaceId = spaceRoomId;
47855
+ try {
47856
+ workforce.load(await client.fetchRoomState(spaceRoomId, asUserId));
47857
+ } catch (err) {
47858
+ console.warn("[matrix] workforce roster load failed:", err);
47859
+ }
47860
+ }
47102
47861
  await Promise.allSettled(
47103
47862
  bindings.map(
47104
47863
  (b) => client.setPresence({ asUserId: b.userId, presence: "online" }).catch((err) => {
@@ -47110,7 +47869,7 @@ function createMatrixTransport(opts) {
47110
47869
  pool
47111
47870
  };
47112
47871
  }
47113
- async function rebuildThreadState(client, roomId, rootEventId, bindings) {
47872
+ async function rebuildThreadState(client, roomId, rootEventId, bindings, knownAgentIds) {
47114
47873
  const state = {
47115
47874
  participants: [],
47116
47875
  rootMentions: [],
@@ -47119,50 +47878,49 @@ async function rebuildThreadState(client, roomId, rootEventId, bindings) {
47119
47878
  };
47120
47879
  const asUser = (bindings.find((b) => b.rooms.some((r) => r.alias === roomId)) ?? bindings[0])?.userId;
47121
47880
  if (!asUser) return state;
47122
- const root = await client.fetchEvent(roomId, rootEventId, asUser);
47123
- if (root) {
47124
- const rootMentions = new Set(extractMentions(root));
47125
- const rootSender = root.sender;
47126
- const rootSenderAgent = rootSender ? bindings.find((b) => b.userId === rootSender) : void 0;
47127
- for (const a of bindings) {
47128
- if (!rootMentions.has(a.userId)) continue;
47129
- if (!state.rootMentions.includes(a.name)) state.rootMentions.push(a.name);
47130
- if (rootSenderAgent && a.name !== rootSenderAgent.name && !wouldCycleCallers(state.callers, a.name, rootSenderAgent.name)) {
47131
- state.callers[a.name] = rootSenderAgent.name;
47132
- const arcs = state.handoffs[a.name] ??= [];
47133
- if (!arcs.includes(rootEventId)) arcs.push(rootEventId);
47134
- }
47135
- }
47136
- }
47137
47881
  const { chunk: thread } = await client.fetchThreadRelations({
47138
47882
  roomId,
47139
47883
  rootEventId,
47140
47884
  asUserId: asUser
47141
47885
  });
47142
- for (const ev of thread) {
47143
- 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) {
47144
47889
  const evSender = ev.sender;
47145
- const evSenderAgent = evSender ? bindings.find((b) => b.userId === evSender) : void 0;
47146
47890
  const evId = ev.event_id;
47147
- for (const a of bindings) {
47148
- if (!mentions.has(a.userId)) continue;
47149
- if (!state.rootMentions.includes(a.name)) state.rootMentions.push(a.name);
47150
- if (evSenderAgent && a.name !== evSenderAgent.name && !wouldCycleCallers(state.callers, a.name, evSenderAgent.name)) {
47151
- state.callers[a.name] = evSenderAgent.name;
47152
- if (evId) {
47153
- const arcs = state.handoffs[a.name] ??= [];
47154
- if (!arcs.includes(evId)) arcs.push(evId);
47155
- }
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);
47156
47904
  }
47157
47905
  }
47906
+ }
47907
+ for (const ev of thread) {
47158
47908
  const type = ev.type;
47909
+ const evSender = ev.sender;
47159
47910
  if (type === "m.room.message" && evSender) {
47160
47911
  const a = bindings.find((b) => b.userId === evSender);
47161
- if (a && state.participants.at(-1) !== a.name) state.participants.push(a.name);
47912
+ const msgtype = ev.content?.msgtype;
47913
+ const participant = a ? a.name : isRemoteAgent(evSender, msgtype, bindings, knownAgentIds) ? evSender : void 0;
47914
+ if (participant && state.participants.at(-1) !== participant)
47915
+ state.participants.push(participant);
47162
47916
  }
47163
47917
  }
47164
47918
  return state;
47165
47919
  }
47920
+ function isRemoteAgent(sender, msgtype, bindings, knownAgentIds) {
47921
+ if (bindings.some((b) => b.userId === sender)) return false;
47922
+ return knownAgentIds?.has(sender) === true || msgtype === "m.notice";
47923
+ }
47166
47924
  function logInbound(evt) {
47167
47925
  const sender = evt.sender ?? "?";
47168
47926
  const room = evt.room_id ?? "?";
@@ -47182,46 +47940,15 @@ function truncate(s, n) {
47182
47940
  return s.length > n ? s.slice(0, n) + "\u2026" : s;
47183
47941
  }
47184
47942
 
47185
- // ../transport-matrix/src/workforce-publisher.ts
47186
- function buildWorkforceRoster(agents) {
47187
- return {
47188
- version: 1,
47189
- agents: agents.map((a) => ({
47190
- user_id: a.userId,
47191
- name: a.name,
47192
- rooms: a.rooms.map((r) => r.alias)
47193
- }))
47194
- };
47195
- }
47196
- async function publishWorkforce(opts) {
47197
- await opts.client.sendStateEvent({
47198
- roomId: opts.spaceRoomId,
47199
- asUserId: opts.asUserId,
47200
- eventType: "dev.zooid.workforce",
47201
- stateKey: "",
47202
- content: buildWorkforceRoster(opts.agents)
47203
- });
47204
- }
47205
- async function startWorkforcePublisher(opts) {
47206
- await publishWorkforce({ ...opts, agents: opts.getAgents() });
47207
- return {
47208
- async reload() {
47209
- await publishWorkforce({ ...opts, agents: opts.getAgents() });
47210
- },
47211
- async stop() {
47212
- }
47213
- };
47214
- }
47215
-
47216
47943
  // ../context-mcp/src/spawn-registry.ts
47217
- import { randomUUID as randomUUID5 } from "crypto";
47944
+ import { randomUUID as randomUUID6 } from "crypto";
47218
47945
  var SpawnRegistry = class {
47219
47946
  bindings = /* @__PURE__ */ new Map();
47220
47947
  spawnByAgentSession = /* @__PURE__ */ new Map();
47221
47948
  spawnByAcpSession = /* @__PURE__ */ new Map();
47222
47949
  tasks;
47223
47950
  register(input) {
47224
- const spawnId = randomUUID5();
47951
+ const spawnId = randomUUID6();
47225
47952
  this.bindings.set(spawnId, { spawnId, ...input });
47226
47953
  this.spawnByAgentSession.set(this.key(input.agentName, input.sessionKey ?? input.threadRef.threadId), spawnId);
47227
47954
  return spawnId;
@@ -47231,11 +47958,11 @@ var SpawnRegistry = class {
47231
47958
  }
47232
47959
  release(spawnId) {
47233
47960
  this.bindings.delete(spawnId);
47234
- for (const [key, value] of this.spawnByAgentSession) {
47235
- if (value === spawnId) this.spawnByAgentSession.delete(key);
47961
+ for (const [key2, value] of this.spawnByAgentSession) {
47962
+ if (value === spawnId) this.spawnByAgentSession.delete(key2);
47236
47963
  }
47237
- for (const [key, value] of this.spawnByAcpSession) {
47238
- if (value === spawnId) this.spawnByAcpSession.delete(key);
47964
+ for (const [key2, value] of this.spawnByAcpSession) {
47965
+ if (value === spawnId) this.spawnByAcpSession.delete(key2);
47239
47966
  }
47240
47967
  }
47241
47968
  linkSession(agentName, sessionKey, acpSessionId) {
@@ -47376,7 +48103,7 @@ async function handleLine(line, socket, registry3, callerAgent) {
47376
48103
  result = await binding.provider.sendMessage(
47377
48104
  req.params
47378
48105
  );
47379
- } 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") {
47380
48107
  const actions = registry3.taskActions;
47381
48108
  if (!actions) {
47382
48109
  socket.write(
@@ -47393,7 +48120,7 @@ async function handleLine(line, socket, registry3, callerAgent) {
47393
48120
  threadRoot: binding.threadRef.threadId,
47394
48121
  sessionKey: binding.sessionKey ?? binding.threadRef.threadId
47395
48122
  };
47396
- 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);
47397
48124
  } else {
47398
48125
  socket.write(
47399
48126
  JSON.stringify({
@@ -47609,19 +48336,19 @@ function floatSafeRemainder2(val, step) {
47609
48336
  const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
47610
48337
  return valInt % stepInt / 10 ** decCount;
47611
48338
  }
47612
- function defineLazy2(object3, key, getter) {
48339
+ function defineLazy2(object3, key2, getter) {
47613
48340
  const set2 = false;
47614
- Object.defineProperty(object3, key, {
48341
+ Object.defineProperty(object3, key2, {
47615
48342
  get() {
47616
48343
  if (!set2) {
47617
48344
  const value = getter();
47618
- object3[key] = value;
48345
+ object3[key2] = value;
47619
48346
  return value;
47620
48347
  }
47621
48348
  throw new Error("cached value already set");
47622
48349
  },
47623
48350
  set(v) {
47624
- Object.defineProperty(object3, key, {
48351
+ Object.defineProperty(object3, key2, {
47625
48352
  value: v
47626
48353
  // configurable: true,
47627
48354
  });
@@ -47640,11 +48367,11 @@ function assignProp2(target, prop, value) {
47640
48367
  function getElementAtPath2(obj, path) {
47641
48368
  if (!path)
47642
48369
  return obj;
47643
- return path.reduce((acc, key) => acc?.[key], obj);
48370
+ return path.reduce((acc, key2) => acc?.[key2], obj);
47644
48371
  }
47645
48372
  function promiseAllObject2(promisesObj) {
47646
48373
  const keys = Object.keys(promisesObj);
47647
- const promises = keys.map((key) => promisesObj[key]);
48374
+ const promises = keys.map((key2) => promisesObj[key2]);
47648
48375
  return Promise.all(promises).then((results) => {
47649
48376
  const resolvedObj = {};
47650
48377
  for (let i = 0; i < keys.length; i++) {
@@ -47697,8 +48424,8 @@ function isPlainObject2(o) {
47697
48424
  }
47698
48425
  function numKeys2(data) {
47699
48426
  let keyCount = 0;
47700
- for (const key in data) {
47701
- if (Object.prototype.hasOwnProperty.call(data, key)) {
48427
+ for (const key2 in data) {
48428
+ if (Object.prototype.hasOwnProperty.call(data, key2)) {
47702
48429
  keyCount++;
47703
48430
  }
47704
48431
  }
@@ -47834,13 +48561,13 @@ var BIGINT_FORMAT_RANGES2 = {
47834
48561
  function pick2(schema, mask) {
47835
48562
  const newShape = {};
47836
48563
  const currDef = schema._zod.def;
47837
- for (const key in mask) {
47838
- if (!(key in currDef.shape)) {
47839
- 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}"`);
47840
48567
  }
47841
- if (!mask[key])
48568
+ if (!mask[key2])
47842
48569
  continue;
47843
- newShape[key] = currDef.shape[key];
48570
+ newShape[key2] = currDef.shape[key2];
47844
48571
  }
47845
48572
  return clone2(schema, {
47846
48573
  ...schema._zod.def,
@@ -47851,13 +48578,13 @@ function pick2(schema, mask) {
47851
48578
  function omit2(schema, mask) {
47852
48579
  const newShape = { ...schema._zod.def.shape };
47853
48580
  const currDef = schema._zod.def;
47854
- for (const key in mask) {
47855
- if (!(key in currDef.shape)) {
47856
- 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}"`);
47857
48584
  }
47858
- if (!mask[key])
48585
+ if (!mask[key2])
47859
48586
  continue;
47860
- delete newShape[key];
48587
+ delete newShape[key2];
47861
48588
  }
47862
48589
  return clone2(schema, {
47863
48590
  ...schema._zod.def,
@@ -47898,23 +48625,23 @@ function partial2(Class3, schema, mask) {
47898
48625
  const oldShape = schema._zod.def.shape;
47899
48626
  const shape = { ...oldShape };
47900
48627
  if (mask) {
47901
- for (const key in mask) {
47902
- if (!(key in oldShape)) {
47903
- throw new Error(`Unrecognized key: "${key}"`);
48628
+ for (const key2 in mask) {
48629
+ if (!(key2 in oldShape)) {
48630
+ throw new Error(`Unrecognized key: "${key2}"`);
47904
48631
  }
47905
- if (!mask[key])
48632
+ if (!mask[key2])
47906
48633
  continue;
47907
- shape[key] = Class3 ? new Class3({
48634
+ shape[key2] = Class3 ? new Class3({
47908
48635
  type: "optional",
47909
- innerType: oldShape[key]
47910
- }) : oldShape[key];
48636
+ innerType: oldShape[key2]
48637
+ }) : oldShape[key2];
47911
48638
  }
47912
48639
  } else {
47913
- for (const key in oldShape) {
47914
- shape[key] = Class3 ? new Class3({
48640
+ for (const key2 in oldShape) {
48641
+ shape[key2] = Class3 ? new Class3({
47915
48642
  type: "optional",
47916
- innerType: oldShape[key]
47917
- }) : oldShape[key];
48643
+ innerType: oldShape[key2]
48644
+ }) : oldShape[key2];
47918
48645
  }
47919
48646
  }
47920
48647
  return clone2(schema, {
@@ -47927,22 +48654,22 @@ function required2(Class3, schema, mask) {
47927
48654
  const oldShape = schema._zod.def.shape;
47928
48655
  const shape = { ...oldShape };
47929
48656
  if (mask) {
47930
- for (const key in mask) {
47931
- if (!(key in shape)) {
47932
- throw new Error(`Unrecognized key: "${key}"`);
48657
+ for (const key2 in mask) {
48658
+ if (!(key2 in shape)) {
48659
+ throw new Error(`Unrecognized key: "${key2}"`);
47933
48660
  }
47934
- if (!mask[key])
48661
+ if (!mask[key2])
47935
48662
  continue;
47936
- shape[key] = new Class3({
48663
+ shape[key2] = new Class3({
47937
48664
  type: "nonoptional",
47938
- innerType: oldShape[key]
48665
+ innerType: oldShape[key2]
47939
48666
  });
47940
48667
  }
47941
48668
  } else {
47942
- for (const key in oldShape) {
47943
- shape[key] = new Class3({
48669
+ for (const key2 in oldShape) {
48670
+ shape[key2] = new Class3({
47944
48671
  type: "nonoptional",
47945
- innerType: oldShape[key]
48672
+ innerType: oldShape[key2]
47946
48673
  });
47947
48674
  }
47948
48675
  }
@@ -49138,28 +49865,28 @@ var $ZodArray2 = /* @__PURE__ */ $constructor2("$ZodArray", (inst, def) => {
49138
49865
  return payload;
49139
49866
  };
49140
49867
  });
49141
- function handleObjectResult(result, final, key) {
49868
+ function handleObjectResult(result, final, key2) {
49142
49869
  if (result.issues.length) {
49143
- final.issues.push(...prefixIssues2(key, result.issues));
49870
+ final.issues.push(...prefixIssues2(key2, result.issues));
49144
49871
  }
49145
- final.value[key] = result.value;
49872
+ final.value[key2] = result.value;
49146
49873
  }
49147
- function handleOptionalObjectResult(result, final, key, input) {
49874
+ function handleOptionalObjectResult(result, final, key2, input) {
49148
49875
  if (result.issues.length) {
49149
- if (input[key] === void 0) {
49150
- if (key in input) {
49151
- final.value[key] = void 0;
49876
+ if (input[key2] === void 0) {
49877
+ if (key2 in input) {
49878
+ final.value[key2] = void 0;
49152
49879
  } else {
49153
- final.value[key] = result.value;
49880
+ final.value[key2] = result.value;
49154
49881
  }
49155
49882
  } else {
49156
- final.issues.push(...prefixIssues2(key, result.issues));
49883
+ final.issues.push(...prefixIssues2(key2, result.issues));
49157
49884
  }
49158
49885
  } else if (result.value === void 0) {
49159
- if (key in input)
49160
- final.value[key] = void 0;
49886
+ if (key2 in input)
49887
+ final.value[key2] = void 0;
49161
49888
  } else {
49162
- final.value[key] = result.value;
49889
+ final.value[key2] = result.value;
49163
49890
  }
49164
49891
  }
49165
49892
  var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
@@ -49183,12 +49910,12 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49183
49910
  defineLazy2(inst._zod, "propValues", () => {
49184
49911
  const shape = def.shape;
49185
49912
  const propValues = {};
49186
- for (const key in shape) {
49187
- const field = shape[key]._zod;
49913
+ for (const key2 in shape) {
49914
+ const field = shape[key2]._zod;
49188
49915
  if (field.values) {
49189
- propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
49916
+ propValues[key2] ?? (propValues[key2] = /* @__PURE__ */ new Set());
49190
49917
  for (const v of field.values)
49191
- propValues[key].add(v);
49918
+ propValues[key2].add(v);
49192
49919
  }
49193
49920
  }
49194
49921
  return propValues;
@@ -49196,22 +49923,22 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49196
49923
  const generateFastpass = (shape) => {
49197
49924
  const doc = new Doc2(["shape", "payload", "ctx"]);
49198
49925
  const normalized = _normalized.value;
49199
- const parseStr = (key) => {
49200
- const k = esc2(key);
49926
+ const parseStr = (key2) => {
49927
+ const k = esc2(key2);
49201
49928
  return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
49202
49929
  };
49203
49930
  doc.write(`const input = payload.value;`);
49204
49931
  const ids = /* @__PURE__ */ Object.create(null);
49205
49932
  let counter = 0;
49206
- for (const key of normalized.keys) {
49207
- ids[key] = `key_${counter++}`;
49933
+ for (const key2 of normalized.keys) {
49934
+ ids[key2] = `key_${counter++}`;
49208
49935
  }
49209
49936
  doc.write(`const newResult = {}`);
49210
- for (const key of normalized.keys) {
49211
- if (normalized.optionalKeys.has(key)) {
49212
- const id = ids[key];
49213
- doc.write(`const ${id} = ${parseStr(key)};`);
49214
- 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);
49215
49942
  doc.write(`
49216
49943
  if (${id}.issues.length) {
49217
49944
  if (input[${k}] === undefined) {
@@ -49233,14 +49960,14 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49233
49960
  }
49234
49961
  `);
49235
49962
  } else {
49236
- const id = ids[key];
49237
- doc.write(`const ${id} = ${parseStr(key)};`);
49963
+ const id = ids[key2];
49964
+ doc.write(`const ${id} = ${parseStr(key2)};`);
49238
49965
  doc.write(`
49239
49966
  if (${id}.issues.length) payload.issues = payload.issues.concat(${id}.issues.map(iss => ({
49240
49967
  ...iss,
49241
- path: iss.path ? [${esc2(key)}, ...iss.path] : [${esc2(key)}]
49968
+ path: iss.path ? [${esc2(key2)}, ...iss.path] : [${esc2(key2)}]
49242
49969
  })));`);
49243
- doc.write(`newResult[${esc2(key)}] = ${id}.value`);
49970
+ doc.write(`newResult[${esc2(key2)}] = ${id}.value`);
49244
49971
  }
49245
49972
  }
49246
49973
  doc.write(`payload.value = newResult;`);
@@ -49275,16 +50002,16 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49275
50002
  } else {
49276
50003
  payload.value = {};
49277
50004
  const shape = value.shape;
49278
- for (const key of value.keys) {
49279
- const el = shape[key];
49280
- 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);
49281
50008
  const isOptional = el._zod.optin === "optional" && el._zod.optout === "optional";
49282
50009
  if (r instanceof Promise) {
49283
- 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)));
49284
50011
  } else if (isOptional) {
49285
- handleOptionalObjectResult(r, payload, key, input);
50012
+ handleOptionalObjectResult(r, payload, key2, input);
49286
50013
  } else {
49287
- handleObjectResult(r, payload, key);
50014
+ handleObjectResult(r, payload, key2);
49288
50015
  }
49289
50016
  }
49290
50017
  }
@@ -49295,18 +50022,18 @@ var $ZodObject2 = /* @__PURE__ */ $constructor2("$ZodObject", (inst, def) => {
49295
50022
  const keySet = value.keySet;
49296
50023
  const _catchall = catchall._zod;
49297
50024
  const t = _catchall.def.type;
49298
- for (const key of Object.keys(input)) {
49299
- if (keySet.has(key))
50025
+ for (const key2 of Object.keys(input)) {
50026
+ if (keySet.has(key2))
49300
50027
  continue;
49301
50028
  if (t === "never") {
49302
- unrecognized.push(key);
50029
+ unrecognized.push(key2);
49303
50030
  continue;
49304
50031
  }
49305
- const r = _catchall.run({ value: input[key], issues: [] }, ctx);
50032
+ const r = _catchall.run({ value: input[key2], issues: [] }, ctx);
49306
50033
  if (r instanceof Promise) {
49307
- proms.push(r.then((r2) => handleObjectResult(r2, payload, key)));
50034
+ proms.push(r.then((r2) => handleObjectResult(r2, payload, key2)));
49308
50035
  } else {
49309
- handleObjectResult(r, payload, key);
50036
+ handleObjectResult(r, payload, key2);
49310
50037
  }
49311
50038
  }
49312
50039
  if (unrecognized.length) {
@@ -49468,17 +50195,17 @@ function mergeValues2(a, b) {
49468
50195
  }
49469
50196
  if (isPlainObject2(a) && isPlainObject2(b)) {
49470
50197
  const bKeys = Object.keys(b);
49471
- const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
50198
+ const sharedKeys = Object.keys(a).filter((key2) => bKeys.indexOf(key2) !== -1);
49472
50199
  const newObj = { ...a, ...b };
49473
- for (const key of sharedKeys) {
49474
- const sharedValue = mergeValues2(a[key], b[key]);
50200
+ for (const key2 of sharedKeys) {
50201
+ const sharedValue = mergeValues2(a[key2], b[key2]);
49475
50202
  if (!sharedValue.valid) {
49476
50203
  return {
49477
50204
  valid: false,
49478
- mergeErrorPath: [key, ...sharedValue.mergeErrorPath]
50205
+ mergeErrorPath: [key2, ...sharedValue.mergeErrorPath]
49479
50206
  };
49480
50207
  }
49481
- newObj[key] = sharedValue.data;
50208
+ newObj[key2] = sharedValue.data;
49482
50209
  }
49483
50210
  return { valid: true, data: newObj };
49484
50211
  }
@@ -49536,29 +50263,29 @@ var $ZodRecord2 = /* @__PURE__ */ $constructor2("$ZodRecord", (inst, def) => {
49536
50263
  if (def.keyType._zod.values) {
49537
50264
  const values = def.keyType._zod.values;
49538
50265
  payload.value = {};
49539
- for (const key of values) {
49540
- if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
49541
- 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);
49542
50269
  if (result instanceof Promise) {
49543
50270
  proms.push(result.then((result2) => {
49544
50271
  if (result2.issues.length) {
49545
- payload.issues.push(...prefixIssues2(key, result2.issues));
50272
+ payload.issues.push(...prefixIssues2(key2, result2.issues));
49546
50273
  }
49547
- payload.value[key] = result2.value;
50274
+ payload.value[key2] = result2.value;
49548
50275
  }));
49549
50276
  } else {
49550
50277
  if (result.issues.length) {
49551
- payload.issues.push(...prefixIssues2(key, result.issues));
50278
+ payload.issues.push(...prefixIssues2(key2, result.issues));
49552
50279
  }
49553
- payload.value[key] = result.value;
50280
+ payload.value[key2] = result.value;
49554
50281
  }
49555
50282
  }
49556
50283
  }
49557
50284
  let unrecognized;
49558
- for (const key in input) {
49559
- if (!values.has(key)) {
50285
+ for (const key2 in input) {
50286
+ if (!values.has(key2)) {
49560
50287
  unrecognized = unrecognized ?? [];
49561
- unrecognized.push(key);
50288
+ unrecognized.push(key2);
49562
50289
  }
49563
50290
  }
49564
50291
  if (unrecognized && unrecognized.length > 0) {
@@ -49571,10 +50298,10 @@ var $ZodRecord2 = /* @__PURE__ */ $constructor2("$ZodRecord", (inst, def) => {
49571
50298
  }
49572
50299
  } else {
49573
50300
  payload.value = {};
49574
- for (const key of Reflect.ownKeys(input)) {
49575
- if (key === "__proto__")
50301
+ for (const key2 of Reflect.ownKeys(input)) {
50302
+ if (key2 === "__proto__")
49576
50303
  continue;
49577
- const keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
50304
+ const keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
49578
50305
  if (keyResult instanceof Promise) {
49579
50306
  throw new Error("Async schemas not supported in object keys currently");
49580
50307
  }
@@ -49583,24 +50310,24 @@ var $ZodRecord2 = /* @__PURE__ */ $constructor2("$ZodRecord", (inst, def) => {
49583
50310
  origin: "record",
49584
50311
  code: "invalid_key",
49585
50312
  issues: keyResult.issues.map((iss) => finalizeIssue2(iss, ctx, config2())),
49586
- input: key,
49587
- path: [key],
50313
+ input: key2,
50314
+ path: [key2],
49588
50315
  inst
49589
50316
  });
49590
50317
  payload.value[keyResult.value] = keyResult.value;
49591
50318
  continue;
49592
50319
  }
49593
- const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
50320
+ const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
49594
50321
  if (result instanceof Promise) {
49595
50322
  proms.push(result.then((result2) => {
49596
50323
  if (result2.issues.length) {
49597
- payload.issues.push(...prefixIssues2(key, result2.issues));
50324
+ payload.issues.push(...prefixIssues2(key2, result2.issues));
49598
50325
  }
49599
50326
  payload.value[keyResult.value] = result2.value;
49600
50327
  }));
49601
50328
  } else {
49602
50329
  if (result.issues.length) {
49603
- payload.issues.push(...prefixIssues2(key, result.issues));
50330
+ payload.issues.push(...prefixIssues2(key2, result.issues));
49604
50331
  }
49605
50332
  payload.value[keyResult.value] = result.value;
49606
50333
  }
@@ -52877,6 +53604,7 @@ Set agents.<name>.container.image, top-level container.image, or use a preset th
52877
53604
  cwd: cwdByAgent,
52878
53605
  approvals: opts.approvals,
52879
53606
  onTap: opts.onTap,
53607
+ onLifecycle: opts.onLifecycle,
52880
53608
  agentsDir: opts.agentsDir,
52881
53609
  contextSpawns,
52882
53610
  onSessionEstablished: (agentName, sessionKey, sessionId) => opts.contextSpawnRegistry?.linkSession(agentName, sessionKey, sessionId)
@@ -52963,14 +53691,15 @@ export {
52963
53691
  ApprovalCorrelator,
52964
53692
  MatrixClient,
52965
53693
  renderRegistration,
53694
+ buildMentionContent,
52966
53695
  ensureWorkforceSpace,
52967
53696
  ensureDefaultChannel,
53697
+ startWorkforcePublisher,
52968
53698
  MediaClient,
52969
53699
  createMatrixTransport,
52970
- startWorkforcePublisher,
52971
53700
  SpawnRegistry,
52972
53701
  startAgentSocketServers,
52973
53702
  buildAcpRegistry,
52974
53703
  contextEligibleAgents
52975
53704
  };
52976
- //# sourceMappingURL=chunk-R5S26T7B.js.map
53705
+ //# sourceMappingURL=chunk-HE7DVDJA.js.map