@overaihq/cli 0.9.0 → 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.
package/dist/index.js CHANGED
@@ -5,10 +5,10 @@ import {
5
5
  import {
6
6
  itemFilterExpressionRootSchema,
7
7
  webPageConfigSchema
8
- } from "./chunk-2F4ZHHFG.js";
8
+ } from "./chunk-KIHU74V6.js";
9
9
  import {
10
10
  external_exports
11
- } from "./chunk-6YTIPJTD.js";
11
+ } from "./chunk-XCJJTK3H.js";
12
12
  import {
13
13
  __commonJS,
14
14
  __toESM
@@ -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,175 +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/output.ts
26617
- var resolveFormat = (explicit) => {
26618
- if (explicit === "json" || explicit === "csv" || explicit === "table") {
26619
- return explicit;
26620
- }
26621
- if (explicit != null) {
26622
- throw new Error(
26623
- `Unknown output format "${explicit}". Use json, table, or csv.`
26624
- );
26625
- }
26626
- return process.stdout.isTTY ? "table" : "json";
26627
- };
26628
- var cell = (value) => {
26629
- if (value == null) return "";
26630
- if (typeof value === "string") return value;
26631
- if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
26632
- return String(value);
26633
- }
26634
- return JSON.stringify(value);
26635
- };
26636
- var formatResult = (data, format2) => {
26637
- if (format2 === "json" || !Array.isArray(data)) {
26638
- return JSON.stringify(data, null, 2);
26639
- }
26640
- const records = data.map(
26641
- (row) => row != null && typeof row === "object" ? row : { value: row }
26642
- );
26643
- if (records.length === 0) return "(no rows)";
26644
- const columns = [...new Set(records.flatMap((r) => Object.keys(r)))];
26645
- if (format2 === "csv") {
26646
- const escape2 = (value) => {
26647
- const text = cell(value);
26648
- return /[",\n\r]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
26649
- };
26650
- return [
26651
- columns.join(","),
26652
- ...records.map((r) => columns.map((c) => escape2(r[c])).join(","))
26653
- ].join("\n");
26654
- }
26655
- const widths = columns.map(
26656
- (c) => Math.max(c.length, ...records.map((r) => cell(r[c]).length))
26657
- );
26658
- const line = (cells) => cells.map((text, i) => text.padEnd(widths[i] ?? 0)).join(" ");
26659
- return [
26660
- line(columns),
26661
- line(widths.map((w) => "-".repeat(w))),
26662
- ...records.map((r) => line(columns.map((c) => cell(r[c]))))
26663
- ].join("\n");
26664
- };
26665
- var printResult = (data, format2) => {
26666
- process.stdout.write(`${formatResult(data, format2)}
26667
- `);
26668
- };
26669
-
26670
- // src/commands/org.ts
26671
- var USER_ORGS_QUERY = `
26672
- query UserOrganizations($identityId: String!) {
26673
- identityOrganizations(
26674
- where: { identityId: { _eq: $identityId }, disabled: { _eq: false } }
26675
- ) {
26676
- organization { id name }
26677
- }
26678
- }
26679
- `;
26680
- var fetchOrgNames = async () => {
26681
- const orgs = await listOrgRows();
26682
- return new Map(orgs.map((org) => [org.id, org.name ?? ""]));
26683
- };
26684
- var listOrgRows = async () => {
26685
- const auth = await getAccessToken();
26686
- const identityId = decodeJwtClaims(auth.token).user_id;
26687
- if (identityId == null) {
26688
- throw new Error("Could not read identity from the current session.");
26689
- }
26690
- const res = await v2Fetch("/v1/graphql", {
26691
- method: "POST",
26692
- headers: { "Content-Type": "application/json" },
26693
- body: JSON.stringify({ query: USER_ORGS_QUERY, variables: { identityId } })
26694
- });
26695
- const body = await res.json().catch(() => null);
26696
- if (body?.errors != null && body.errors.length > 0) {
26697
- throw new Error(body.errors.map((e) => e.message).join("; "));
26698
- }
26699
- if (!res.ok || body == null) {
26700
- throw new Error(`org list failed (${String(res.status)})`);
26701
- }
26702
- return (body.data?.identityOrganizations ?? []).map((edge) => edge.organization).filter((org) => org != null);
26703
- };
26704
- var listOrgs = async (args) => {
26705
- const active = scopedOrgId();
26706
- printResult(
26707
- (await listOrgRows()).map((org) => ({
26708
- id: org.id,
26709
- name: org.name ?? "",
26710
- active: org.id === active
26711
- })),
26712
- resolveFormat(flagValue(args, "-o", "--output"))
26713
- );
26714
- };
26715
- var switchOrg = async (orgId) => {
26716
- const config = readConfig();
26717
- if (config == null) {
26718
- process.stderr.write("Not signed in. Run `overai signin`.\n");
26719
- process.exitCode = 1;
26720
- return;
26721
- }
26722
- const result = await exchangeSessionToken(config.refreshToken, orgId);
26723
- if (result.type === "redirect") {
26724
- process.stdout.write(
26725
- `This organization requires SSO. Complete sign-in in your browser, then run \`overai signin\`.
26726
- ${result.redirectUrl}
26727
- `
26728
- );
26729
- openBrowser(result.redirectUrl);
26730
- process.exitCode = 1;
26731
- return;
26732
- }
26733
- writeConfig({
26734
- ...config,
26735
- organizationId: orgId,
26736
- email: decodeJwtClaims(result.token).email ?? config.email,
26737
- accessToken: result.token,
26738
- accessTokenExpiresAt: Date.now() + result.accessTokenValiditySeconds * 1e3,
26739
- refreshToken: result.refreshToken
26740
- });
26741
- process.stdout.write(
26742
- `Switched to org ${orgId}.
26743
- 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.
26744
- `
26745
- );
26746
- };
26747
-
26748
26816
  // src/pkce.ts
26749
26817
  import { createHash, randomBytes } from "crypto";
26750
26818
  var createPkcePair = () => {
@@ -26754,7 +26822,7 @@ var createPkcePair = () => {
26754
26822
  };
26755
26823
 
26756
26824
  // src/workspace/manifest.ts
26757
- 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";
26758
26826
  import { dirname, join as join2, resolve } from "path";
26759
26827
  var MANIFEST_DIR = ".overai";
26760
26828
  var MANIFEST_FILE = "manifest.json";
@@ -26773,11 +26841,16 @@ var findWorkspaceRoot = (from = process.cwd()) => {
26773
26841
  }
26774
26842
  };
26775
26843
  var readManifest = (root) => JSON.parse(
26776
- readFileSync3(join2(root, MANIFEST_DIR, MANIFEST_FILE), "utf8")
26844
+ readFileSync2(join2(root, MANIFEST_DIR, MANIFEST_FILE), "utf8")
26777
26845
  );
26778
26846
  var openClone = () => {
26779
26847
  const root = findWorkspaceRoot();
26780
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
+ }
26781
26854
  setOrgScope(manifest.organizationId);
26782
26855
  return { root, manifest };
26783
26856
  };
