@overaihq/cli 0.9.1 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +25 -0
  2. package/dist/index.js +802 -451
  3. package/package.json +7 -2
package/dist/index.js CHANGED
@@ -3276,10 +3276,10 @@ var require_xpath = __commonJS({
3276
3276
  includes(REVERSE_AXES, step.axis)
3277
3277
  );
3278
3278
  }
3279
- function applyStepToNodes(context, nodes, step) {
3279
+ function applyStepToNodes(context2, nodes, step) {
3280
3280
  return flatten(
3281
3281
  map2(
3282
- applyStepWithPredicates.bind(null, step, context),
3282
+ applyStepWithPredicates.bind(null, step, context2),
3283
3283
  nodes
3284
3284
  )
3285
3285
  );
@@ -4410,12 +4410,12 @@ var require_xpath = __commonJS({
4410
4410
  FunctionResolver.prototype.addFunction = function(ns, ln, f) {
4411
4411
  this.functions["{" + ns + "}" + ln] = f;
4412
4412
  };
4413
- FunctionResolver.getFunctionFromContext = function(qName, context) {
4414
- var parts = Utilities.resolveQName(qName, context.namespaceResolver, context.contextNode, false);
4413
+ FunctionResolver.getFunctionFromContext = function(qName, context2) {
4414
+ var parts = Utilities.resolveQName(qName, context2.namespaceResolver, context2.contextNode, false);
4415
4415
  if (parts[0] === null) {
4416
4416
  throw new Error("Cannot resolve QName " + name);
4417
4417
  }
4418
- return context.functionResolver.getFunction(parts[1], parts[0]);
4418
+ return context2.functionResolver.getFunction(parts[1], parts[0]);
4419
4419
  };
4420
4420
  FunctionResolver.prototype.getFunction = function(localName, namespace) {
4421
4421
  return this.functions["{" + namespace + "}" + localName];
@@ -5124,11 +5124,11 @@ var require_xpath = __commonJS({
5124
5124
  return ns;
5125
5125
  }
5126
5126
  function makeEvaluator(func) {
5127
- return function(context) {
5127
+ return function(context2) {
5128
5128
  var args = Array.prototype.slice.call(arguments, 1).map(function(arg) {
5129
- return arg.evaluate(context);
5129
+ return arg.evaluate(context2);
5130
5130
  });
5131
- var result = func.apply(this, [].concat(context, args));
5131
+ var result = func.apply(this, [].concat(context2, args));
5132
5132
  return convertValue(result);
5133
5133
  };
5134
5134
  }
@@ -5193,22 +5193,22 @@ var require_xpath = __commonJS({
5193
5193
  }
5194
5194
  }
5195
5195
  function makeContext(options) {
5196
- var context = new XPathContext();
5196
+ var context2 = new XPathContext();
5197
5197
  if (options) {
5198
- context.namespaceResolver = makeNSResolver(options.namespaces);
5199
- context.functionResolver = makeFunctionResolver(options.functions);
5200
- context.variableResolver = makeVariableResolver(options.variables);
5201
- context.expressionContextNode = options.node;
5202
- copyIfPresent("allowAnyNamespaceForNoPrefix", context, options);
5203
- copyIfPresent("isHtml", context, options);
5198
+ context2.namespaceResolver = makeNSResolver(options.namespaces);
5199
+ context2.functionResolver = makeFunctionResolver(options.functions);
5200
+ context2.variableResolver = makeVariableResolver(options.variables);
5201
+ context2.expressionContextNode = options.node;
5202
+ copyIfPresent("allowAnyNamespaceForNoPrefix", context2, options);
5203
+ copyIfPresent("isHtml", context2, options);
5204
5204
  } else {
5205
- context.namespaceResolver = defaultNSResolver;
5205
+ context2.namespaceResolver = defaultNSResolver;
5206
5206
  }
5207
- return context;
5207
+ return context2;
5208
5208
  }
5209
5209
  function evaluate(parsedExpression, options) {
5210
- var context = makeContext(options);
5211
- return parsedExpression.evaluate(context);
5210
+ var context2 = makeContext(options);
5211
+ return parsedExpression.evaluate(context2);
5212
5212
  }
5213
5213
  var evaluatorPrototype = {
5214
5214
  evaluate: function(options) {
@@ -7227,8 +7227,8 @@ var require_dom = __commonJS({
7227
7227
  }
7228
7228
  });
7229
7229
  }
7230
- function walkDOM(node, context, callbacks) {
7231
- var stack = [{ node, context, phase: walkDOM.ENTER }];
7230
+ function walkDOM(node, context2, callbacks) {
7231
+ var stack = [{ node, context: context2, phase: walkDOM.ENTER }];
7232
7232
  while (stack.length > 0) {
7233
7233
  var frame = stack.pop();
7234
7234
  if (frame.phase === walkDOM.ENTER) {
@@ -13203,21 +13203,21 @@ var require_lib2 = __commonJS({
13203
13203
  function getExportedToken(token) {
13204
13204
  return tokenTypes[token];
13205
13205
  }
13206
- tokenTypes[8].updateContext = (context) => {
13207
- context.pop();
13206
+ tokenTypes[8].updateContext = (context2) => {
13207
+ context2.pop();
13208
13208
  };
13209
- tokenTypes[5].updateContext = tokenTypes[7].updateContext = tokenTypes[23].updateContext = (context) => {
13210
- context.push(types.brace);
13209
+ tokenTypes[5].updateContext = tokenTypes[7].updateContext = tokenTypes[23].updateContext = (context2) => {
13210
+ context2.push(types.brace);
13211
13211
  };
13212
- tokenTypes[22].updateContext = (context) => {
13213
- if (context[context.length - 1] === types.template) {
13214
- context.pop();
13212
+ tokenTypes[22].updateContext = (context2) => {
13213
+ if (context2[context2.length - 1] === types.template) {
13214
+ context2.pop();
13215
13215
  } else {
13216
- context.push(types.template);
13216
+ context2.push(types.template);
13217
13217
  }
13218
13218
  };
13219
- tokenTypes[143].updateContext = (context) => {
13220
- context.push(types.j_expr, types.j_oTag);
13219
+ tokenTypes[143].updateContext = (context2) => {
13220
+ context2.push(types.j_expr, types.j_oTag);
13221
13221
  };
13222
13222
  var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088F\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5C\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDC-\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C8A\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7DC\uA7F1-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC";
13223
13223
  var nonASCIIidentifierChars = "\xB7\u0300-\u036F\u0387\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u0897-\u089F\u08CA-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C04\u0C3C\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0CF3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D81-\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EBC\u0EC8-\u0ECE\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u180F-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19D0-\u19DA\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1ABF-\u1ADD\u1AE0-\u1AEB\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DFF\u200C\u200D\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\u30FB\uA620-\uA629\uA66F\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA82C\uA880\uA881\uA8B4-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F1\uA8FF-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F\uFF65";
@@ -15292,11 +15292,11 @@ var require_lib2 = __commonJS({
15292
15292
  jsx2 = this.tryParse(() => super.parseMaybeAssign(refExpressionErrors, afterLeftParse), state);
15293
15293
  if (!jsx2.error) return jsx2.node;
15294
15294
  const {
15295
- context
15295
+ context: context2
15296
15296
  } = this.state;
15297
- const currentContext = context[context.length - 1];
15297
+ const currentContext = context2[context2.length - 1];
15298
15298
  if (currentContext === types.j_oTag || currentContext === types.j_expr) {
15299
- context.pop();
15299
+ context2.pop();
15300
15300
  }
15301
15301
  }
15302
15302
  if ((_jsx = jsx2) != null && _jsx.error || this.match(47)) {
@@ -15608,15 +15608,15 @@ var require_lib2 = __commonJS({
15608
15608
  init
15609
15609
  };
15610
15610
  }
15611
- flowEnumCheckExplicitTypeMismatch(loc, context, expectedType) {
15611
+ flowEnumCheckExplicitTypeMismatch(loc, context2, expectedType) {
15612
15612
  const {
15613
15613
  explicitType
15614
- } = context;
15614
+ } = context2;
15615
15615
  if (explicitType === null) {
15616
15616
  return;
15617
15617
  }
15618
15618
  if (explicitType !== expectedType) {
15619
- this.flowEnumErrorInvalidMemberInitializer(loc, context);
15619
+ this.flowEnumErrorInvalidMemberInitializer(loc, context2);
15620
15620
  }
15621
15621
  }
15622
15622
  flowEnumMembers({
@@ -15659,7 +15659,7 @@ var require_lib2 = __commonJS({
15659
15659
  });
15660
15660
  }
15661
15661
  seenNames.add(memberName);
15662
- const context = {
15662
+ const context2 = {
15663
15663
  enumName,
15664
15664
  explicitType,
15665
15665
  memberName
@@ -15667,33 +15667,33 @@ var require_lib2 = __commonJS({
15667
15667
  memberNode.id = id;
15668
15668
  switch (init.type) {
15669
15669
  case "boolean": {
15670
- this.flowEnumCheckExplicitTypeMismatch(init.loc, context, "boolean");
15670
+ this.flowEnumCheckExplicitTypeMismatch(init.loc, context2, "boolean");
15671
15671
  memberNode.init = init.value;
15672
15672
  members.booleanMembers.push(this.finishNode(memberNode, "EnumBooleanMember"));
15673
15673
  break;
15674
15674
  }
15675
15675
  case "number": {
15676
- this.flowEnumCheckExplicitTypeMismatch(init.loc, context, "number");
15676
+ this.flowEnumCheckExplicitTypeMismatch(init.loc, context2, "number");
15677
15677
  memberNode.init = init.value;
15678
15678
  members.numberMembers.push(this.finishNode(memberNode, "EnumNumberMember"));
15679
15679
  break;
15680
15680
  }
15681
15681
  case "string": {
15682
- this.flowEnumCheckExplicitTypeMismatch(init.loc, context, "string");
15682
+ this.flowEnumCheckExplicitTypeMismatch(init.loc, context2, "string");
15683
15683
  memberNode.init = init.value;
15684
15684
  members.stringMembers.push(this.finishNode(memberNode, "EnumStringMember"));
15685
15685
  break;
15686
15686
  }
15687
15687
  case "invalid": {
15688
- throw this.flowEnumErrorInvalidMemberInitializer(init.loc, context);
15688
+ throw this.flowEnumErrorInvalidMemberInitializer(init.loc, context2);
15689
15689
  }
15690
15690
  case "none": {
15691
15691
  switch (explicitType) {
15692
15692
  case "boolean":
15693
- this.flowEnumErrorBooleanMemberNotInitialized(init.loc, context);
15693
+ this.flowEnumErrorBooleanMemberNotInitialized(init.loc, context2);
15694
15694
  break;
15695
15695
  case "number":
15696
- this.flowEnumErrorNumberMemberNotInitialized(init.loc, context);
15696
+ this.flowEnumErrorNumberMemberNotInitialized(init.loc, context2);
15697
15697
  break;
15698
15698
  default:
15699
15699
  members.defaultedMembers.push(this.finishNode(memberNode, "EnumDefaultedMember"));
@@ -16534,9 +16534,9 @@ var require_lib2 = __commonJS({
16534
16534
  }
16535
16535
  setContext(newContext) {
16536
16536
  const {
16537
- context
16537
+ context: context2
16538
16538
  } = this.state;
16539
- context[context.length - 1] = newContext;
16539
+ context2[context2.length - 1] = newContext;
16540
16540
  }
16541
16541
  parseExprAtom(refExpressionErrors) {
16542
16542
  if (this.match(143)) {
@@ -16553,12 +16553,12 @@ var require_lib2 = __commonJS({
16553
16553
  if (!curContext.preserveSpace) super.skipSpace();
16554
16554
  }
16555
16555
  getTokenFromCode(code2) {
16556
- const context = this.curContext();
16557
- if (context === types.j_expr) {
16556
+ const context2 = this.curContext();
16557
+ if (context2 === types.j_expr) {
16558
16558
  this.jsxReadToken();
16559
16559
  return;
16560
16560
  }
16561
- if (context === types.j_oTag || context === types.j_cTag) {
16561
+ if (context2 === types.j_oTag || context2 === types.j_cTag) {
16562
16562
  if (isIdentifierStart(code2)) {
16563
16563
  this.jsxReadWord();
16564
16564
  return;
@@ -16568,7 +16568,7 @@ var require_lib2 = __commonJS({
16568
16568
  this.finishToken(144);
16569
16569
  return;
16570
16570
  }
16571
- if ((code2 === 34 || code2 === 39) && context === types.j_oTag) {
16571
+ if ((code2 === 34 || code2 === 39) && context2 === types.j_oTag) {
16572
16572
  this.jsxReadString(code2);
16573
16573
  return;
16574
16574
  }
@@ -16582,19 +16582,19 @@ var require_lib2 = __commonJS({
16582
16582
  }
16583
16583
  updateContext(prevType) {
16584
16584
  const {
16585
- context,
16585
+ context: context2,
16586
16586
  type
16587
16587
  } = this.state;
16588
16588
  if (type === 56 && prevType === 143) {
16589
- context.splice(-2, 2, types.j_cTag);
16589
+ context2.splice(-2, 2, types.j_cTag);
16590
16590
  this.state.canStartJSXElement = false;
16591
16591
  } else if (type === 143) {
16592
- context.push(types.j_oTag);
16592
+ context2.push(types.j_oTag);
16593
16593
  } else if (type === 144) {
16594
- const out = context[context.length - 1];
16594
+ const out = context2[context2.length - 1];
16595
16595
  if (out === types.j_oTag && prevType === 56 || out === types.j_cTag) {
16596
- context.pop();
16597
- this.state.canStartJSXElement = context[context.length - 1] === types.j_expr;
16596
+ context2.pop();
16597
+ this.state.canStartJSXElement = context2[context2.length - 1] === types.j_expr;
16598
16598
  } else {
16599
16599
  this.setContext(types.j_expr);
16600
16600
  this.state.canStartJSXElement = true;
@@ -21560,11 +21560,11 @@ var require_lib2 = __commonJS({
21560
21560
  jsx2 = this.tryParse(() => super.parseMaybeAssign(refExpressionErrors, afterLeftParse), state);
21561
21561
  if (!jsx2.error) return jsx2.node;
21562
21562
  const {
21563
- context
21563
+ context: context2
21564
21564
  } = this.state;
21565
- const currentContext = context[context.length - 1];
21565
+ const currentContext = context2[context2.length - 1];
21566
21566
  if (currentContext === types.j_oTag || currentContext === types.j_expr) {
21567
- context.pop();
21567
+ context2.pop();
21568
21568
  }
21569
21569
  }
21570
21570
  if (!((_jsx = jsx2) != null && _jsx.error) && !this.match(47)) {
@@ -26360,36 +26360,125 @@ var require_lib2 = __commonJS({
26360
26360
  }
26361
26361
  });
26362
26362
 
26363
+ // src/api.ts
26364
+ import { randomUUID as randomUUID2 } from "crypto";
26365
+
26363
26366
  // src/config.ts
26367
+ import { randomUUID } from "crypto";
26364
26368
  import {
26365
26369
  chmodSync,
26366
26370
  mkdirSync,
26367
26371
  readFileSync,
26372
+ renameSync,
26368
26373
  rmSync,
26369
26374
  writeFileSync
26370
26375
  } from "fs";
26371
26376
  import { homedir } from "os";
26372
26377
  import { join } from "path";
26378
+ import { lock } from "proper-lockfile";
26379
+ var sessionSchema = external_exports.object({
26380
+ refreshToken: external_exports.string(),
26381
+ organizationId: external_exports.string(),
26382
+ apiBaseUrl: external_exports.string(),
26383
+ identityId: external_exports.string().optional(),
26384
+ email: external_exports.string().optional(),
26385
+ accessToken: external_exports.string().optional(),
26386
+ accessTokenExpiresAt: external_exports.number().optional()
26387
+ });
26388
+ var storeSchema = external_exports.object({
26389
+ version: external_exports.literal(2),
26390
+ generation: external_exports.number().default(0),
26391
+ defaultApiBaseUrl: external_exports.string().optional(),
26392
+ deployments: external_exports.record(
26393
+ external_exports.string(),
26394
+ external_exports.object({
26395
+ defaultOrgId: external_exports.string().optional(),
26396
+ appBaseUrl: external_exports.string().optional(),
26397
+ signedOut: external_exports.record(external_exports.string(), external_exports.number()).default({}),
26398
+ sessions: external_exports.record(external_exports.string(), sessionSchema),
26399
+ // Persist before requesting a session so a lost response can be retried.
26400
+ pending: external_exports.record(
26401
+ external_exports.string(),
26402
+ external_exports.object({
26403
+ sourceOrgId: external_exports.string(),
26404
+ sourceSessionId: external_exports.string(),
26405
+ sourceRefreshToken: external_exports.string(),
26406
+ requestId: external_exports.string()
26407
+ })
26408
+ ).default({})
26409
+ })
26410
+ )
26411
+ });
26373
26412
  var configDir = join(homedir(), ".overai");
26374
26413
  var configFilePath = join(configDir, "config.json");
26375
- var readConfig = () => {
26414
+ var readStore = () => {
26415
+ const raw2 = (() => {
26416
+ try {
26417
+ return readFileSync(configFilePath, "utf8");
26418
+ } catch (error) {
26419
+ if (error.code === "ENOENT") return null;
26420
+ throw error;
26421
+ }
26422
+ })();
26423
+ if (raw2 == null) return { version: 2, generation: 0, deployments: {} };
26424
+ const invalidStoreMessage = `Invalid credential store at ${configFilePath}. Restore a valid copy before continuing.`;
26425
+ const [value, parseError] = resultOfSync(() => JSON.parse(raw2));
26426
+ if (parseError != null) throw new Error(invalidStoreMessage);
26427
+ const current = storeSchema.safeParse(value);
26428
+ if (current.success) return current.data;
26429
+ const legacy = sessionSchema.safeParse(value);
26430
+ if (!legacy.success)
26431
+ throw new Error(invalidStoreMessage);
26432
+ const session = legacy.data;
26433
+ session.apiBaseUrl = session.apiBaseUrl.replace(/\/+$/, "");
26434
+ return {
26435
+ version: 2,
26436
+ generation: 0,
26437
+ defaultApiBaseUrl: session.apiBaseUrl,
26438
+ deployments: {
26439
+ [session.apiBaseUrl]: {
26440
+ defaultOrgId: session.organizationId,
26441
+ sessions: { [session.organizationId]: session },
26442
+ pending: {},
26443
+ signedOut: {}
26444
+ }
26445
+ }
26446
+ };
26447
+ };
26448
+ var writeStore = (store) => {
26449
+ const temporary = `${configFilePath}.${randomUUID()}.tmp`;
26376
26450
  try {
26377
- return JSON.parse(readFileSync(configFilePath, "utf8"));
26378
- } catch {
26379
- return null;
26451
+ writeFileSync(temporary, `${JSON.stringify(store, null, 2)}
26452
+ `, {
26453
+ mode: 384,
26454
+ flag: "wx"
26455
+ });
26456
+ renameSync(temporary, configFilePath);
26457
+ } finally {
26458
+ rmSync(temporary, { force: true });
26380
26459
  }
26381
26460
  };
26382
- var writeConfig = (config) => {
26383
- mkdirSync(configDir, { recursive: true });
26461
+ var withStoreLock = async (run2) => {
26462
+ mkdirSync(configDir, { recursive: true, mode: 448 });
26384
26463
  chmodSync(configDir, 448);
26385
- writeFileSync(configFilePath, `${JSON.stringify(config, null, 2)}
26386
- `, {
26387
- mode: 384
26464
+ const release = await lock(configFilePath, {
26465
+ realpath: false,
26466
+ stale: 6e4,
26467
+ retries: { retries: 120, minTimeout: 250, maxTimeout: 1e3, factor: 1.2 }
26388
26468
  });
26389
- chmodSync(configFilePath, 384);
26469
+ try {
26470
+ return await run2(readStore());
26471
+ } finally {
26472
+ await release();
26473
+ }
26390
26474
  };
26391
- var clearConfig = () => {
26392
- rmSync(configFilePath, { force: true });
26475
+
26476
+ // ../common/src/cluster.ts
26477
+ var API_HOST_REGEX = /^api\.((?:[a-z]+\.)?(?:perygee|overai)\.com)$/;
26478
+ var appBaseUrlFromApiHost = (apiHost) => {
26479
+ const match = API_HOST_REGEX.exec(apiHost);
26480
+ if (!match) return null;
26481
+ return `https://app.${match[1] ?? ""}`;
26393
26482
  };
26394
26483
 
26395
26484
  // src/env.ts
@@ -26397,16 +26486,35 @@ var trimSlash = (url) => url.replace(/\/+$/, "");
26397
26486
  var DEFAULT_API_BASE_URL = "https://api.overai.com";
26398
26487
  var apiBaseUrlOverride = process.env.OVERAI_API_URL != null ? trimSlash(process.env.OVERAI_API_URL) : void 0;
26399
26488
  var orgIdOverride = process.env.OVERAI_ORG_ID != null && process.env.OVERAI_ORG_ID !== "" ? process.env.OVERAI_ORG_ID : void 0;
26400
- var appBaseUrl = trimSlash(
26401
- process.env.OVERAI_APP_URL ?? "https://app.overai.com"
26402
- );
26489
+ var appBaseUrl = (backend) => {
26490
+ const saved = readStore();
26491
+ return trimSlash(
26492
+ process.env.OVERAI_APP_URL ?? saved.deployments[backend]?.appBaseUrl ?? appBaseUrlFromApiHost(new URL(backend).host) ?? (new URL(backend).hostname === "localhost" || new URL(backend).hostname === "127.0.0.1" ? `${new URL(backend).protocol}//${new URL(backend).hostname}:3000` : "")
26493
+ );
26494
+ };
26495
+
26496
+ // ../common/src/stdlib/omit.ts
26497
+ var omit = (obj, ...keys) => {
26498
+ const result = { ...obj };
26499
+ keys.forEach((key) => delete result[key]);
26500
+ return result;
26501
+ };
26403
26502
 
26404
26503
  // src/api.ts
26405
- var apiBaseUrl = () => apiBaseUrlOverride ?? readConfig()?.apiBaseUrl ?? DEFAULT_API_BASE_URL;
26504
+ var commandApiBaseUrl;
26505
+ var apiBaseUrl = () => commandApiBaseUrl ??= apiBaseUrlOverride ?? readStore().defaultApiBaseUrl ?? DEFAULT_API_BASE_URL;
26506
+ var AuthRpcError = class extends Error {
26507
+ constructor(status, message) {
26508
+ super(message);
26509
+ this.status = status;
26510
+ }
26511
+ status;
26512
+ };
26406
26513
  var trpcResult = async (res, procedure) => {
26407
26514
  const body = await res.json().catch(() => null);
26408
26515
  if (body != null && "error" in body) {
26409
- throw new Error(
26516
+ throw new AuthRpcError(
26517
+ res.status,
26410
26518
  body.error.message || `${procedure} failed (${String(res.status)})`
26411
26519
  );
26412
26520
  }
@@ -26415,13 +26523,14 @@ var trpcResult = async (res, procedure) => {
26415
26523
  }
26416
26524
  return body.result.data;
26417
26525
  };
26418
- var trpcMutation = async (procedure, input) => {
26526
+ var trpcMutation = async (procedure, input, baseUrl = apiBaseUrl()) => {
26419
26527
  const res = await fetch(
26420
- `${apiBaseUrl()}/v1/utils/trpc/unauthenticated/${procedure}`,
26528
+ `${baseUrl}/v1/utils/trpc/unauthenticated/${procedure}`,
26421
26529
  {
26422
26530
  method: "POST",
26423
26531
  headers: { "Content-Type": "application/json" },
26424
- body: JSON.stringify(input)
26532
+ body: JSON.stringify(input),
26533
+ signal: AbortSignal.timeout(3e4)
26425
26534
  }
26426
26535
  );
26427
26536
  return trpcResult(res, procedure);
@@ -26431,7 +26540,18 @@ var exchangeSessionToken = (refreshToken, destinationOrgId) => trpcMutation("exc
26431
26540
  refreshToken,
26432
26541
  destinationOrgId
26433
26542
  });
26434
- var signOutHeadless = (refreshToken) => trpcMutation("signOutHeadless", { refreshToken });
26543
+ var signOutHeadless = (refreshToken, baseUrl = apiBaseUrl()) => trpcMutation(
26544
+ "signOutHeadless",
26545
+ { refreshToken },
26546
+ baseUrl
26547
+ );
26548
+ var cancelCliOrgSession = (sourceSessionId, sourceRefreshToken, destinationOrgId, requestId, backend = apiBaseUrl()) => trpcMutation(
26549
+ "cancelCliOrgSession",
26550
+ { sourceSessionId, sourceRefreshToken, destinationOrgId, requestId },
26551
+ backend
26552
+ );
26553
+ var InteractiveSignInRequired = class extends Error {
26554
+ };
26435
26555
  var decodeJwtClaims = (token) => {
26436
26556
  const payload = token.split(".")[1];
26437
26557
  if (payload == null) return {};
@@ -26442,66 +26562,183 @@ var decodeJwtClaims = (token) => {
26442
26562
  }
26443
26563
  };
26444
26564
  var orgScopeOverride = null;
26565
+ var commandContext;
26445
26566
  var setOrgScope = (organizationId) => {
26567
+ if (commandContext != null && commandContext.organizationId !== organizationId) {
26568
+ throw new Error("Cannot change organization after a command has started.");
26569
+ }
26446
26570
  orgScopeOverride = organizationId;
26447
26571
  };
26448
- var resolveOrgId = (config) => orgIdOverride ?? orgScopeOverride ?? config.organizationId;
26572
+ var context = () => {
26573
+ if (commandContext != null) return commandContext;
26574
+ const store = readStore();
26575
+ const deployment = store.deployments[apiBaseUrl()];
26576
+ const organizationId = orgIdOverride ?? orgScopeOverride ?? deployment?.defaultOrgId;
26577
+ if (organizationId == null)
26578
+ throw new InteractiveSignInRequired("Not signed in. Run `overai signin`.");
26579
+ const session = deployment?.sessions[organizationId] ?? Object.values(deployment?.sessions ?? {})[0];
26580
+ commandContext = {
26581
+ organizationId,
26582
+ identityId: session?.identityId ?? (session?.accessToken == null ? void 0 : decodeJwtClaims(session.accessToken).user_id),
26583
+ email: session?.email,
26584
+ hadSession: deployment?.sessions[organizationId] != null,
26585
+ signedOut: deployment?.signedOut[organizationId] ?? 0,
26586
+ generation: store.generation
26587
+ };
26588
+ return commandContext;
26589
+ };
26449
26590
  var scopedOrgId = () => {
26450
- const config = readConfig();
26451
- return config == null ? null : resolveOrgId(config);
26591
+ try {
26592
+ return context().organizationId;
26593
+ } catch {
26594
+ return null;
26595
+ }
26452
26596
  };
26453
26597
  var announceOrgScope = () => {
26454
- const config = readConfig();
26455
- if (config == null) return;
26456
- const targetOrgId = resolveOrgId(config);
26457
- if (targetOrgId === config.organizationId) return;
26598
+ const org = scopedOrgId();
26599
+ if (org == null) return;
26458
26600
  process.stderr.write(
26459
- `Using org ${targetOrgId} (${orgIdOverride != null ? "OVERAI_ORG_ID" : ".overai/manifest.json"}); the active org is ${config.organizationId}.
26601
+ `Using org ${org} (${orgIdOverride != null ? "OVERAI_ORG_ID" : orgScopeOverride != null ? ".overai/manifest.json" : "saved default"}).
26460
26602
  `
26461
26603
  );
26462
26604
  };
26463
- var inFlightExchange = null;
26464
- var processToken = null;
26465
26605
  var getAccessToken = async () => {
26466
- const config = readConfig();
26467
- if (config == null) {
26468
- throw new Error("Not signed in. Run `overai signin`.");
26469
- }
26470
- const targetOrgId = resolveOrgId(config);
26471
- const skewMs = 6e4;
26472
- if (targetOrgId === config.organizationId && config.accessToken != null && config.accessTokenExpiresAt != null && config.accessTokenExpiresAt - skewMs > Date.now()) {
26473
- return { token: config.accessToken, organizationId: config.organizationId };
26474
- }
26475
- if (processToken?.organizationId === targetOrgId && processToken.expiresAt - skewMs > Date.now()) {
26476
- return { token: processToken.token, organizationId: targetOrgId };
26477
- }
26478
- inFlightExchange ??= (async () => {
26479
- const result = await exchangeSessionToken(config.refreshToken, targetOrgId);
26480
- if (result.type === "redirect") {
26606
+ const target = context();
26607
+ const baseUrl = apiBaseUrl();
26608
+ return withStoreLock(async (store) => {
26609
+ if (store.generation !== target.generation)
26481
26610
  throw new Error(
26482
- targetOrgId === config.organizationId ? "Your session expired. Run `overai signin`." : `Org ${targetOrgId} requires interactive sign-in (SSO). Run \`overai org switch ${targetOrgId}\`.`
26611
+ "All CLI sessions were signed out in another process. Run the command again."
26483
26612
  );
26613
+ const deployment = store.deployments[baseUrl];
26614
+ const signin = `Run OVERAI_ORG_ID=${target.organizationId} overai signin.`;
26615
+ if (deployment == null) throw new InteractiveSignInRequired(signin);
26616
+ if ((deployment.signedOut[target.organizationId] ?? 0) !== target.signedOut)
26617
+ throw new Error(`This org was signed out in another process. ${signin}`);
26618
+ const existing = deployment.sessions[target.organizationId];
26619
+ if (target.hadSession && existing == null)
26620
+ throw new Error(`This org was signed out in another process. ${signin}`);
26621
+ const sources = existing == null ? Object.values(deployment.sessions) : [existing];
26622
+ if (sources.length === 0) throw new InteractiveSignInRequired(signin);
26623
+ if (sources.some(
26624
+ (session) => target.identityId != null && (session.identityId ?? (session.accessToken == null ? void 0 : decodeJwtClaims(session.accessToken).user_id)) !== target.identityId || target.email != null && session.email !== target.email
26625
+ )) {
26626
+ throw new Error("The signed-in identity changed. Run the command again.");
26627
+ }
26628
+ if (existing?.accessToken != null && (existing.accessTokenExpiresAt ?? 0) > Date.now() + 6e4) {
26629
+ writeStore(store);
26630
+ return {
26631
+ token: existing.accessToken,
26632
+ organizationId: target.organizationId
26633
+ };
26484
26634
  }
26485
- const forActiveOrg = targetOrgId === config.organizationId;
26486
- writeConfig({
26487
- ...config,
26488
- email: decodeJwtClaims(result.token).email ?? config.email,
26635
+ const result = await (async () => {
26636
+ if (existing != null) {
26637
+ return exchangeSessionToken(existing.refreshToken, null).catch(
26638
+ (error) => {
26639
+ if (error instanceof AuthRpcError && (error.status === 400 || error.status === 401))
26640
+ throw new InteractiveSignInRequired(
26641
+ `Session expired or revoked. ${signin}`
26642
+ );
26643
+ throw error;
26644
+ }
26645
+ );
26646
+ }
26647
+ const pending = deployment.pending[target.organizationId];
26648
+ const candidates = [...sources].sort(
26649
+ (a, b) => Number(b.organizationId === pending?.sourceOrgId) - Number(a.organizationId === pending?.sourceOrgId)
26650
+ );
26651
+ for (const source of candidates) {
26652
+ if (source.accessToken == null || decodeJwtClaims(source.accessToken).sid == null) {
26653
+ const refreshed = await exchangeSessionToken(
26654
+ source.refreshToken,
26655
+ null
26656
+ ).catch((error) => {
26657
+ if (error instanceof AuthRpcError && (error.status === 400 || error.status === 401))
26658
+ return null;
26659
+ throw error;
26660
+ });
26661
+ if (refreshed?.type !== "success") {
26662
+ if (pending?.sourceOrgId === source.organizationId) {
26663
+ await cancelCliOrgSession(
26664
+ pending.sourceSessionId,
26665
+ pending.sourceRefreshToken,
26666
+ target.organizationId,
26667
+ pending.requestId
26668
+ );
26669
+ deployment.pending = omit(
26670
+ deployment.pending,
26671
+ target.organizationId
26672
+ );
26673
+ writeStore(store);
26674
+ }
26675
+ continue;
26676
+ }
26677
+ source.refreshToken = refreshed.refreshToken;
26678
+ source.accessToken = refreshed.token;
26679
+ source.accessTokenExpiresAt = Date.now() + refreshed.accessTokenValiditySeconds * 1e3;
26680
+ writeStore(store);
26681
+ }
26682
+ const sourceSessionId = decodeJwtClaims(source.accessToken).sid;
26683
+ if (sourceSessionId == null || sourceSessionId === "")
26684
+ throw new InteractiveSignInRequired(signin);
26685
+ const operation = pending?.sourceOrgId === source.organizationId ? { ...pending, sourceRefreshToken: source.refreshToken } : {
26686
+ sourceOrgId: source.organizationId,
26687
+ sourceSessionId,
26688
+ sourceRefreshToken: source.refreshToken,
26689
+ requestId: randomUUID2()
26690
+ };
26691
+ deployment.pending[target.organizationId] = operation;
26692
+ writeStore(store);
26693
+ const response = await trpcMutation(
26694
+ "establishCliOrgSession",
26695
+ {
26696
+ refreshToken: source.refreshToken,
26697
+ destinationOrgId: target.organizationId,
26698
+ requestId: operation.requestId
26699
+ }
26700
+ ).catch((error) => {
26701
+ if (error instanceof AuthRpcError && error.status === 401)
26702
+ return null;
26703
+ throw new Error(
26704
+ `Could not establish an independent org session: ${error instanceof Error ? error.message : String(error)}. No legacy switch was attempted.`
26705
+ );
26706
+ });
26707
+ if (response?.type === "success") return response;
26708
+ await cancelCliOrgSession(
26709
+ operation.sourceSessionId,
26710
+ operation.sourceRefreshToken,
26711
+ target.organizationId,
26712
+ operation.requestId
26713
+ );
26714
+ deployment.pending = omit(deployment.pending, target.organizationId);
26715
+ writeStore(store);
26716
+ }
26717
+ throw new InteractiveSignInRequired(
26718
+ `Org ${target.organizationId} requires browser authorization. ${signin}`
26719
+ );
26720
+ })();
26721
+ if (result.type === "redirect") throw new InteractiveSignInRequired(signin);
26722
+ const claims = decodeJwtClaims(result.token);
26723
+ if (claims.org !== target.organizationId || target.identityId != null && claims.user_id !== target.identityId) {
26724
+ throw new Error(
26725
+ "The auth server returned a session for a different org or identity."
26726
+ );
26727
+ }
26728
+ deployment.sessions[target.organizationId] = {
26729
+ organizationId: target.organizationId,
26730
+ apiBaseUrl: baseUrl,
26731
+ identityId: claims.user_id,
26732
+ email: claims.email ?? target.email,
26489
26733
  refreshToken: result.refreshToken,
26490
- accessToken: forActiveOrg ? result.token : config.accessToken,
26491
- accessTokenExpiresAt: forActiveOrg ? Date.now() + result.accessTokenValiditySeconds * 1e3 : config.accessTokenExpiresAt
26492
- });
26493
- processToken = {
26494
- organizationId: targetOrgId,
26495
- token: result.token,
26496
- expiresAt: Date.now() + result.accessTokenValiditySeconds * 1e3
26734
+ accessToken: result.token,
26735
+ accessTokenExpiresAt: Date.now() + result.accessTokenValiditySeconds * 1e3
26497
26736
  };
26498
- return { token: result.token, organizationId: targetOrgId };
26499
- })();
26500
- try {
26501
- return await inFlightExchange;
26502
- } finally {
26503
- inFlightExchange = null;
26504
- }
26737
+ deployment.pending = omit(deployment.pending, target.organizationId);
26738
+ writeStore(store);
26739
+ target.hadSession = true;
26740
+ return { token: result.token, organizationId: target.organizationId };
26741
+ });
26505
26742
  };
26506
26743
  var v2Fetch = async (path, init) => {
26507
26744
  const auth = await getAccessToken();
@@ -26576,190 +26813,6 @@ var openBrowser = (url) => {
26576
26813
  }
26577
26814
  };
26578
26815
 
26579
- // src/args.ts
26580
- import { readFileSync as readFileSync2 } from "fs";
26581
- var flagValue = (args, ...names) => {
26582
- for (const name2 of names) {
26583
- const i = args.indexOf(name2);
26584
- if (i !== -1 && i + 1 < args.length) return args[i + 1];
26585
- }
26586
- return void 0;
26587
- };
26588
- var stdinClaimedBy = null;
26589
- var readStdin = async (claimant = "stdin") => {
26590
- if (stdinClaimedBy != null) {
26591
- throw new Error(
26592
- `Only one value can be read from stdin; ${stdinClaimedBy} already consumed it.`
26593
- );
26594
- }
26595
- stdinClaimedBy = claimant;
26596
- const chunks = [];
26597
- for await (const chunk of process.stdin) {
26598
- chunks.push(chunk);
26599
- }
26600
- return Buffer.concat(chunks).toString("utf8");
26601
- };
26602
- var readValue = async (value, label) => {
26603
- if (value?.startsWith("@") !== true) return value;
26604
- if (value.startsWith("@@")) return value.slice(1);
26605
- const path = value.slice(1);
26606
- if (path === "-") return (await readStdin(`${label} @-`)).trim();
26607
- try {
26608
- return readFileSync2(path, "utf8").trim();
26609
- } catch {
26610
- throw new Error(
26611
- `${label}: could not read file "${path}". Write "@@" to send a literal value starting with "@".`
26612
- );
26613
- }
26614
- };
26615
-
26616
- // src/gql.ts
26617
- var gqlRequest = async (query, variables) => {
26618
- const res = await v2Fetch("/v2/graphql", {
26619
- method: "POST",
26620
- headers: { "Content-Type": "application/json" },
26621
- body: JSON.stringify({ query, variables })
26622
- });
26623
- const raw2 = await res.text();
26624
- const body = (() => {
26625
- try {
26626
- return JSON.parse(raw2);
26627
- } catch {
26628
- return null;
26629
- }
26630
- })();
26631
- if (body?.errors != null && body.errors.length > 0) {
26632
- throw new Error(body.errors.map((e) => e.message).join("; "));
26633
- }
26634
- if (!res.ok) throw v2Error("graphql", res, raw2);
26635
- if (body?.data == null) {
26636
- throw new Error("graphql returned no data and no errors.");
26637
- }
26638
- return body.data;
26639
- };
26640
-
26641
- // src/output.ts
26642
- var resolveFormat = (explicit) => {
26643
- if (explicit === "json" || explicit === "csv" || explicit === "table") {
26644
- return explicit;
26645
- }
26646
- if (explicit != null) {
26647
- throw new Error(
26648
- `Unknown output format "${explicit}". Use json, table, or csv.`
26649
- );
26650
- }
26651
- return process.stdout.isTTY ? "table" : "json";
26652
- };
26653
- var cell = (value) => {
26654
- if (value == null) return "";
26655
- if (typeof value === "string") return value;
26656
- if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
26657
- return String(value);
26658
- }
26659
- return JSON.stringify(value);
26660
- };
26661
- var formatResult = (data, format2) => {
26662
- if (format2 === "json" || !Array.isArray(data)) {
26663
- return JSON.stringify(data, null, 2);
26664
- }
26665
- const records = data.map(
26666
- (row) => row != null && typeof row === "object" ? row : { value: row }
26667
- );
26668
- if (records.length === 0) return "(no rows)";
26669
- const columns = [...new Set(records.flatMap((r) => Object.keys(r)))];
26670
- if (format2 === "csv") {
26671
- const escape2 = (value) => {
26672
- const text = cell(value);
26673
- return /[",\n\r]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
26674
- };
26675
- return [
26676
- columns.join(","),
26677
- ...records.map((r) => columns.map((c) => escape2(r[c])).join(","))
26678
- ].join("\n");
26679
- }
26680
- const widths = columns.map(
26681
- (c) => Math.max(c.length, ...records.map((r) => cell(r[c]).length))
26682
- );
26683
- const line = (cells) => cells.map((text, i) => text.padEnd(widths[i] ?? 0)).join(" ");
26684
- return [
26685
- line(columns),
26686
- line(widths.map((w) => "-".repeat(w))),
26687
- ...records.map((r) => line(columns.map((c) => cell(r[c]))))
26688
- ].join("\n");
26689
- };
26690
- var printResult = (data, format2) => {
26691
- process.stdout.write(`${formatResult(data, format2)}
26692
- `);
26693
- };
26694
-
26695
- // src/commands/org.ts
26696
- var USER_ORGS_QUERY = `
26697
- query UserOrganizations($identityId: String!) {
26698
- identityOrganizations(condition: { identityId: $identityId }) {
26699
- nodes {
26700
- disabled
26701
- organization { id name }
26702
- }
26703
- }
26704
- }
26705
- `;
26706
- var fetchOrgNames = async () => {
26707
- const orgs = await listOrgRows();
26708
- return new Map(orgs.map((org) => [org.id, org.name ?? ""]));
26709
- };
26710
- var listOrgRows = async () => {
26711
- const auth = await getAccessToken();
26712
- const identityId = decodeJwtClaims(auth.token).user_id;
26713
- if (identityId == null) {
26714
- throw new Error("Could not read identity from the current session.");
26715
- }
26716
- const data = await gqlRequest(USER_ORGS_QUERY, { identityId });
26717
- return data.identityOrganizations.nodes.filter((node) => node != null && !node.disabled).map((node) => node?.organization).filter((org) => org != null);
26718
- };
26719
- var listOrgs = async (args) => {
26720
- const active = scopedOrgId();
26721
- printResult(
26722
- (await listOrgRows()).map((org) => ({
26723
- id: org.id,
26724
- name: org.name ?? "",
26725
- active: org.id === active
26726
- })),
26727
- resolveFormat(flagValue(args, "-o", "--output"))
26728
- );
26729
- };
26730
- var switchOrg = async (orgId) => {
26731
- const config = readConfig();
26732
- if (config == null) {
26733
- process.stderr.write("Not signed in. Run `overai signin`.\n");
26734
- process.exitCode = 1;
26735
- return;
26736
- }
26737
- const result = await exchangeSessionToken(config.refreshToken, orgId);
26738
- if (result.type === "redirect") {
26739
- process.stdout.write(
26740
- `This organization requires SSO. Complete sign-in in your browser, then run \`overai signin\`.
26741
- ${result.redirectUrl}
26742
- `
26743
- );
26744
- openBrowser(result.redirectUrl);
26745
- process.exitCode = 1;
26746
- return;
26747
- }
26748
- writeConfig({
26749
- ...config,
26750
- organizationId: orgId,
26751
- email: decodeJwtClaims(result.token).email ?? config.email,
26752
- accessToken: result.token,
26753
- accessTokenExpiresAt: Date.now() + result.accessTokenValiditySeconds * 1e3,
26754
- refreshToken: result.refreshToken
26755
- });
26756
- process.stdout.write(
26757
- `Switched to org ${orgId}.
26758
- This is machine-global \u2014 every shell and editor session on this machine now uses it. Prefix a command with OVERAI_ORG_ID=<orgId> to scope just one.
26759
- `
26760
- );
26761
- };
26762
-
26763
26816
  // src/pkce.ts
26764
26817
  import { createHash, randomBytes } from "crypto";
26765
26818
  var createPkcePair = () => {
@@ -26769,7 +26822,7 @@ var createPkcePair = () => {
26769
26822
  };
26770
26823
 
26771
26824
  // src/workspace/manifest.ts
26772
- import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
26825
+ import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
26773
26826
  import { dirname, join as join2, resolve } from "path";
26774
26827
  var MANIFEST_DIR = ".overai";
26775
26828
  var MANIFEST_FILE = "manifest.json";
@@ -26788,11 +26841,16 @@ var findWorkspaceRoot = (from = process.cwd()) => {
26788
26841
  }
26789
26842
  };
26790
26843
  var readManifest = (root) => JSON.parse(
26791
- readFileSync3(join2(root, MANIFEST_DIR, MANIFEST_FILE), "utf8")
26844
+ readFileSync2(join2(root, MANIFEST_DIR, MANIFEST_FILE), "utf8")
26792
26845
  );
26793
26846
  var openClone = () => {
26794
26847
  const root = findWorkspaceRoot();
26795
26848
  const manifest = readManifest(root);
26849
+ if (orgIdOverride != null && orgIdOverride !== manifest.organizationId) {
26850
+ throw new Error(
26851
+ `OVERAI_ORG_ID=${orgIdOverride} conflicts with this clone's org ${manifest.organizationId}. Unset it before syncing.`
26852
+ );
26853
+ }
26796
26854
  setOrgScope(manifest.organizationId);
26797
26855
  return { root, manifest };
26798
26856
  };
@@ -26819,14 +26877,14 @@ var writeSynced = (root, relPath, content) => {
26819
26877
  };
26820
26878
  var readWorkingFile = (root, relPath) => {
26821
26879
  try {
26822
- return readFileSync3(join2(root, relPath), "utf8");
26880
+ return readFileSync2(join2(root, relPath), "utf8");
26823
26881
  } catch {
26824
26882
  return null;
26825
26883
  }
26826
26884
  };
26827
26885
  var readBaseFile = (root, relPath) => {
26828
26886
  try {
26829
- return readFileSync3(basePath(root, relPath), "utf8");
26887
+ return readFileSync2(basePath(root, relPath), "utf8");
26830
26888
  } catch {
26831
26889
  return null;
26832
26890
  }
@@ -26913,16 +26971,23 @@ var startCallbackServer = (expectedState) => {
26913
26971
  });
26914
26972
  });
26915
26973
  };
26916
- var signIn = async () => {
26974
+ var signIn = async (requestedOrgId = orgIdOverride) => {
26975
+ const baseUrl = apiBaseUrl();
26976
+ const browserBaseUrl = appBaseUrl(baseUrl);
26977
+ if (browserBaseUrl === "")
26978
+ throw new Error("Set OVERAI_APP_URL for this backend before signing in.");
26979
+ const initialStore = readStore();
26917
26980
  const { verifier, challenge } = createPkcePair();
26918
26981
  const state = randomBytes2(16).toString("base64url");
26919
26982
  const { port, codePromise, close } = await startCallbackServer(state);
26920
- const authorizeUrl = `${appBaseUrl}/cli-auth?${new URLSearchParams({
26921
- redirect_uri: `http://127.0.0.1:${String(port)}`,
26922
- code_challenge: challenge,
26923
- state,
26924
- label: hostname()
26925
- }).toString()}`;
26983
+ const authorizeUrl = `${browserBaseUrl}${requestedOrgId == null ? "" : `/${encodeURIComponent(requestedOrgId)}`}/cli-auth?${new URLSearchParams(
26984
+ {
26985
+ redirect_uri: `http://127.0.0.1:${String(port)}`,
26986
+ code_challenge: challenge,
26987
+ state,
26988
+ label: hostname()
26989
+ }
26990
+ ).toString()}`;
26926
26991
  const autoOpen = process.env.OVERAI_NO_BROWSER == null;
26927
26992
  process.stdout.write(
26928
26993
  `${autoOpen ? "Opening your browser to authorize the CLI.\nIf it doesn't open, visit" : "Visit this URL to authorize the CLI"}:
@@ -26933,60 +26998,242 @@ ${authorizeUrl}
26933
26998
  try {
26934
26999
  const code = await codePromise;
26935
27000
  const session = await exchangeCliAuthCode(code, verifier);
26936
- const email = decodeJwtClaims(session.token).email;
26937
- writeConfig({
26938
- refreshToken: session.refreshToken,
26939
- organizationId: session.organizationId,
26940
- apiBaseUrl: apiBaseUrlOverride ?? DEFAULT_API_BASE_URL,
26941
- email,
26942
- accessToken: session.token,
26943
- accessTokenExpiresAt: Date.now() + session.accessTokenValiditySeconds * 1e3
26944
- });
27001
+ const claims = decodeJwtClaims(session.token);
27002
+ const email = claims.email;
27003
+ try {
27004
+ await withStoreLock(async (store) => {
27005
+ if (store.generation !== initialStore.generation || (store.deployments[baseUrl]?.signedOut[session.organizationId] ?? 0) !== (initialStore.deployments[baseUrl]?.signedOut[session.organizationId] ?? 0))
27006
+ throw new Error(
27007
+ "A sign-out occurred during authorization. Run signin again."
27008
+ );
27009
+ if (requestedOrgId != null && session.organizationId !== requestedOrgId)
27010
+ throw new Error(
27011
+ `Expected org ${requestedOrgId}; browser authorized ${session.organizationId}.`
27012
+ );
27013
+ const deployment = store.deployments[baseUrl] ??= {
27014
+ sessions: {},
27015
+ pending: {},
27016
+ signedOut: {}
27017
+ };
27018
+ if (Object.values(deployment.sessions).some((saved) => {
27019
+ const identityId = saved.identityId ?? (saved.accessToken == null ? void 0 : decodeJwtClaims(saved.accessToken).user_id);
27020
+ return identityId != null && identityId !== claims.user_id || saved.email != null && saved.email !== email;
27021
+ }))
27022
+ throw new Error(
27023
+ "Another identity is saved for this backend. Sign out of its sessions before changing accounts."
27024
+ );
27025
+ if (Object.entries(deployment.pending).some(
27026
+ ([id, pending]) => id === session.organizationId || pending.sourceOrgId === session.organizationId
27027
+ )) {
27028
+ throw new Error(
27029
+ "An org exchange is unfinished. Retry that org command or signout before replacing its source login."
27030
+ );
27031
+ }
27032
+ const previous = deployment.sessions[session.organizationId];
27033
+ if (previous != null) await signOutHeadless(previous.refreshToken);
27034
+ deployment.sessions[session.organizationId] = {
27035
+ refreshToken: session.refreshToken,
27036
+ organizationId: session.organizationId,
27037
+ apiBaseUrl: baseUrl,
27038
+ identityId: claims.user_id,
27039
+ email,
27040
+ accessToken: session.token,
27041
+ accessTokenExpiresAt: Date.now() + session.accessTokenValiditySeconds * 1e3
27042
+ };
27043
+ deployment.pending = omit(deployment.pending, session.organizationId);
27044
+ deployment.appBaseUrl = browserBaseUrl;
27045
+ deployment.defaultOrgId = session.organizationId;
27046
+ store.defaultApiBaseUrl = baseUrl;
27047
+ writeStore(store);
27048
+ });
27049
+ } catch (error) {
27050
+ await signOutHeadless(session.refreshToken).catch(() => void 0);
27051
+ throw error;
27052
+ }
26945
27053
  process.stdout.write(
26946
27054
  `Signed in${email != null ? ` as ${email}` : ""} (org ${session.organizationId}).
26947
27055
  `
26948
27056
  );
26949
- } finally {
26950
- close();
27057
+ } finally {
27058
+ close();
27059
+ }
27060
+ };
27061
+ var signOut = async (all = false) => {
27062
+ const root = (() => {
27063
+ try {
27064
+ return findWorkspaceRoot();
27065
+ } catch {
27066
+ return null;
27067
+ }
27068
+ })();
27069
+ if (root != null) setOrgScope(readManifest(root).organizationId);
27070
+ const baseUrl = apiBaseUrl();
27071
+ const orgId = scopedOrgId();
27072
+ await withStoreLock(async (store) => {
27073
+ const failures = [];
27074
+ if (!all && orgId != null) {
27075
+ const deployment = store.deployments[baseUrl] ??= {
27076
+ sessions: {},
27077
+ pending: {},
27078
+ signedOut: {}
27079
+ };
27080
+ deployment.signedOut[orgId] = (deployment.signedOut[orgId] ?? 0) + 1;
27081
+ }
27082
+ for (const [backend, deployment] of Object.entries(store.deployments)) {
27083
+ if (!all && backend !== baseUrl) continue;
27084
+ const blockedSources = /* @__PURE__ */ new Set();
27085
+ for (const [id, pending] of Object.entries(deployment.pending)) {
27086
+ if (!all && id !== orgId && pending.sourceOrgId !== orgId) continue;
27087
+ try {
27088
+ await cancelCliOrgSession(
27089
+ pending.sourceSessionId,
27090
+ pending.sourceRefreshToken,
27091
+ id,
27092
+ pending.requestId,
27093
+ backend
27094
+ );
27095
+ deployment.pending = omit(deployment.pending, id);
27096
+ writeStore(store);
27097
+ } catch {
27098
+ blockedSources.add(pending.sourceOrgId);
27099
+ failures.push(`${backend} pending org ${id}`);
27100
+ }
27101
+ }
27102
+ for (const [id, session] of Object.entries(deployment.sessions)) {
27103
+ if (!all && id !== orgId || blockedSources.has(id)) continue;
27104
+ try {
27105
+ await signOutHeadless(session.refreshToken, backend);
27106
+ deployment.sessions = omit(deployment.sessions, id);
27107
+ } catch {
27108
+ failures.push(`${backend} org ${id}`);
27109
+ }
27110
+ }
27111
+ if (deployment.defaultOrgId != null && deployment.sessions[deployment.defaultOrgId] == null) {
27112
+ delete deployment.defaultOrgId;
27113
+ }
27114
+ }
27115
+ if (all) store.generation += 1;
27116
+ writeStore(store);
27117
+ if (failures.length > 0)
27118
+ throw new Error(
27119
+ `Could not revoke ${failures.join(", ")}. Credentials retained; retry signout.`
27120
+ );
27121
+ });
27122
+ process.stdout.write(
27123
+ all ? "Signed out of all locally saved CLI sessions.\n" : `Signed out of org ${orgId ?? "(none selected)"}.
27124
+ `
27125
+ );
27126
+ };
27127
+ var whoami = () => {
27128
+ const root = (() => {
27129
+ try {
27130
+ return findWorkspaceRoot();
27131
+ } catch {
27132
+ return null;
27133
+ }
27134
+ })();
27135
+ if (root != null) setOrgScope(readManifest(root).organizationId);
27136
+ const org = scopedOrgId();
27137
+ const deployment = readStore().deployments[apiBaseUrl()];
27138
+ const session = org == null ? void 0 : deployment?.sessions[org];
27139
+ process.stdout.write(
27140
+ `Backend: ${apiBaseUrl()}
27141
+ Org: ${org ?? "none"}
27142
+ Selected by: ${orgIdOverride != null ? "OVERAI_ORG_ID" : root != null ? ".overai/manifest.json" : "saved default"}
27143
+ Identity: ${session?.email ?? session?.identityId ?? "no saved session for this org"}
27144
+ `
27145
+ );
27146
+ };
27147
+
27148
+ // src/args.ts
27149
+ import { readFileSync as readFileSync3 } from "fs";
27150
+ var flagValue = (args, ...names) => {
27151
+ for (const name2 of names) {
27152
+ const i = args.indexOf(name2);
27153
+ if (i !== -1 && i + 1 < args.length) return args[i + 1];
27154
+ }
27155
+ return void 0;
27156
+ };
27157
+ var stdinClaimedBy = null;
27158
+ var readStdin = async (claimant = "stdin") => {
27159
+ if (stdinClaimedBy != null) {
27160
+ throw new Error(
27161
+ `Only one value can be read from stdin; ${stdinClaimedBy} already consumed it.`
27162
+ );
27163
+ }
27164
+ stdinClaimedBy = claimant;
27165
+ const chunks = [];
27166
+ for await (const chunk of process.stdin) {
27167
+ chunks.push(chunk);
27168
+ }
27169
+ return Buffer.concat(chunks).toString("utf8");
27170
+ };
27171
+ var readValue = async (value, label) => {
27172
+ if (value?.startsWith("@") !== true) return value;
27173
+ if (value.startsWith("@@")) return value.slice(1);
27174
+ const path = value.slice(1);
27175
+ if (path === "-") return (await readStdin(`${label} @-`)).trim();
27176
+ try {
27177
+ return readFileSync3(path, "utf8").trim();
27178
+ } catch {
27179
+ throw new Error(
27180
+ `${label}: could not read file "${path}". Write "@@" to send a literal value starting with "@".`
27181
+ );
26951
27182
  }
26952
27183
  };
26953
- var signOut = async () => {
26954
- const config = readConfig();
26955
- if (config == null) {
26956
- process.stdout.write("Not signed in.\n");
26957
- return;
27184
+
27185
+ // src/output.ts
27186
+ var resolveFormat = (explicit) => {
27187
+ if (explicit === "json" || explicit === "csv" || explicit === "table") {
27188
+ return explicit;
27189
+ }
27190
+ if (explicit != null) {
27191
+ throw new Error(
27192
+ `Unknown output format "${explicit}". Use json, table, or csv.`
27193
+ );
26958
27194
  }
26959
- await signOutHeadless(config.refreshToken).catch(() => void 0);
26960
- clearConfig();
26961
- process.stdout.write("Signed out.\n");
27195
+ return process.stdout.isTTY ? "table" : "json";
26962
27196
  };
26963
- var whoami = async () => {
26964
- const config = readConfig();
26965
- if (config == null) {
26966
- process.stderr.write("Not signed in. Run `overai signin`.\n");
26967
- process.exitCode = 1;
26968
- return;
27197
+ var cell = (value) => {
27198
+ if (value == null) return "";
27199
+ if (typeof value === "string") return value;
27200
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
27201
+ return String(value);
26969
27202
  }
26970
- const cloneOrgId = (() => {
26971
- try {
26972
- return readManifest(findWorkspaceRoot()).organizationId;
26973
- } catch {
26974
- return null;
26975
- }
26976
- })();
26977
- const effective = orgIdOverride ?? cloneOrgId ?? config.organizationId;
26978
- const names = await fetchOrgNames().catch(() => null);
26979
- const label = (id) => names?.get(id) == null ? id : `${id} \u2014 ${String(names.get(id))}`;
26980
- process.stdout.write(
26981
- `Signed in${config.email != null ? ` as ${config.email}` : ""} (org ${label(effective)}).
26982
- `
27203
+ return JSON.stringify(value);
27204
+ };
27205
+ var formatResult = (data, format2) => {
27206
+ if (format2 === "json" || !Array.isArray(data)) {
27207
+ return JSON.stringify(data, null, 2);
27208
+ }
27209
+ const records = data.map(
27210
+ (row) => row != null && typeof row === "object" ? row : { value: row }
26983
27211
  );
26984
- if (effective !== config.organizationId) {
26985
- process.stdout.write(
26986
- `Scoped by ${orgIdOverride != null ? "OVERAI_ORG_ID" : ".overai/manifest.json"}; the machine-global active org is ${label(config.organizationId)}.
26987
- `
26988
- );
27212
+ if (records.length === 0) return "(no rows)";
27213
+ const columns = [...new Set(records.flatMap((r) => Object.keys(r)))];
27214
+ if (format2 === "csv") {
27215
+ const escape2 = (value) => {
27216
+ const text = cell(value);
27217
+ return /[",\n\r]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
27218
+ };
27219
+ return [
27220
+ columns.join(","),
27221
+ ...records.map((r) => columns.map((c) => escape2(r[c])).join(","))
27222
+ ].join("\n");
26989
27223
  }
27224
+ const widths = columns.map(
27225
+ (c) => Math.max(c.length, ...records.map((r) => cell(r[c]).length))
27226
+ );
27227
+ const line = (cells) => cells.map((text, i) => text.padEnd(widths[i] ?? 0)).join(" ");
27228
+ return [
27229
+ line(columns),
27230
+ line(widths.map((w) => "-".repeat(w))),
27231
+ ...records.map((r) => line(columns.map((c) => cell(r[c]))))
27232
+ ].join("\n");
27233
+ };
27234
+ var printResult = (data, format2) => {
27235
+ process.stdout.write(`${formatResult(data, format2)}
27236
+ `);
26990
27237
  };
26991
27238
 
26992
27239
  // src/commands/agent.ts
@@ -27007,6 +27254,31 @@ var runAgent = async (args) => {
27007
27254
  printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
27008
27255
  };
27009
27256
 
27257
+ // src/gql.ts
27258
+ var gqlRequest = async (query, variables) => {
27259
+ const res = await v2Fetch("/v2/graphql", {
27260
+ method: "POST",
27261
+ headers: { "Content-Type": "application/json" },
27262
+ body: JSON.stringify({ query, variables })
27263
+ });
27264
+ const raw2 = await res.text();
27265
+ const body = (() => {
27266
+ try {
27267
+ return JSON.parse(raw2);
27268
+ } catch {
27269
+ return null;
27270
+ }
27271
+ })();
27272
+ if (body?.errors != null && body.errors.length > 0) {
27273
+ throw new Error(body.errors.map((e) => e.message).join("; "));
27274
+ }
27275
+ if (!res.ok) throw v2Error("graphql", res, raw2);
27276
+ if (body?.data == null) {
27277
+ throw new Error("graphql returned no data and no errors.");
27278
+ }
27279
+ return body.data;
27280
+ };
27281
+
27010
27282
  // src/commands/automation.ts
27011
27283
  var runRuns = async (automationId, args) => {
27012
27284
  const limit2 = Number(flagValue(args, "--limit") ?? 20);
@@ -27893,7 +28165,7 @@ var Token = class {
27893
28165
  }
27894
28166
  };
27895
28167
  var Drop = class {
27896
- liquidMethodMissing(key, context) {
28168
+ liquidMethodMissing(key, context2) {
27897
28169
  return void 0;
27898
28170
  }
27899
28171
  };
@@ -28166,7 +28438,7 @@ function mkContext(token) {
28166
28438
  const lines = token.input.split("\n");
28167
28439
  const begin = Math.max(line - 2, 1);
28168
28440
  const end = Math.min(line + 3, lines.length);
28169
- const context = range(begin, end + 1).map((lineNumber) => {
28441
+ const context2 = range(begin, end + 1).map((lineNumber) => {
28170
28442
  const rowIndicator = lineNumber === line ? ">> " : " ";
28171
28443
  const num = padStart(String(lineNumber), String(end).length);
28172
28444
  let text = `${rowIndicator}${num}| `;
@@ -28175,7 +28447,7 @@ function mkContext(token) {
28175
28447
  text += colIndicator;
28176
28448
  return text;
28177
28449
  }).join("\n");
28178
- return context;
28450
+ return context2;
28179
28451
  }
28180
28452
  function mkMessage(msg, token) {
28181
28453
  if (token.file)
@@ -29087,15 +29359,15 @@ var Filter = class {
29087
29359
  this.args = token.args;
29088
29360
  this.liquid = liquid;
29089
29361
  }
29090
- *render(value, context) {
29362
+ *render(value, context2) {
29091
29363
  const argv = [];
29092
29364
  for (const arg of this.args) {
29093
29365
  if (isKeyValuePair(arg))
29094
- argv.push([arg[0], yield evalToken(arg[1], context)]);
29366
+ argv.push([arg[0], yield evalToken(arg[1], context2)]);
29095
29367
  else
29096
- argv.push(yield evalToken(arg, context));
29368
+ argv.push(yield evalToken(arg, context2));
29097
29369
  }
29098
- return yield this.handler.apply({ context, token: this.token, liquid: this.liquid }, [value, ...argv]);
29370
+ return yield this.handler.apply({ context: context2, token: this.token, liquid: this.liquid }, [value, ...argv]);
29099
29371
  }
29100
29372
  };
29101
29373
  var Expression = class {
@@ -32080,8 +32352,8 @@ var DecrementTag = class extends Tag {
32080
32352
  this.identifier = this.tokenizer.readIdentifier();
32081
32353
  this.variable = this.identifier.content;
32082
32354
  }
32083
- render(context, emitter) {
32084
- const scope = context.environments;
32355
+ render(context2, emitter) {
32356
+ const scope = context2.environments;
32085
32357
  if (!isNumber(scope[this.variable])) {
32086
32358
  scope[this.variable] = 0;
32087
32359
  }
@@ -32185,8 +32457,8 @@ var IncrementTag = class extends Tag {
32185
32457
  this.identifier = this.tokenizer.readIdentifier();
32186
32458
  this.variable = this.identifier.content;
32187
32459
  }
32188
- render(context, emitter) {
32189
- const scope = context.environments;
32460
+ render(context2, emitter) {
32461
+ const scope = context2.environments;
32190
32462
  if (!isNumber(scope[this.variable])) {
32191
32463
  scope[this.variable] = 0;
32192
32464
  }
@@ -33151,8 +33423,8 @@ var GeneratePasswordTag = class extends Tag {
33151
33423
  *arguments() {
33152
33424
  yield* Object.values(this.args.hash).filter(typeGuards.isValueToken);
33153
33425
  }
33154
- *render(context, emitter) {
33155
- const { length, charSet } = yield this.args.render(context);
33426
+ *render(context2, emitter) {
33427
+ const { length, charSet } = yield this.args.render(context2);
33156
33428
  const passwordLength = typeof length === "string" && !isNaN(parseInt(length)) ? parseInt(length) : typeof length === "number" ? length : 12;
33157
33429
  const passwordCharSet = typeof charSet === "string" ? charSet : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%&*";
33158
33430
  const password = customAlphabet(passwordCharSet, passwordLength)();
@@ -33564,66 +33836,6 @@ var runDataStream = async (args) => {
33564
33836
  printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
33565
33837
  };
33566
33838
 
33567
- // src/commands/knowledgeBase.ts
33568
- import { readFile as readFile2 } from "fs/promises";
33569
- import { basename } from "path";
33570
- var runKnowledgeBase = async (args) => {
33571
- const [operation, id] = args;
33572
- if (id == null || operation !== "upload" && operation !== "search") {
33573
- throw new Error(
33574
- "Usage: overai knowledge-base upload <id> <file...> | knowledge-base search <id> <query> [--limit N]"
33575
- );
33576
- }
33577
- const { organizationId } = await getAccessToken();
33578
- if (operation === "upload") {
33579
- const paths = args.slice(2).filter(
33580
- (arg, i, all) => !arg.startsWith("-") && all[i - 1] !== "-o" && all[i - 1] !== "--output"
33581
- );
33582
- if (paths.length === 0)
33583
- throw new Error("Knowledge base upload requires at least one file path.");
33584
- const uploads = [];
33585
- for (const path of paths) {
33586
- const bytes = await readFile2(path);
33587
- const formData = new FormData();
33588
- formData.append(
33589
- "file",
33590
- new Blob([new Uint8Array(bytes)]),
33591
- basename(path)
33592
- );
33593
- const response2 = await v2Fetch(
33594
- `/v2/knowledge-bases/${organizationId}/${id}/upload`,
33595
- { method: "POST", body: formData }
33596
- );
33597
- const raw3 = await response2.text();
33598
- if (!response2.ok) throw v2Error("knowledge-base upload", response2, raw3);
33599
- uploads.push({ file: basename(path), ...JSON.parse(raw3) });
33600
- }
33601
- printResult(uploads, resolveFormat(flagValue(args, "-o", "--output")));
33602
- return;
33603
- }
33604
- const query = args[2];
33605
- if (query == null || query.startsWith("-"))
33606
- throw new Error("Knowledge base search requires a query string.");
33607
- const limit2 = flagValue(args, "--limit");
33608
- const response = await v2Fetch(
33609
- `/v2/knowledge-bases/${organizationId}/${id}/search`,
33610
- {
33611
- method: "POST",
33612
- headers: { "Content-Type": "application/json" },
33613
- body: JSON.stringify({
33614
- query,
33615
- ...limit2 != null ? { limit: Number(limit2) } : {}
33616
- })
33617
- }
33618
- );
33619
- const raw2 = await response.text();
33620
- if (!response.ok) throw v2Error("knowledge-base search", response, raw2);
33621
- printResult(
33622
- JSON.parse(raw2),
33623
- resolveFormat(flagValue(args, "-o", "--output"))
33624
- );
33625
- };
33626
-
33627
33839
  // src/commands/dev.ts
33628
33840
  import { createHash as createHash3 } from "crypto";
33629
33841
  import { watch } from "fs";
@@ -34108,6 +34320,8 @@ var runDev = async (args) => {
34108
34320
  );
34109
34321
  }
34110
34322
  const [id, resource] = match;
34323
+ const browserBaseUrl = appBaseUrl(apiBaseUrl());
34324
+ const appOrigin = new URL(browserBaseUrl).origin;
34111
34325
  const snapshot = () => {
34112
34326
  const base = {
34113
34327
  id,
@@ -34149,7 +34363,6 @@ var runDev = async (args) => {
34149
34363
  ...new Set(resource.files.map((f) => join5(root, dirname3(f))))
34150
34364
  ];
34151
34365
  watchedDirs.forEach((dir) => watch(dir, notifyChange));
34152
- const appOrigin = new URL(appBaseUrl).origin;
34153
34366
  const server = createServer2((req, res) => {
34154
34367
  const headers = {
34155
34368
  // The webapp page is a different origin; a secure page may also send a
@@ -34201,7 +34414,7 @@ var runDev = async (args) => {
34201
34414
  error instanceof Error && "code" in error && error.code === "EADDRINUSE" ? `Port ${String(port)} is in use \u2014 pass --port <n>.` : String(error)
34202
34415
  );
34203
34416
  });
34204
- const url = `${appBaseUrl}/${manifest.organizationId}/dev?src=${encodeURIComponent(`http://127.0.0.1:${String(port)}`)}`;
34417
+ const url = `${browserBaseUrl}/${manifest.organizationId}/dev?src=${encodeURIComponent(`http://127.0.0.1:${String(port)}`)}`;
34205
34418
  process.stdout.write(
34206
34419
  `Serving ${resource.name} (${id}) from local files.
34207
34420
  ${url}
@@ -34405,6 +34618,66 @@ var runIntegration = async (args) => {
34405
34618
  printResult(result, resolveFormat(flagValue(args, "-o", "--output")));
34406
34619
  };
34407
34620
 
34621
+ // src/commands/knowledgeBase.ts
34622
+ import { readFile as readFile2 } from "fs/promises";
34623
+ import { basename } from "path";
34624
+ var runKnowledgeBase = async (args) => {
34625
+ const [operation, id] = args;
34626
+ if (id == null || operation !== "upload" && operation !== "search") {
34627
+ throw new Error(
34628
+ "Usage: overai knowledge-base upload <id> <file...> | knowledge-base search <id> <query> [--limit N]"
34629
+ );
34630
+ }
34631
+ const { organizationId } = await getAccessToken();
34632
+ if (operation === "upload") {
34633
+ const paths = args.slice(2).filter(
34634
+ (arg, i, all) => !arg.startsWith("-") && all[i - 1] !== "-o" && all[i - 1] !== "--output"
34635
+ );
34636
+ if (paths.length === 0)
34637
+ throw new Error("Knowledge base upload requires at least one file path.");
34638
+ const uploads = [];
34639
+ for (const path of paths) {
34640
+ const bytes = await readFile2(path);
34641
+ const formData = new FormData();
34642
+ formData.append(
34643
+ "file",
34644
+ new Blob([new Uint8Array(bytes)]),
34645
+ basename(path)
34646
+ );
34647
+ const response2 = await v2Fetch(
34648
+ `/v2/knowledge-bases/${organizationId}/${id}/upload`,
34649
+ { method: "POST", body: formData }
34650
+ );
34651
+ const raw3 = await response2.text();
34652
+ if (!response2.ok) throw v2Error("knowledge-base upload", response2, raw3);
34653
+ uploads.push({ file: basename(path), ...JSON.parse(raw3) });
34654
+ }
34655
+ printResult(uploads, resolveFormat(flagValue(args, "-o", "--output")));
34656
+ return;
34657
+ }
34658
+ const query = args[2];
34659
+ if (query == null || query.startsWith("-"))
34660
+ throw new Error("Knowledge base search requires a query string.");
34661
+ const limit2 = flagValue(args, "--limit");
34662
+ const response = await v2Fetch(
34663
+ `/v2/knowledge-bases/${organizationId}/${id}/search`,
34664
+ {
34665
+ method: "POST",
34666
+ headers: { "Content-Type": "application/json" },
34667
+ body: JSON.stringify({
34668
+ query,
34669
+ ...limit2 != null ? { limit: Number(limit2) } : {}
34670
+ })
34671
+ }
34672
+ );
34673
+ const raw2 = await response.text();
34674
+ if (!response.ok) throw v2Error("knowledge-base search", response, raw2);
34675
+ printResult(
34676
+ JSON.parse(raw2),
34677
+ resolveFormat(flagValue(args, "-o", "--output"))
34678
+ );
34679
+ };
34680
+
34408
34681
  // src/commands/open.ts
34409
34682
  var ROUTE_BY_TYPE = {
34410
34683
  automation: "automations",
@@ -34440,14 +34713,14 @@ var runOpen = async (args) => {
34440
34713
  })();
34441
34714
  if (manifest != null) {
34442
34715
  if (filter2 == null) {
34443
- return `${appBaseUrl}/${manifest.organizationId}/workspaces/${manifest.workspaceId}`;
34716
+ return `${appBaseUrl(apiBaseUrl())}/${manifest.organizationId}/workspaces/${manifest.workspaceId}`;
34444
34717
  }
34445
34718
  const match = Object.entries(manifest.resources).find(
34446
34719
  ([id, r]) => id === filter2 || r.name.toLowerCase().includes(filter2.toLowerCase()) || r.files.some((f) => f.includes(filter2))
34447
34720
  );
34448
34721
  if (match != null) {
34449
34722
  const [id, resource] = match;
34450
- return `${appBaseUrl}/${manifest.organizationId}/${ROUTE_BY_TYPE[resource.type]}/${id}`;
34723
+ return `${appBaseUrl(apiBaseUrl())}/${manifest.organizationId}/${ROUTE_BY_TYPE[resource.type]}/${id}`;
34451
34724
  }
34452
34725
  }
34453
34726
  if (filter2 == null) {
@@ -34463,13 +34736,74 @@ var runOpen = async (args) => {
34463
34736
  `Nothing matched "${filter2}" (not a tracked resource or a recognized id prefix).`
34464
34737
  );
34465
34738
  }
34466
- return `${appBaseUrl}/${organizationId}/${prefixed[1]}/${filter2}`;
34739
+ return `${appBaseUrl(apiBaseUrl())}/${organizationId}/${prefixed[1]}/${filter2}`;
34467
34740
  })();
34468
34741
  process.stdout.write(`${url}
34469
34742
  `);
34470
34743
  openBrowser(url);
34471
34744
  };
34472
34745
 
34746
+ // src/commands/org.ts
34747
+ var USER_ORGS_QUERY = `
34748
+ query UserOrganizations($identityId: String!) {
34749
+ identityOrganizations(condition: { identityId: $identityId }) {
34750
+ nodes {
34751
+ disabled
34752
+ organization { id name }
34753
+ }
34754
+ }
34755
+ }
34756
+ `;
34757
+ var listOrgRows = async () => {
34758
+ const auth = await getAccessToken();
34759
+ const identityId = decodeJwtClaims(auth.token).user_id;
34760
+ if (identityId == null) {
34761
+ throw new Error("Could not read identity from the current session.");
34762
+ }
34763
+ const data = await gqlRequest(USER_ORGS_QUERY, { identityId });
34764
+ return data.identityOrganizations.nodes.filter((node) => node != null && !node.disabled).map((node) => node?.organization).filter((org) => org != null);
34765
+ };
34766
+ var listOrgs = async (args) => {
34767
+ const active = scopedOrgId();
34768
+ printResult(
34769
+ (await listOrgRows()).map((org) => ({
34770
+ id: org.id,
34771
+ name: org.name ?? "",
34772
+ active: org.id === active,
34773
+ sessionSaved: readStore().deployments[apiBaseUrl()]?.sessions[org.id] != null
34774
+ })),
34775
+ resolveFormat(flagValue(args, "-o", "--output"))
34776
+ );
34777
+ };
34778
+ var switchOrg = async (orgId) => {
34779
+ if (orgIdOverride != null && orgIdOverride !== orgId) {
34780
+ throw new Error(
34781
+ `OVERAI_ORG_ID=${orgIdOverride} conflicts with the requested org ${orgId}. Unset it first.`
34782
+ );
34783
+ }
34784
+ setOrgScope(orgId);
34785
+ try {
34786
+ await getAccessToken();
34787
+ } catch (error) {
34788
+ if (!(error instanceof InteractiveSignInRequired)) throw error;
34789
+ await signIn(orgId);
34790
+ }
34791
+ await withStoreLock((store) => {
34792
+ const deployment = store.deployments[apiBaseUrl()];
34793
+ if (deployment?.sessions[orgId] == null)
34794
+ throw new Error(
34795
+ "Session was signed out before the default could be changed."
34796
+ );
34797
+ deployment.defaultOrgId = orgId;
34798
+ writeStore(store);
34799
+ });
34800
+ process.stdout.write(
34801
+ `Default org set to ${orgId}. Other org sessions are unchanged.
34802
+ This default is machine-global; workspace folders and OVERAI_ORG_ID override it.
34803
+ `
34804
+ );
34805
+ };
34806
+
34473
34807
  // src/commands/printablePage.ts
34474
34808
  var runPrintablePage = async (args) => {
34475
34809
  const [operation, id] = args;
@@ -34745,6 +35079,12 @@ var runResource = async (args) => {
34745
35079
  // src/docs/bestPractices.ts
34746
35080
  var platform2 = `# OverAI platform primer
34747
35081
 
35082
+ Organization context: Commands in a clone select its org automatically. Outside a clone,
35083
+ use OVERAI_ORG_ID=<orgId>. Each backend/org has an independent saved session; org switch
35084
+ changes only the machine-global default. Use whoami to inspect the effective scope.
35085
+ If browser authorization is required, ask the user to run the suggested signin command.
35086
+ Never change org to work around a clone-sync mismatch; use the correct workspace folder.
35087
+
34748
35088
  Resources live in Workspaces. The runtime always executes the DEPLOYED version
34749
35089
  of a resource, never the latest \u2014 \`overai push\` creates a version, \`overai
34750
35090
  deploy\` makes it live. Pick primitives by trigger:
@@ -34849,9 +35189,9 @@ language, customTitle, hideTopBar, ...). Push reassembles them.
34849
35189
  - SQL from pages: env.TBSxxx.sql tagged templates only; compose dynamic SQL by
34850
35190
  nesting sql fragments, sql([...]) for IN lists. sql.unsafe only for dynamic
34851
35191
  identifiers.
34852
- - For guest-facing workspaces, add page-to-page navigation (guests land on the
34853
- workspace homepage and can only follow links). "Hide Top Bar" gives an
34854
- app-like experience.
35192
+ - For end-user-facing workspaces, add page-to-page navigation (end users land
35193
+ on the workspace homepage and can only follow links). "Hide Top Bar" gives
35194
+ an app-like experience.
34855
35195
  - Public pages (/public/:id) have no viewer identity \u2014 useCurrentUser() is
34856
35196
  null. Identity-scoped features degrade: useAgentChat streams but persists
34857
35197
  nothing (conversationId stays null, useAgentConversations is empty, the
@@ -34868,6 +35208,14 @@ language, customTitle, hideTopBar, ...). Push reassembles them.
34868
35208
  item/attribute model. For new pages load data in the page instead \u2014 web pages
34869
35209
  via env.TBSxxx.sql / env.DFxxx, printable pages via fetch with the \`token\`
34870
35210
  global (no env proxy there). Don't rewrite a working page just to migrate it.
35211
+ - filter in meta.json DOES evaluate Liquid, in every string value it contains,
35212
+ against \`now\` (a Date rounded down to the minute) plus the search params.
35213
+ The two page kinds bind params differently: a WEB page takes them by bare
35214
+ name (\`{{ since }}\` for ?since=), a PRINTABLE page namespaces them
35215
+ (\`{{ searchParams.since }}\`). \`{{ now | minus: 1209600000 | toISOString }}\`
35216
+ works on both. On a web page a template that won't evaluate, or that
35217
+ evaluates to nothing, fails the page; a printable page falls back to an
35218
+ empty filter instead.
34871
35219
  - dataSourceUrl in meta.json is fetched verbatim and its response becomes the
34872
35220
  \`data\` global. It is a static URL, not a template \u2014 search params are NOT
34873
35221
  substituted into it (neither {x} nor Liquid {{ x }}). If the data depends on
@@ -35854,10 +36202,11 @@ var HELP = `overai \u2014 OverAI command-line interface
35854
36202
  Usage:
35855
36203
  overai signin Sign in via your browser; choose your
35856
36204
  organization there to complete SSO
35857
- overai signout Sign out and revoke this session
36205
+ overai signout [--all] Revoke this org\u2019s saved CLI session;
36206
+ --all revokes all locally saved sessions
35858
36207
  overai whoami Show the current identity and org
35859
36208
  overai org list List your organizations
35860
- overai org switch <orgId> Switch the active org
36209
+ overai org switch <orgId> Select the default org
35861
36210
  overai workspace list [--archived] List workspaces you can see in this org
35862
36211
  overai workspace show [workspaceId] Show a workspace's name and overview
35863
36212
  overai workspace users [workspaceId] List users and effective/direct roles
@@ -35940,10 +36289,12 @@ it from stdin. Prefer that for anything long or quote-heavy: an inline value is
35940
36289
  parsed by your shell first, and one apostrophe inside it silently truncates the
35941
36290
  rest. Write @@ to send a literal value that starts with "@".
35942
36291
 
35943
- Organizations: commands run as the clone you're standing in (.overai/manifest.json),
35944
- else the active org from \`org switch\`. The active org is machine-global \u2014 every
35945
- shell shares it \u2014 so scope one command or one shell with OVERAI_ORG_ID=<orgId>
35946
- instead. \`overai whoami\` says which org is in effect and why.
36292
+ Organizations: OVERAI_ORG_ID selects an org for one command or shell, else commands
36293
+ use the clone\u2019s org (.overai/manifest.json), else the saved default. Each backend
36294
+ and org has its own session. Entering another org preserves existing sessions;
36295
+ org switch changes only the machine-global default. Clone sync commands reject
36296
+ conflicting overrides. SSO prompts name the signin command to run explicitly.
36297
+ whoami shows the backend, org, identity, and selection source.
35947
36298
 
35948
36299
  Output: table on a TTY, JSON when piped; -o json|table|csv to force.
35949
36300
  Aliases: login = signin, logout = signout, ws = workspace.
@@ -35984,10 +36335,10 @@ var run = async () => {
35984
36335
  return;
35985
36336
  case "signout":
35986
36337
  case "logout":
35987
- await signOut();
36338
+ await signOut(rest.includes("--all"));
35988
36339
  return;
35989
36340
  case "whoami":
35990
- await whoami();
36341
+ whoami();
35991
36342
  return;
35992
36343
  case "org":
35993
36344
  if (rest[0] === "list") {