@sinoia/hubdoc-tools 1.11.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/cli.js +198 -61
  2. package/docs/llm-usage.md +42 -0
  3. package/package.json +1 -1
package/cli.js CHANGED
@@ -42589,9 +42589,9 @@ var require_follow_redirects = __commonJS({
42589
42589
  "search",
42590
42590
  "hash"
42591
42591
  ];
42592
- var events = ["abort", "aborted", "connect", "error", "socket", "timeout"];
42592
+ var events2 = ["abort", "aborted", "connect", "error", "socket", "timeout"];
42593
42593
  var eventHandlers = /* @__PURE__ */ Object.create(null);
42594
- events.forEach(function(event) {
42594
+ events2.forEach(function(event) {
42595
42595
  eventHandlers[event] = function(arg1, arg2, arg3) {
42596
42596
  this._redirectable.emit(event, arg1, arg2, arg3);
42597
42597
  };
@@ -42805,7 +42805,7 @@ var require_follow_redirects = __commonJS({
42805
42805
  }
42806
42806
  var request = this._currentRequest = nativeProtocol.request(this._options, this._onNativeResponse);
42807
42807
  request._redirectable = this;
42808
- for (var event of events) {
42808
+ for (var event of events2) {
42809
42809
  request.on(event, eventHandlers[event]);
42810
42810
  }
42811
42811
  this._currentUrl = /^\//.test(this._options.path) ? url3.format(this._options) : (
@@ -43020,7 +43020,7 @@ var require_follow_redirects = __commonJS({
43020
43020
  return CustomError;
43021
43021
  }
43022
43022
  function destroyRequest(request, error2) {
43023
- for (var event of events) {
43023
+ for (var event of events2) {
43024
43024
  request.removeListener(event, eventHandlers[event]);
43025
43025
  }
43026
43026
  request.on("error", noop2);
@@ -50043,7 +50043,7 @@ var require_parser = __commonJS({
50043
50043
  "node_modules/xml2js/lib/parser.js"(exports2) {
50044
50044
  (function() {
50045
50045
  "use strict";
50046
- var bom, defaults3, defineProperty, events, isEmpty, processItem, processors, sax, setImmediate2, bind2 = function(fn, me) {
50046
+ var bom, defaults3, defineProperty, events2, isEmpty, processItem, processors, sax, setImmediate2, bind2 = function(fn, me) {
50047
50047
  return function() {
50048
50048
  return fn.apply(me, arguments);
50049
50049
  };
@@ -50060,7 +50060,7 @@ var require_parser = __commonJS({
50060
50060
  return child;
50061
50061
  }, hasProp = {}.hasOwnProperty;
50062
50062
  sax = require_sax();
50063
- events = require("events");
50063
+ events2 = require("events");
50064
50064
  bom = require_bom();
50065
50065
  processors = require_processors();
50066
50066
  setImmediate2 = require("timers").setImmediate;
@@ -50398,7 +50398,7 @@ var require_parser = __commonJS({
50398
50398
  })(this));
50399
50399
  };
50400
50400
  return Parser;
50401
- })(events);
50401
+ })(events2);
50402
50402
  exports2.parseString = function(str, a3, b3) {
50403
50403
  var cb, options, parser;
50404
50404
  if (b3 != null) {
@@ -73349,7 +73349,7 @@ var require_dist_cjs69 = __commonJS({
73349
73349
  return value2;
73350
73350
  };
73351
73351
  };
73352
- var sleep = (seconds) => {
73352
+ var sleep2 = (seconds) => {
73353
73353
  return new Promise((resolve) => setTimeout(resolve, seconds * 1e3));
73354
73354
  };
73355
73355
  var waiterServiceDefaults = {
@@ -73416,7 +73416,7 @@ var require_dist_cjs69 = __commonJS({
73416
73416
  if (Date.now() + delay5 * 1e3 > waitUntil) {
73417
73417
  return { state: exports2.WaiterState.TIMEOUT, observedResponses };
73418
73418
  }
73419
- await sleep(delay5);
73419
+ await sleep2(delay5);
73420
73420
  const { state: state5, reason: reason2 } = await acceptorChecks(client, input);
73421
73421
  if (reason2) {
73422
73422
  const message = createMessageFromResponse(reason2);
@@ -86010,7 +86010,7 @@ var require_dist_cjs72 = __commonJS({
86010
86010
  var abortController = require_dist_cjs71();
86011
86011
  var middlewareEndpoint = require_dist_cjs42();
86012
86012
  var smithyClient = require_dist_cjs20();
86013
- var events = require("events");
86013
+ var events2 = require("events");
86014
86014
  var buffer2 = require("buffer");
86015
86015
  var runtimeConfig = require_runtimeConfig3();
86016
86016
  var stream5 = require("stream");
@@ -86166,7 +86166,7 @@ var require_dist_cjs72 = __commonJS({
86166
86166
  }
86167
86167
  throw new Error("Body Data is unsupported format, expected data to be one of: string | Uint8Array | Buffer | Readable | ReadableStream | Blob;.");
86168
86168
  };
86169
- var Upload2 = class _Upload extends events.EventEmitter {
86169
+ var Upload2 = class _Upload extends events2.EventEmitter {
86170
86170
  static MIN_PART_SIZE = 1024 * 1024 * 5;
86171
86171
  MAX_PARTS = 1e4;
86172
86172
  queueSize = 4;
@@ -86229,7 +86229,7 @@ var require_dist_cjs72 = __commonJS({
86229
86229
  const params = { ...this.params, Body: dataPart.data };
86230
86230
  const clientConfig = this.client.config;
86231
86231
  const requestHandler = clientConfig.requestHandler;
86232
- const eventEmitter = requestHandler instanceof events.EventEmitter ? requestHandler : null;
86232
+ const eventEmitter = requestHandler instanceof events2.EventEmitter ? requestHandler : null;
86233
86233
  const uploadEventListener = (event) => {
86234
86234
  this.bytesUploadedSoFar = event.loaded;
86235
86235
  this.totalBytes = event.total;
@@ -86325,7 +86325,7 @@ var require_dist_cjs72 = __commonJS({
86325
86325
  }
86326
86326
  const partSize = byteLength(dataPart.data) || 0;
86327
86327
  const requestHandler = this.client.config.requestHandler;
86328
- const eventEmitter = requestHandler instanceof events.EventEmitter ? requestHandler : null;
86328
+ const eventEmitter = requestHandler instanceof events2.EventEmitter ? requestHandler : null;
86329
86329
  let lastSeenBytes = 0;
86330
86330
  const uploadEventListener = (event, request) => {
86331
86331
  const requestPartSize = Number(request.query["partNumber"]) || -1;
@@ -95034,7 +95034,7 @@ var require_bignumber = __commonJS({
95034
95034
  "node_modules/bignumber.js/bignumber.js"(exports2, module2) {
95035
95035
  (function(globalObject) {
95036
95036
  "use strict";
95037
- var BigNumber, isNumeric = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i, mathceil = Math.ceil, mathfloor = Math.floor, bignumberError = "[BigNumber Error] ", tooManyDigits = bignumberError + "Number primitive has more than 15 significant digits: ", BASE5 = 1e14, LOG_BASE = 14, MAX_SAFE_INTEGER = 9007199254740991, POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13], SQRT_BASE = 1e7, MAX = 1e9;
95037
+ var BigNumber, isNumeric = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i, mathceil = Math.ceil, mathfloor = Math.floor, bignumberError = "[BigNumber Error] ", tooManyDigits = bignumberError + "Number primitive has more than 15 significant digits: ", BASE6 = 1e14, LOG_BASE = 14, MAX_SAFE_INTEGER = 9007199254740991, POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13], SQRT_BASE = 1e7, MAX = 1e9;
95038
95038
  function clone(configObject) {
95039
95039
  var div, convertBase, parseNumeric, P = BigNumber2.prototype = { constructor: BigNumber2, toString: null, valueOf: null }, ONE = new BigNumber2(1), DECIMAL_PLACES = 20, ROUNDING_MODE = 4, TO_EXP_NEG = -7, TO_EXP_POS = 21, MIN_EXP = -1e7, MAX_EXP = 1e7, CRYPTO = false, MODULO_MODE = 1, POW_PRECISION = 0, FORMAT = {
95040
95040
  prefix: "",
@@ -95286,7 +95286,7 @@ var require_bignumber = __commonJS({
95286
95286
  if (String(c3[0]).length == i3) {
95287
95287
  for (i3 = 0; i3 < c3.length; i3++) {
95288
95288
  n3 = c3[i3];
95289
- if (n3 < 0 || n3 >= BASE5 || n3 !== mathfloor(n3)) break out;
95289
+ if (n3 < 0 || n3 >= BASE6 || n3 !== mathfloor(n3)) break out;
95290
95290
  }
95291
95291
  if (n3 !== 0) return true;
95292
95292
  }
@@ -95503,7 +95503,7 @@ var require_bignumber = __commonJS({
95503
95503
  e3 = x3.e - y2.e;
95504
95504
  s3 = dp + e3 + 1;
95505
95505
  if (!base) {
95506
- base = BASE5;
95506
+ base = BASE6;
95507
95507
  e3 = bitFloor(x3.e / LOG_BASE) - bitFloor(y2.e / LOG_BASE);
95508
95508
  s3 = s3 / LOG_BASE | 0;
95509
95509
  }
@@ -95582,7 +95582,7 @@ var require_bignumber = __commonJS({
95582
95582
  more = rem[0] != null;
95583
95583
  if (!qc[0]) qc.splice(0, 1);
95584
95584
  }
95585
- if (base == BASE5) {
95585
+ if (base == BASE6) {
95586
95586
  for (i3 = 1, s3 = qc[0]; s3 >= 10; s3 /= 10, i3++) ;
95587
95587
  round(q3, dp + (q3.e = i3 + e3 * LOG_BASE - 1) + 1, rm, more);
95588
95588
  } else {
@@ -95741,12 +95741,12 @@ var require_bignumber = __commonJS({
95741
95741
  for (k3 = 1; j3 >= 10; j3 /= 10, k3++) ;
95742
95742
  if (i3 != k3) {
95743
95743
  x3.e++;
95744
- if (xc[0] == BASE5) xc[0] = 1;
95744
+ if (xc[0] == BASE6) xc[0] = 1;
95745
95745
  }
95746
95746
  break;
95747
95747
  } else {
95748
95748
  xc[ni] += k3;
95749
- if (xc[ni] != BASE5) break;
95749
+ if (xc[ni] != BASE6) break;
95750
95750
  xc[ni--] = 0;
95751
95751
  k3 = 1;
95752
95752
  }
@@ -95955,12 +95955,12 @@ var require_bignumber = __commonJS({
95955
95955
  }
95956
95956
  b3 = (j3 = yc.length) - (i3 = xc.length);
95957
95957
  if (b3 > 0) for (; b3--; xc[i3++] = 0) ;
95958
- b3 = BASE5 - 1;
95958
+ b3 = BASE6 - 1;
95959
95959
  for (; j3 > a3; ) {
95960
95960
  if (xc[--j3] < yc[j3]) {
95961
95961
  for (i3 = j3; i3 && !xc[--i3]; xc[i3] = b3) ;
95962
95962
  --xc[i3];
95963
- xc[j3] += BASE5;
95963
+ xc[j3] += BASE6;
95964
95964
  }
95965
95965
  xc[j3] -= yc[j3];
95966
95966
  }
@@ -96022,7 +96022,7 @@ var require_bignumber = __commonJS({
96022
96022
  ycL = i3;
96023
96023
  }
96024
96024
  for (i3 = xcL + ycL, zc = []; i3--; zc.push(0)) ;
96025
- base = BASE5;
96025
+ base = BASE6;
96026
96026
  sqrtBase = SQRT_BASE;
96027
96027
  for (i3 = ycL; --i3 >= 0; ) {
96028
96028
  c3 = 0;
@@ -96088,8 +96088,8 @@ var require_bignumber = __commonJS({
96088
96088
  b3 = a3;
96089
96089
  }
96090
96090
  for (a3 = 0; b3; ) {
96091
- a3 = (xc[--b3] = xc[b3] + yc[b3] + a3) / BASE5 | 0;
96092
- xc[b3] = BASE5 === xc[b3] ? 0 : xc[b3] % BASE5;
96091
+ a3 = (xc[--b3] = xc[b3] + yc[b3] + a3) / BASE6 | 0;
96092
+ xc[b3] = BASE6 === xc[b3] ? 0 : xc[b3] % BASE6;
96093
96093
  }
96094
96094
  if (a3) {
96095
96095
  xc = [a3].concat(xc);
@@ -672699,11 +672699,11 @@ var ListPrompt = class extends Prompt {
672699
672699
  */
672700
672700
  _run(cb) {
672701
672701
  this.done = cb;
672702
- const events = observe(this.rl);
672703
- events.normalizedUpKey.pipe((0, import_rxjs3.takeUntil)(events.line)).forEach(this.onUpKey.bind(this));
672704
- events.normalizedDownKey.pipe((0, import_rxjs3.takeUntil)(events.line)).forEach(this.onDownKey.bind(this));
672705
- events.numberKey.pipe((0, import_rxjs3.takeUntil)(events.line)).forEach(this.onNumberKey.bind(this));
672706
- events.line.pipe(
672702
+ const events2 = observe(this.rl);
672703
+ events2.normalizedUpKey.pipe((0, import_rxjs3.takeUntil)(events2.line)).forEach(this.onUpKey.bind(this));
672704
+ events2.normalizedDownKey.pipe((0, import_rxjs3.takeUntil)(events2.line)).forEach(this.onDownKey.bind(this));
672705
+ events2.numberKey.pipe((0, import_rxjs3.takeUntil)(events2.line)).forEach(this.onNumberKey.bind(this));
672706
+ events2.line.pipe(
672707
672707
  (0, import_rxjs3.take)(1),
672708
672708
  (0, import_rxjs3.map)(this.getCurrentValue.bind(this)),
672709
672709
  (0, import_rxjs3.flatMap)(
@@ -672816,12 +672816,12 @@ var InputPrompt = class extends Prompt {
672816
672816
  */
672817
672817
  _run(cb) {
672818
672818
  this.done = cb;
672819
- const events = observe(this.rl);
672820
- const submit = events.line.pipe((0, import_rxjs4.map)(this.filterInput.bind(this)));
672819
+ const events2 = observe(this.rl);
672820
+ const submit = events2.line.pipe((0, import_rxjs4.map)(this.filterInput.bind(this)));
672821
672821
  const validation = this.handleSubmitEvents(submit);
672822
672822
  validation.success.forEach(this.onEnd.bind(this));
672823
672823
  validation.error.forEach(this.onError.bind(this));
672824
- events.keypress.pipe((0, import_rxjs4.takeUntil)(validation.success)).forEach(this.onKeypress.bind(this));
672824
+ events2.keypress.pipe((0, import_rxjs4.takeUntil)(validation.success)).forEach(this.onKeypress.bind(this));
672825
672825
  this.render();
672826
672826
  return this;
672827
672827
  }
@@ -672918,9 +672918,9 @@ var ConfirmPrompt = class extends Prompt {
672918
672918
  */
672919
672919
  _run(cb) {
672920
672920
  this.done = cb;
672921
- const events = observe(this.rl);
672922
- events.keypress.pipe((0, import_rxjs5.takeUntil)(events.line)).forEach(this.onKeypress.bind(this));
672923
- events.line.pipe((0, import_rxjs5.take)(1)).forEach(this.onEnd.bind(this));
672921
+ const events2 = observe(this.rl);
672922
+ events2.keypress.pipe((0, import_rxjs5.takeUntil)(events2.line)).forEach(this.onKeypress.bind(this));
672923
+ events2.line.pipe((0, import_rxjs5.take)(1)).forEach(this.onEnd.bind(this));
672924
672924
  this.render();
672925
672925
  return this;
672926
672926
  }
@@ -673001,14 +673001,14 @@ var RawListPrompt = class extends Prompt {
673001
673001
  */
673002
673002
  _run(cb) {
673003
673003
  this.done = cb;
673004
- const events = observe(this.rl);
673005
- const submit = events.line.pipe((0, import_rxjs6.map)(this.getCurrentValue.bind(this)));
673004
+ const events2 = observe(this.rl);
673005
+ const submit = events2.line.pipe((0, import_rxjs6.map)(this.getCurrentValue.bind(this)));
673006
673006
  const validation = this.handleSubmitEvents(submit);
673007
673007
  validation.success.forEach(this.onEnd.bind(this));
673008
673008
  validation.error.forEach(this.onError.bind(this));
673009
- events.normalizedUpKey.pipe((0, import_rxjs6.takeUntil)(validation.success)).forEach(this.onUpKey.bind(this));
673010
- events.normalizedDownKey.pipe((0, import_rxjs6.takeUntil)(validation.success)).forEach(this.onDownKey.bind(this));
673011
- events.keypress.pipe((0, import_rxjs6.takeUntil)(validation.success)).forEach(this.onKeypress.bind(this));
673009
+ events2.normalizedUpKey.pipe((0, import_rxjs6.takeUntil)(validation.success)).forEach(this.onUpKey.bind(this));
673010
+ events2.normalizedDownKey.pipe((0, import_rxjs6.takeUntil)(validation.success)).forEach(this.onDownKey.bind(this));
673011
+ events2.keypress.pipe((0, import_rxjs6.takeUntil)(validation.success)).forEach(this.onKeypress.bind(this));
673012
673012
  this.render();
673013
673013
  return this;
673014
673014
  }
@@ -673145,13 +673145,13 @@ var ExpandPrompt = class extends Prompt {
673145
673145
  */
673146
673146
  _run(cb) {
673147
673147
  this.done = cb;
673148
- const events = observe(this.rl);
673148
+ const events2 = observe(this.rl);
673149
673149
  const validation = this.handleSubmitEvents(
673150
- events.line.pipe((0, import_rxjs7.map)(this.getCurrentValue.bind(this)))
673150
+ events2.line.pipe((0, import_rxjs7.map)(this.getCurrentValue.bind(this)))
673151
673151
  );
673152
673152
  validation.success.forEach(this.onSubmit.bind(this));
673153
673153
  validation.error.forEach(this.onError.bind(this));
673154
- this.keypressObs = events.keypress.pipe((0, import_rxjs7.takeUntil)(validation.success)).forEach(this.onKeypress.bind(this));
673154
+ this.keypressObs = events2.keypress.pipe((0, import_rxjs7.takeUntil)(validation.success)).forEach(this.onKeypress.bind(this));
673155
673155
  this.render();
673156
673156
  return this;
673157
673157
  }
@@ -673338,18 +673338,18 @@ var CheckboxPrompt = class extends Prompt {
673338
673338
  */
673339
673339
  _run(cb) {
673340
673340
  this.done = cb;
673341
- const events = observe(this.rl);
673341
+ const events2 = observe(this.rl);
673342
673342
  const validation = this.handleSubmitEvents(
673343
- events.line.pipe((0, import_rxjs8.map)(this.getCurrentValue.bind(this)))
673343
+ events2.line.pipe((0, import_rxjs8.map)(this.getCurrentValue.bind(this)))
673344
673344
  );
673345
673345
  validation.success.forEach(this.onEnd.bind(this));
673346
673346
  validation.error.forEach(this.onError.bind(this));
673347
- events.normalizedUpKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onUpKey.bind(this));
673348
- events.normalizedDownKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onDownKey.bind(this));
673349
- events.numberKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onNumberKey.bind(this));
673350
- events.spaceKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onSpaceKey.bind(this));
673351
- events.aKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onAllKey.bind(this));
673352
- events.iKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onInverseKey.bind(this));
673347
+ events2.normalizedUpKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onUpKey.bind(this));
673348
+ events2.normalizedDownKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onDownKey.bind(this));
673349
+ events2.numberKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onNumberKey.bind(this));
673350
+ events2.spaceKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onSpaceKey.bind(this));
673351
+ events2.aKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onAllKey.bind(this));
673352
+ events2.iKey.pipe((0, import_rxjs8.takeUntil)(validation.success)).forEach(this.onInverseKey.bind(this));
673353
673353
  this.render();
673354
673354
  this.firstRender = false;
673355
673355
  return this;
@@ -673502,12 +673502,12 @@ var PasswordPrompt = class extends Prompt {
673502
673502
  */
673503
673503
  _run(cb) {
673504
673504
  this.done = cb;
673505
- const events = observe(this.rl);
673506
- const submit = events.line.pipe((0, import_rxjs9.map)(this.filterInput.bind(this)));
673505
+ const events2 = observe(this.rl);
673506
+ const submit = events2.line.pipe((0, import_rxjs9.map)(this.filterInput.bind(this)));
673507
673507
  const validation = this.handleSubmitEvents(submit);
673508
673508
  validation.success.forEach(this.onEnd.bind(this));
673509
673509
  validation.error.forEach(this.onError.bind(this));
673510
- events.keypress.pipe((0, import_rxjs9.takeUntil)(validation.success)).forEach(this.onKeypress.bind(this));
673510
+ events2.keypress.pipe((0, import_rxjs9.takeUntil)(validation.success)).forEach(this.onKeypress.bind(this));
673511
673511
  this.render();
673512
673512
  return this;
673513
673513
  }
@@ -673774,8 +673774,8 @@ var EditorPrompt = class extends Prompt {
673774
673774
  _run(cb) {
673775
673775
  this.done = cb;
673776
673776
  this.editorResult = new import_rxjs10.Subject();
673777
- const events = observe(this.rl);
673778
- this.lineSubscription = events.line.subscribe(this.startExternalEditor.bind(this));
673777
+ const events2 = observe(this.rl);
673778
+ this.lineSubscription = events2.line.subscribe(this.startExternalEditor.bind(this));
673779
673779
  const waitUserInput = this.opt.waitUserInput === void 0 ? true : this.opt.waitUserInput;
673780
673780
  const validation = this.handleSubmitEvents(this.editorResult);
673781
673781
  validation.success.forEach(this.onEnd.bind(this));
@@ -730850,7 +730850,7 @@ var DeviceAuthService = class {
730850
730850
  * Honors `slow_down` by widening the interval (RFC 8628 §3.5).
730851
730851
  */
730852
730852
  async pollUntilDone(deviceCode, opts) {
730853
- const sleep = opts.sleep || defaultSleep;
730853
+ const sleep2 = opts.sleep || defaultSleep;
730854
730854
  let intervalMs = Math.max(1, opts.interval) * 1e3;
730855
730855
  const caps = [Date.now() + opts.expiresIn * 1e3];
730856
730856
  if (opts.timeoutMs != null) caps.push(Date.now() + opts.timeoutMs);
@@ -730880,7 +730880,7 @@ var DeviceAuthService = class {
730880
730880
  "Timed out waiting for device approval. Run `hubdoc login --start` again."
730881
730881
  );
730882
730882
  }
730883
- await sleep(intervalMs);
730883
+ await sleep2(intervalMs);
730884
730884
  }
730885
730885
  }
730886
730886
  };
@@ -734683,6 +734683,136 @@ async function handleAgentsShow(id, opts) {
734683
734683
  }
734684
734684
  }
734685
734685
 
734686
+ // apps/cli/cli/handlers/event-handlers.ts
734687
+ var BASE5 = "/api/v1/events";
734688
+ var EVENT_COLUMNS = [
734689
+ { header: "Event ID", key: "event_id" },
734690
+ { header: "Type", key: "type", format: (v6) => shortType(v6) },
734691
+ { header: "At", key: "timestamp" }
734692
+ ];
734693
+ var TYPE_ALIASES = {
734694
+ // Projects
734695
+ "project.created": "Projects::Projects::ProjectCreated",
734696
+ "project.updated": "Projects::Projects::ProjectUpdated",
734697
+ "project.started": "Projects::Projects::ProjectStarted",
734698
+ "project.completed": "Projects::Projects::ProjectCompleted",
734699
+ "project.archived": "Projects::Projects::ProjectArchived",
734700
+ "project.deleted": "Projects::Projects::ProjectDeleted",
734701
+ // Sprints
734702
+ "sprint.created": "Projects::Sprints::SprintCreated",
734703
+ "sprint.updated": "Projects::Sprints::SprintUpdated",
734704
+ "sprint.started": "Projects::Sprints::SprintStarted",
734705
+ "sprint.completed": "Projects::Sprints::SprintCompleted",
734706
+ "sprint.deleted": "Projects::Sprints::SprintDeleted",
734707
+ // Tickets
734708
+ "ticket.created": "Projects::Tickets::TicketCreated",
734709
+ "ticket.updated": "Projects::Tickets::TicketUpdated",
734710
+ "ticket.assigned": "Projects::Tickets::TicketAssigned",
734711
+ "ticket.blocked": "Projects::Tickets::TicketBlocked",
734712
+ "ticket.escalated": "Projects::Tickets::TicketEscalated",
734713
+ "ticket.failed": "Projects::Tickets::TicketFailed",
734714
+ "ticket.moved": "Projects::Tickets::TicketMoved",
734715
+ "ticket.status_changed": "Projects::Tickets::TicketStatusChanged",
734716
+ "ticket.deleted": "Projects::Tickets::TicketDeleted",
734717
+ "ticket.comment": "Projects::Tickets::ChannelMessagePosted",
734718
+ "ticket.deliverable": "Projects::Tickets::DeliverableAttached",
734719
+ // Tasks
734720
+ "task.created": "Projects::Tasks::TaskCreated",
734721
+ "task.updated": "Projects::Tasks::TaskUpdated",
734722
+ "task.completed": "Projects::Tasks::TaskCompleted",
734723
+ "task.deleted": "Projects::Tasks::TaskDeleted"
734724
+ };
734725
+ function expandTypes(raw) {
734726
+ if (raw == null) return void 0;
734727
+ const items = raw.split(",").map((s3) => s3.trim()).filter(Boolean).map((s3) => TYPE_ALIASES[s3] ?? s3);
734728
+ return items.length > 0 ? items.join(",") : void 0;
734729
+ }
734730
+ function shortType(fq) {
734731
+ if (!fq) return "";
734732
+ const inverted = Object.entries(TYPE_ALIASES).find(([, v6]) => v6 === fq)?.[0];
734733
+ if (inverted) return inverted;
734734
+ return fq.split("::").pop() ?? fq;
734735
+ }
734736
+ async function fetchEventsPage(ctx, opts) {
734737
+ const params = {};
734738
+ if (opts.project) params.project_id = opts.project;
734739
+ if (opts.ticket) params.ticket_id = opts.ticket;
734740
+ const expanded = expandTypes(opts.type);
734741
+ if (expanded) params.type = expanded;
734742
+ if (opts.since) params.since = opts.since;
734743
+ if (opts.limit) params.limit = Number(opts.limit);
734744
+ const res = await ctx.axios.get(BASE5, { params });
734745
+ const items = Array.isArray(res.data) ? res.data : [];
734746
+ const headers = res.headers ?? {};
734747
+ const nextCursor = headers["x-next-cursor"] ?? headers["X-Next-Cursor"] ?? null;
734748
+ return { items, nextCursor };
734749
+ }
734750
+ async function handleEventsList(opts) {
734751
+ const out = output(opts);
734752
+ const ctx = await buildApiContext(out);
734753
+ try {
734754
+ const { items, nextCursor } = await fetchEventsPage(ctx, opts);
734755
+ if (opts.json) {
734756
+ out.show({ items, next_cursor: nextCursor });
734757
+ return;
734758
+ }
734759
+ out.list(items, EVENT_COLUMNS);
734760
+ if (nextCursor) {
734761
+ out.note(`next_cursor: ${nextCursor} (pass to --since to continue)`);
734762
+ }
734763
+ } catch (err) {
734764
+ out.fail(err);
734765
+ }
734766
+ }
734767
+ async function handleEventsWatch(opts) {
734768
+ const out = output(opts);
734769
+ const ctx = await buildApiContext(out);
734770
+ const timeoutMs = Math.max(1e3, Number(opts.timeout ?? "60") * 1e3);
734771
+ const intervalMs = Math.max(100, Number(opts.pollIntervalMs ?? "1000"));
734772
+ const startedAt = Date.now();
734773
+ let cursor2 = opts.since;
734774
+ try {
734775
+ while (Date.now() - startedAt < timeoutMs) {
734776
+ const page = await fetchEventsPage(ctx, { ...opts, since: cursor2 });
734777
+ if (page.items.length > 0) {
734778
+ if (opts.json) {
734779
+ out.show({
734780
+ items: page.items,
734781
+ next_cursor: page.nextCursor,
734782
+ waited_ms: Date.now() - startedAt
734783
+ });
734784
+ } else {
734785
+ out.list(page.items, EVENT_COLUMNS);
734786
+ if (page.nextCursor) {
734787
+ out.note(`next_cursor: ${page.nextCursor}`);
734788
+ }
734789
+ }
734790
+ return;
734791
+ }
734792
+ await sleep(intervalMs);
734793
+ }
734794
+ } catch (err) {
734795
+ out.fail(err);
734796
+ }
734797
+ const waited = Date.now() - startedAt;
734798
+ const payload2 = {
734799
+ ok: false,
734800
+ reason: "timeout",
734801
+ waited_ms: waited,
734802
+ since: cursor2 ?? null
734803
+ };
734804
+ if (opts.json) {
734805
+ process.stderr.write(JSON.stringify(payload2, null, 2) + "\n");
734806
+ } else {
734807
+ process.stderr.write(`Timed out after ${waited}ms with no matching event.
734808
+ `);
734809
+ }
734810
+ process.exit(2);
734811
+ }
734812
+ function sleep(ms) {
734813
+ return new Promise((resolve) => setTimeout(resolve, ms));
734814
+ }
734815
+
734686
734816
  // apps/cli/cli/handlers/task-handlers.ts
734687
734817
  var tasksBase = (pid, tid) => `/api/v1/projects/${encodeURIComponent(pid)}/tickets/${encodeURIComponent(tid)}/tasks`;
734688
734818
  var TASK_COLUMNS = [
@@ -734857,7 +734987,7 @@ async function handleTasksReorder(opts) {
734857
734987
  // apps/cli/cli.ts
734858
734988
  var getVersion = () => {
734859
734989
  try {
734860
- if (true) return "1.11.0";
734990
+ if (true) return "1.12.0";
734861
734991
  } catch {
734862
734992
  }
734863
734993
  for (const candidate of [
@@ -735139,13 +735269,13 @@ members.command("remove <membership-id>").description("Remove a membership by it
735139
735269
  await handleGroupMembersRemove(id, withGlobals(options));
735140
735270
  });
735141
735271
  var permissions = program2.command("permissions").description("Manage ACL: grant / list / revoke permissions on documents resources");
735142
- permissions.command("ls").description("List permissions on a specific resource").requiredOption("--on <resource-id>", "Permissible resource UUID").option("--on-type <type>", "workspace | folder | file | share_link", "workspace").option("--to <actor-id>", "Filter by actor id (client-side)").option("--to-type <type>", "Filter by actor type (user | group | contact)").option("--level <level>", "Filter by level (read|write|admin|owner|forbidden)").action(async (options) => {
735272
+ permissions.command("ls").description("List permissions on a specific resource").requiredOption("--on <resource-id>", "Permissible resource UUID").option("--on-type <type>", "workspace | folder | file | share_link | project", "workspace").option("--to <actor-id>", "Filter by actor id (client-side)").option("--to-type <type>", "Filter by actor type (user | group | contact)").option("--level <level>", "Filter by level (read|write|admin|owner|forbidden)").action(async (options) => {
735143
735273
  await handlePermissionsList(withGlobals(options));
735144
735274
  });
735145
735275
  permissions.command("show <id>").description("Show a permission by id").action(async (id, options) => {
735146
735276
  await handlePermissionsShow(id, withGlobals(options));
735147
735277
  });
735148
- permissions.command("grant").description("Grant a permission on a resource to a user or group").requiredOption("--to <actor-id>", "Actor UUID (user/group/contact)").requiredOption("--to-type <type>", "user | group | contact").requiredOption("--on <resource-id>", "Permissible resource UUID").requiredOption("--on-type <type>", "workspace | folder | file | share_link").requiredOption("--level <level>", "read | write | admin | owner | forbidden").option("--temporary", "Mark as temporary (auto-expiring per server policy)").action(async (options) => {
735278
+ permissions.command("grant").description("Grant a permission on a resource to a user or group").requiredOption("--to <actor-id>", "Actor UUID (user/group/contact)").requiredOption("--to-type <type>", "user | group | contact").requiredOption("--on <resource-id>", "Permissible resource UUID").requiredOption("--on-type <type>", "workspace | folder | file | share_link | project").requiredOption("--level <level>", "read | write | admin | owner | forbidden").option("--temporary", "Mark as temporary (auto-expiring per server policy)").action(async (options) => {
735149
735279
  await handlePermissionsGrant(withGlobals(options));
735150
735280
  });
735151
735281
  permissions.command("revoke <id>").description("Revoke a permission by id").option("--yes", "Skip the interactive confirmation").action(async (id, options) => {
@@ -735267,6 +735397,13 @@ agents.command("ls").alias("list").description("List agents").option("--active",
735267
735397
  agents.command("show <id>").description("Show an agent").action(async (id, options) => {
735268
735398
  await handleAgentsShow(id, withGlobals(options));
735269
735399
  });
735400
+ var events = program2.command("events").description("Read the Rails Event Store stream (corex#593)");
735401
+ events.command("ls").alias("list").description("One-shot cursor-paginated read of the event stream").option("--project <id>", "Filter to events touching a specific project").option("--ticket <id>", "Filter to events on a specific ticket").option("--type <a,b,c>", "Comma-separated event types (aliases like ticket.status_changed OR full RES class names)").option("--since <cursor>", "Read events strictly after this event_id").option("--limit <n>", "Max events (default 100, server-side max 1000)").action(async (options) => {
735402
+ await handleEventsList(withGlobals(options));
735403
+ });
735404
+ events.command("watch").description("Block until a matching event arrives or the timeout expires (client-side long-poll)").option("--project <id>", "Filter to events touching a specific project").option("--ticket <id>", "Filter to events on a specific ticket").option("--type <a,b,c>", "Comma-separated event types (aliases or full class names)").option("--since <cursor>", "Start watching from this event_id (exclusive)").option("--limit <n>", "Max events per poll (default 100)").option("--timeout <s>", "Give up after this many seconds (default 60, exit 2 on timeout)").option("--poll-interval-ms <ms>", "Delay between polls (default 1000, min 100)").action(async (options) => {
735405
+ await handleEventsWatch(withGlobals(options));
735406
+ });
735270
735407
  program2.parse();
735271
735408
  /*! Bundled license information:
735272
735409
 
package/docs/llm-usage.md CHANGED
@@ -408,6 +408,48 @@ without going through a workspace-scoped ACL. Example:
408
408
  `hubdoc permissions grant --to <user-id> --to-type user --on <project-id>
409
409
  --on-type project --level admin`.
410
410
 
411
+ ### Events — react to what's happening (corex#593)
412
+
413
+ `hubdoc events ls` and `hubdoc events watch` sit on top of the Rails
414
+ Event Store stream. Every mutation done by `projects/sprints/tickets/
415
+ tasks` (create, update, status_changed, moved, deliverable_attached,
416
+ channel_message_posted, …) is published as a typed event; the CLI lets
417
+ an agent either **poll** the stream once (`ls`) or **block** until
418
+ something happens (`watch`).
419
+
420
+ - **Type aliases** (agent-friendly): `ticket.created | ticket.updated |
421
+ ticket.status_changed | ticket.assigned | ticket.blocked |
422
+ ticket.escalated | ticket.failed | ticket.moved | ticket.comment |
423
+ ticket.deliverable | ticket.deleted | sprint.{created,started,updated,
424
+ completed,deleted} | project.{created,updated,started,completed,
425
+ archived,deleted} | task.{created,updated,completed,deleted}`. Full RES
426
+ class names (`Projects::Tickets::TicketStatusChanged`) are also
427
+ accepted verbatim.
428
+ - **Cursor**: each `ls` response includes `next_cursor` — pass it as
429
+ `--since` on the next call to resume. `watch` re-uses the same `since`
430
+ across empty polls (never skips an event that arrives mid-poll).
431
+ - **Timeout**: `watch --timeout <s>` (default 60) — exit code 2 with a
432
+ `{ ok:false, reason:"timeout", waited_ms, since }` envelope on stderr
433
+ when the window expires. This is distinct from network errors (exit 1).
434
+ - **Poll cadence**: `watch --poll-interval-ms <n>` (default 1000, min
435
+ 100). Kept short so the perceived latency stays low; harmless because
436
+ each poll is a lightweight bare-array read.
437
+
438
+ Two typical patterns:
439
+
440
+ ```bash
441
+ # 1) Wait for the dispatched agent to finish before moving on.
442
+ hubdoc events watch --project "$PID" --ticket "$TID" \
443
+ --type ticket.status_changed --timeout 900 --json \
444
+ | jq -r '.items[-1].data.new_status' # → done / failed / blocked
445
+ # (returns as soon as the first matching event arrives)
446
+
447
+ # 2) Loop over the day's activity from a saved checkpoint.
448
+ CURSOR=$(cat .last-cursor 2>/dev/null || echo "")
449
+ hubdoc events ls --project "$PID" --since "$CURSOR" --limit 200 --json \
450
+ | tee day-batch.json | jq -r '.next_cursor' > .last-cursor
451
+ ```
452
+
411
453
  `hubdoc tasks --project=<pid> --ticket=<tid>` — `ls | show | create |
412
454
  update | delete | complete | reorder`. Sub-tasks live under a ticket;
413
455
  both parents are required on every call.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinoia/hubdoc-tools",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Professional command-line tool for HubDoc document management and bulk import/export",
5
5
  "main": "cli.js",
6
6
  "bin": {