@@ -26804,14 +26877,14 @@ var writeSynced = (root, relPath, content) => {
26804
26877
  };
26805
26878
  var readWorkingFile = (root, relPath) => {
26806
26879
  try {
26807
- return readFileSync3(join2(root, relPath), "utf8");
26880
+ return readFileSync2(join2(root, relPath), "utf8");
26808
26881
  } catch {
26809
26882
  return null;
26810
26883
  }
26811
26884
  };
26812
26885
  var readBaseFile = (root, relPath) => {
26813
26886
  try {
26814
- return readFileSync3(basePath(root, relPath), "utf8");
26887
+ return readFileSync2(basePath(root, relPath), "utf8");
26815
26888
  } catch {
26816
26889
  return null;
26817
26890
  }
@@ -26898,16 +26971,23 @@ var startCallbackServer = (expectedState) => {
26898
26971
  });
26899
26972
  });
26900
26973
  };
26901
- 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();
26902
26980
  const { verifier, challenge } = createPkcePair();
26903
26981
  const state = randomBytes2(16).toString("base64url");
26904
26982
  const { port, codePromise, close } = await startCallbackServer(state);
26905
- const authorizeUrl = `${appBaseUrl}/cli-auth?${new URLSearchParams({
26906
- redirect_uri: `http://127.0.0.1:${String(port)}`,
26907
- code_challenge: challenge,
26908
- state,
26909
- label: hostname()
26910
- }).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()}`;
26911
26991
  const autoOpen = process.env.OVERAI_NO_BROWSER == null;
26912
26992
  process.stdout.write(
26913
26993
  `${autoOpen ? "Opening your browser to authorize the CLI.\nIf it doesn't open, visit" : "Visit this URL to authorize the CLI"}:
@@ -26918,15 +26998,58 @@ ${authorizeUrl}
26918
26998
  try {
26919
26999
  const code = await codePromise;
26920
27000
  const session = await exchangeCliAuthCode(code, verifier);
26921
- const email = decodeJwtClaims(session.token).email;
26922
- writeConfig({
26923
- refreshToken: session.refreshToken,
26924
- organizationId: session.organizationId,
26925
- apiBaseUrl: apiBaseUrlOverride ?? DEFAULT_API_BASE_URL,
26926
- email,
26927
- accessToken: session.token,
26928
- accessTokenExpiresAt: Date.now() + session.accessTokenValiditySeconds * 1e3
26929
- });
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
+ }
26930
27053
  process.stdout.write(
26931
27054
  `Signed in${email != null ? ` as ${email}` : ""} (org ${session.organizationId}).
26932
27055
  `
@@ -26935,45 +27058,184 @@ ${authorizeUrl}
26935
27058
  close();
26936
27059
  }
26937
27060
  };
26938
- var signOut = async () => {
26939
- const config = readConfig();
26940
- if (config == null) {
26941
- process.stdout.write("Not signed in.\n");
26942
- return;
26943
- }
26944
- await signOutHeadless(config.refreshToken).catch(() => void 0);
26945
- clearConfig();
26946
- process.stdout.write("Signed out.\n");
26947
- };
26948
- var whoami = async () => {
26949
- const config = readConfig();
26950
- if (config == null) {
26951
- process.stderr.write("Not signed in. Run `overai signin`.\n");
26952
- process.exitCode = 1;
26953
- return;
26954
- }
26955
- const cloneOrgId = (() => {
27061
+ var signOut = async (all = false) => {
27062
+ const root = (() => {
26956
27063
  try {
26957
- return readManifest(findWorkspaceRoot()).organizationId;
27064
+ return findWorkspaceRoot();
26958
27065
  } catch {
26959
27066
  return null;
26960
27067
  }
26961
27068
  })();
26962
- const effective = orgIdOverride ?? cloneOrgId ?? config.organizationId;
26963
- const names = await fetchOrgNames().catch(() => null);
26964
- const label = (id) => names?.get(id) == null ? id : `${id} \u2014 ${String(names.get(id))}`;
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
+ });
26965
27122
  process.stdout.write(
26966
- `Signed in${config.email != null ? ` as ${config.email}` : ""} (org ${label(effective)}).
27123
+ all ? "Signed out of all locally saved CLI sessions.\n" : `Signed out of org ${orgId ?? "(none selected)"}.
26967
27124
  `
26968
27125
  );
26969
- if (effective !== config.organizationId) {
26970
- process.stdout.write(
26971
- `Scoped by ${orgIdOverride != null ? "OVERAI_ORG_ID" : ".overai/manifest.json"}; the machine-global active org is ${label(config.organizationId)}.
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"}
26972
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 "@".`
26973
27181
  );
26974
27182
  }
26975
27183
  };
26976
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
+ );
27194
+ }
27195
+ return process.stdout.isTTY ? "table" : "json";
27196
+ };
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);
27202
+ }
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 }
27211
+ );
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");
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
+ `);
27237
+ };
27238
+
26977
27239
  // src/commands/agent.ts
26978
27240
  var runAgent = async (args) => {
26979
27241
  const [operation, id] = args;
@@ -26993,15 +27255,12 @@ var runAgent = async (args) => {
26993
27255
  };
26994
27256
 
26995
27257
  // src/gql.ts
26996
- var gqlRequest = async (query, variables, options) => {
26997
- const res = await v2Fetch(
26998
- options?.v1 === true ? "/v1/graphql" : "/v2/graphql",
26999
- {
27000
- method: "POST",
27001
- headers: { "Content-Type": "application/json" },
27002
- body: JSON.stringify({ query, variables })
27003
- }
27004
- );
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
+ });
27005
27264
  const raw2 = await res.text();
27006
27265
  const body = (() => {
27007
27266
  try {
@@ -27110,11 +27369,11 @@ var runAutomation = async (args) => {
27110
27369
  // src/workspace/validateElements.ts
27111
27370
  var findings = (parsed) => parsed.success ? [] : parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`);
27112
27371
  var validateAutomationElements = async (elements) => {
27113
- const { automationNodesSchema } = await import("./types-RJF53EMD.js");
27372
+ const { automationNodesSchema } = await import("./types-QDEUVRZP.js");
27114
27373
  return findings(automationNodesSchema.safeParse(elements));
27115
27374
  };
27116
27375
  var validateWebPageConfig = async (config) => {
27117
- const { webPageConfigWriteSchema } = await import("./webPage-G5HIZM7Q.js");
27376
+ const { webPageConfigWriteSchema } = await import("./webPage-675DU764.js");
27118
27377
  return findings(webPageConfigWriteSchema.safeParse(config));
27119
27378
  };
27120
27379
 
@@ -27637,21 +27896,14 @@ var adapterFor = (type) => {
27637
27896
  var createActionRunner = async (workspaceId, name2) => {
27638
27897
  const identityResult = await gqlRequest(
27639
27898
  `mutation CliCreateMachineIdentity($name: String!) {
27640
- identityInsert(object: { name: $name, type: "machine" }) { id }
27899
+ createMachineIdentity(input: { name: $name }) {
27900
+ identity { id }
27901
+ }
27641
27902
  }`,
27642
- { name: name2 },
27643
- { v1: true }
27903
+ { name: name2 }
27644
27904
  );
27645
- const identityId = identityResult.identityInsert?.id;
27905
+ const identityId = identityResult.createMachineIdentity?.identity?.id;
27646
27906
  if (identityId == null) throw new Error("Failed to create machine identity");
27647
- await gqlRequest(
27648
- `mutation CliCreateIdentityOrganization($identityId: String!) {
27649
- createIdentityOrganization(
27650
- input: { identityOrganization: { identityId: $identityId } }
27651
- ) { identityOrganization { identityId } }
27652
- }`,
27653
- { identityId }
27654
- );
27655
27907
  const runnerResult = await gqlRequest(
27656
27908
  `mutation CliCreateActionRunner($identityId: String!, $workspaceId: String!) {
27657
27909
  createActionRunner(
@@ -27880,7 +28132,7 @@ var defaultAgentFunctionInputSchema = `{
27880
28132
  // ../common/src/liquidjs/liquidjs.ts
27881
28133
  var import_jmespath = __toESM(require_jmespath(), 1);
27882
28134
 
27883
- // ../../node_modules/.pnpm/liquidjs@10.28.0/node_modules/liquidjs/dist/liquid.node.mjs
28135
+ // ../../node_modules/.pnpm/liquidjs@10.29.0/node_modules/liquidjs/dist/liquid.node.mjs
27884
28136
  import { PassThrough } from "stream";
27885
28137
  import { sep, extname, resolve as resolve$1, dirname as dirname$1 } from "path";
27886
28138
  import { statSync, readFileSync as readFileSync$1, realpathSync, stat, readFile as readFile$1, realpath } from "fs";
@@ -27913,7 +28165,7 @@ var Token = class {
27913
28165
  }
27914
28166
  };
27915
28167
  var Drop = class {
27916
- liquidMethodMissing(key, context) {
28168
+ liquidMethodMissing(key, context2) {
27917
28169
  return void 0;
27918
28170
  }
27919
28171
  };
@@ -28186,7 +28438,7 @@ function mkContext(token) {
28186
28438
  const lines = token.input.split("\n");
28187
28439
  const begin = Math.max(line - 2, 1);
28188
28440
  const end = Math.min(line + 3, lines.length);
28189
- const context = range(begin, end + 1).map((lineNumber) => {
28441
+ const context2 = range(begin, end + 1).map((lineNumber) => {
28190
28442
  const rowIndicator = lineNumber === line ? ">> " : " ";
28191
28443
  const num = padStart(String(lineNumber), String(end).length);
28192
28444
  let text = `${rowIndicator}${num}| `;
@@ -28195,7 +28447,7 @@ function mkContext(token) {
28195
28447
  text += colIndicator;
28196
28448
  return text;
28197
28449
  }).join("\n");
28198
- return context;
28450
+ return context2;
28199
28451
  }
28200
28452
  function mkMessage(msg, token) {
28201
28453
  if (token.file)
@@ -29107,15 +29359,15 @@ var Filter = class {
29107
29359
  this.args = token.args;
29108
29360
  this.liquid = liquid;
29109
29361
  }
29110
- *render(value, context) {
29362
+ *render(value, context2) {
29111
29363
  const argv = [];
29112
29364
  for (const arg of this.args) {
29113
29365
  if (isKeyValuePair(arg))
29114
- argv.push([arg[0], yield evalToken(arg[1], context)]);
29366
+ argv.push([arg[0], yield evalToken(arg[1], context2)]);
29115
29367
  else
29116
- argv.push(yield evalToken(arg, context));
29368
+ argv.push(yield evalToken(arg, context2));
29117
29369
  }
29118
- 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]);
29119
29371
  }
29120
29372
  };
29121
29373
  var Expression = class {
@@ -31495,6 +31747,11 @@ function strip_newlines(v) {
31495
31747
  this.context.memoryLimit.use(str.length);
31496
31748
  return str.replace(/\r?\n/gm, "");
31497
31749
  }
31750
+ function squish(v) {
31751
+ const str = stringify(v);
31752
+ this.context.memoryLimit.use(str.length);
31753
+ return str.replace(/\s+/g, " ").trim();
31754
+ }
31498
31755
  function capitalize(str) {
31499
31756
  str = stringify(str);
31500
31757
  this.context.memoryLimit.use(str.length);
@@ -31597,6 +31854,7 @@ var stringFilters = /* @__PURE__ */ Object.freeze({
31597
31854
  split,
31598
31855
  strip,
31599
31856
  strip_newlines,
31857
+ squish,
31600
31858
  capitalize,
31601
31859
  replace,
31602
31860
  replace_first,
@@ -32094,8 +32352,8 @@ var DecrementTag = class extends Tag {
32094
32352
  this.identifier = this.tokenizer.readIdentifier();
32095
32353
  this.variable = this.identifier.content;
32096
32354
  }
32097
- render(context, emitter) {
32098
- const scope = context.environments;
32355
+ render(context2, emitter) {
32356
+ const scope = context2.environments;
32099
32357
  if (!isNumber(scope[this.variable])) {
32100
32358
  scope[this.variable] = 0;
32101
32359
  }
@@ -32199,8 +32457,8 @@ var IncrementTag = class extends Tag {
32199
32457
  this.identifier = this.tokenizer.readIdentifier();
32200
32458
  this.variable = this.identifier.content;
32201
32459
  }
32202
- render(context, emitter) {
32203
- const scope = context.environments;
32460
+ render(context2, emitter) {
32461
+ const scope = context2.environments;
32204
32462
  if (!isNumber(scope[this.variable])) {
32205
32463
  scope[this.variable] = 0;
32206
32464
  }
@@ -32634,6 +32892,9 @@ var Liquid = class _Liquid {
32634
32892
  registerFilter(name2, filter2) {
32635
32893
  this.filters[name2] = filter2;
32636
32894
  }
32895
+ unregisterFilter(name2) {
32896
+ delete this.filters[name2];
32897
+ }
32637
32898
  registerTag(name2, tag) {
32638
32899
  this.tags[name2] = isFunction(tag) ? tag : createTagClass(tag);
32639
32900
  }
@@ -33162,8 +33423,8 @@ var GeneratePasswordTag = class extends Tag {
33162
33423
  *arguments() {
33163
33424
  yield* Object.values(this.args.hash).filter(typeGuards.isValueToken);
33164
33425
  }
33165
- *render(context, emitter) {
33166
- const { length, charSet } = yield this.args.render(context);
33426
+ *render(context2, emitter) {
33427
+ const { length, charSet } = yield this.args.render(context2);
33167
33428
  const passwordLength = typeof length === "string" && !isNaN(parseInt(length)) ? parseInt(length) : typeof length === "number" ? length : 12;
33168
33429
  const passwordCharSet = typeof charSet === "string" ? charSet : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%&*";
33169
33430
  const password = customAlphabet(passwordCharSet, passwordLength)();
@@ -33575,66 +33836,6 @@ var runDataStream = async (args) => {
33575
33836
  printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
33576
33837
  };
33577
33838
 
33578
- // src/commands/knowledgeBase.ts
33579
- import { readFile as readFile2 } from "fs/promises";
33580
- import { basename } from "path";
33581
- var runKnowledgeBase = async (args) => {
33582
- const [operation, id] = args;
33583
- if (id == null || operation !== "upload" && operation !== "search") {
33584
- throw new Error(
33585
- "Usage: overai knowledge-base upload <id> <file...> | knowledge-base search <id> <query> [--limit N]"
33586
- );
33587
- }
33588
- const { organizationId } = await getAccessToken();
33589
- if (operation === "upload") {
33590
- const paths = args.slice(2).filter(
33591
- (arg, i, all) => !arg.startsWith("-") && all[i - 1] !== "-o" && all[i - 1] !== "--output"
33592
- );
33593
- if (paths.length === 0)
33594
- throw new Error("Knowledge base upload requires at least one file path.");
33595
- const uploads = [];
33596
- for (const path of paths) {
33597
- const bytes = await readFile2(path);
33598
- const formData = new FormData();
33599
- formData.append(
33600
- "file",
33601
- new Blob([new Uint8Array(bytes)]),
33602
- basename(path)
33603
- );
33604
- const response2 = await v2Fetch(
33605
- `/v2/knowledge-bases/${organizationId}/${id}/upload`,
33606
- { method: "POST", body: formData }
33607
- );
33608
- const raw3 = await response2.text();
33609
- if (!response2.ok) throw v2Error("knowledge-base upload", response2, raw3);
33610
- uploads.push({ file: basename(path), ...JSON.parse(raw3) });
33611
- }
33612
- printResult(uploads, resolveFormat(flagValue(args, "-o", "--output")));
33613
- return;
33614
- }
33615
- const query = args[2];
33616
- if (query == null || query.startsWith("-"))
33617
- throw new Error("Knowledge base search requires a query string.");
33618
- const limit2 = flagValue(args, "--limit");
33619
- const response = await v2Fetch(
33620
- `/v2/knowledge-bases/${organizationId}/${id}/search`,
33621
- {
33622
- method: "POST",
33623
- headers: { "Content-Type": "application/json" },
33624
- body: JSON.stringify({
33625
- query,
33626
- ...limit2 != null ? { limit: Number(limit2) } : {}
33627
- })
33628
- }
33629
- );
33630
- const raw2 = await response.text();
33631
- if (!response.ok) throw v2Error("knowledge-base search", response, raw2);
33632
- printResult(
33633
- JSON.parse(raw2),
33634
- resolveFormat(flagValue(args, "-o", "--output"))
33635
- );
33636
- };
33637
-
33638
33839
  // src/commands/dev.ts
33639
33840
  import { createHash as createHash3 } from "crypto";
33640
33841
  import { watch } from "fs";
@@ -34119,6 +34320,8 @@ var runDev = async (args) => {
34119
34320
  );
34120
34321
  }
34121
34322
  const [id, resource] = match;
34323
+ const browserBaseUrl = appBaseUrl(apiBaseUrl());
34324
+ const appOrigin = new URL(browserBaseUrl).origin;
34122
34325
  const snapshot = () => {
34123
34326
  const base = {
34124
34327
  id,
@@ -34160,7 +34363,6 @@ var runDev = async (args) => {
34160
34363
  ...new Set(resource.files.map((f) => join5(root, dirname3(f))))
34161
34364
  ];
34162
34365
  watchedDirs.forEach((dir) => watch(dir, notifyChange));
34163
- const appOrigin = new URL(appBaseUrl).origin;
34164
34366
  const server = createServer2((req, res) => {
34165
34367
  const headers = {
34166
34368
  // The webapp page is a different origin; a secure page may also send a
@@ -34212,7 +34414,7 @@ var runDev = async (args) => {
34212
34414
  error instanceof Error && "code" in error && error.code === "EADDRINUSE" ? `Port ${String(port)} is in use \u2014 pass --port <n>.` : String(error)
34213
34415
  );
34214
34416
  });
34215
- 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)}`)}`;
34216
34418
  process.stdout.write(
34217
34419
  `Serving ${resource.name} (${id}) from local files.
34218
34420
  ${url}
@@ -34416,6 +34618,66 @@ var runIntegration = async (args) => {
34416
34618
  printResult(result, resolveFormat(flagValue(args, "-o", "--output")));
34417
34619
  };
34418
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
+
34419
34681
  // src/commands/open.ts
34420
34682
  var ROUTE_BY_TYPE = {
34421
34683
  automation: "automations",
@@ -34451,14 +34713,14 @@ var runOpen = async (args) => {
34451
34713
  })();
34452
34714
  if (manifest != null) {
34453
34715
  if (filter2 == null) {
34454
- return `${appBaseUrl}/${manifest.organizationId}/workspaces/${manifest.workspaceId}`;
34716
+ return `${appBaseUrl(apiBaseUrl())}/${manifest.organizationId}/workspaces/${manifest.workspaceId}`;
34455
34717
  }
34456
34718
  const match = Object.entries(manifest.resources).find(
34457
34719
  ([id, r]) => id === filter2 || r.name.toLowerCase().includes(filter2.toLowerCase()) || r.files.some((f) => f.includes(filter2))
34458
34720
  );
34459
34721
  if (match != null) {
34460
34722
  const [id, resource] = match;
34461
- return `${appBaseUrl}/${manifest.organizationId}/${ROUTE_BY_TYPE[resource.type]}/${id}`;
34723
+ return `${appBaseUrl(apiBaseUrl())}/${manifest.organizationId}/${ROUTE_BY_TYPE[resource.type]}/${id}`;
34462
34724
  }
34463
34725
  }
34464
34726
  if (filter2 == null) {
@@ -34474,13 +34736,74 @@ var runOpen = async (args) => {
34474
34736
  `Nothing matched "${filter2}" (not a tracked resource or a recognized id prefix).`
34475
34737
  );
34476
34738
  }
34477
- return `${appBaseUrl}/${organizationId}/${prefixed[1]}/${filter2}`;
34739
+ return `${appBaseUrl(apiBaseUrl())}/${organizationId}/${prefixed[1]}/${filter2}`;
34478
34740
  })();
34479
34741
  process.stdout.write(`${url}
34480
34742
  `);
34481
34743
  openBrowser(url);
34482
34744
  };
34483
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
+
34484
34807
  // src/commands/printablePage.ts
34485
34808
  var runPrintablePage = async (args) => {
34486
34809
  const [operation, id] = args;
@@ -34756,6 +35079,12 @@ var runResource = async (args) => {
34756
35079
  // src/docs/bestPractices.ts
34757
35080
  var platform2 = `# OverAI platform primer
34758
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
+
34759
35088
  Resources live in Workspaces. The runtime always executes the DEPLOYED version
34760
35089
  of a resource, never the latest \u2014 \`overai push\` creates a version, \`overai
34761
35090
  deploy\` makes it live. Pick primitives by trigger:
@@ -34860,9 +35189,9 @@ language, customTitle, hideTopBar, ...). Push reassembles them.
34860
35189
  - SQL from pages: env.TBSxxx.sql tagged templates only; compose dynamic SQL by
34861
35190
  nesting sql fragments, sql([...]) for IN lists. sql.unsafe only for dynamic
34862
35191
  identifiers.
34863
- - For guest-facing workspaces, add page-to-page navigation (guests land on the
34864
- workspace homepage and can only follow links). "Hide Top Bar" gives an
34865
- 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.
34866
35195
  - Public pages (/public/:id) have no viewer identity \u2014 useCurrentUser() is
34867
35196
  null. Identity-scoped features degrade: useAgentChat streams but persists
34868
35197
  nothing (conversationId stays null, useAgentConversations is empty, the
@@ -34879,6 +35208,14 @@ language, customTitle, hideTopBar, ...). Push reassembles them.
34879
35208
  item/attribute model. For new pages load data in the page instead \u2014 web pages
34880
35209
  via env.TBSxxx.sql / env.DFxxx, printable pages via fetch with the \`token\`
34881
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.
34882
35219
  - dataSourceUrl in meta.json is fetched verbatim and its response becomes the
34883
35220
  \`data\` global. It is a static URL, not a template \u2014 search params are NOT
34884
35221
  substituted into it (neither {x} nor Liquid {{ x }}). If the data depends on
@@ -35865,10 +36202,11 @@ var HELP = `overai \u2014 OverAI command-line interface
35865
36202
  Usage:
35866
36203
  overai signin Sign in via your browser; choose your
35867
36204
  organization there to complete SSO
35868
- 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
35869
36207
  overai whoami Show the current identity and org
35870
36208
  overai org list List your organizations
35871
- overai org switch <orgId> Switch the active org
36209
+ overai org switch <orgId> Select the default org
35872
36210
  overai workspace list [--archived] List workspaces you can see in this org
35873
36211
  overai workspace show [workspaceId] Show a workspace's name and overview
35874
36212
  overai workspace users [workspaceId] List users and effective/direct roles
@@ -35951,10 +36289,12 @@ it from stdin. Prefer that for anything long or quote-heavy: an inline value is
35951
36289
  parsed by your shell first, and one apostrophe inside it silently truncates the
35952
36290
  rest. Write @@ to send a literal value that starts with "@".
35953
36291
 
35954
- Organizations: commands run as the clone you're standing in (.overai/manifest.json),
35955
- else the active org from \`org switch\`. The active org is machine-global \u2014 every
35956
- shell shares it \u2014 so scope one command or one shell with OVERAI_ORG_ID=<orgId>
35957
- 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.
35958
36298
 
35959
36299
  Output: table on a TTY, JSON when piped; -o json|table|csv to force.
35960
36300
  Aliases: login = signin, logout = signout, ws = workspace.
@@ -35995,10 +36335,10 @@ var run = async () => {
35995
36335
  return;
35996
36336
  case "signout":
35997
36337
  case "logout":
35998
- await signOut();
36338
+ await signOut(rest.includes("--all"));
35999
36339
  return;
36000
36340
  case "whoami":
36001
- await whoami();
36341
+ whoami();
36002
36342
  return;
36003
36343
  case "org":
36004
36344
  if (rest[0] === "list") {