oh-my-til 1.1.2 → 1.3.1-dev.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.
package/dist/cli.js CHANGED
@@ -32,24 +32,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
32
32
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
33
33
  mod
34
34
  ));
35
- var __accessCheck = (obj, member, msg) => {
36
- if (!member.has(obj))
37
- throw TypeError("Cannot " + msg);
38
- };
39
- var __privateGet = (obj, member, getter) => {
40
- __accessCheck(obj, member, "read from private field");
41
- return getter ? getter.call(obj) : member.get(obj);
42
- };
43
- var __privateAdd = (obj, member, value) => {
44
- if (member.has(obj))
45
- throw TypeError("Cannot add the same private member more than once");
46
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
47
- };
48
- var __privateSet = (obj, member, value, setter) => {
49
- __accessCheck(obj, member, "write to private field");
50
- setter ? setter.call(obj, value) : member.set(obj, value);
51
- return value;
52
- };
53
35
 
54
36
  // node_modules/yaml/dist/nodes/identity.js
55
37
  var require_identity = __commonJS({
@@ -128,17 +110,17 @@ var require_visit = __commonJS({
128
110
  visit.BREAK = BREAK;
129
111
  visit.SKIP = SKIP;
130
112
  visit.REMOVE = REMOVE;
131
- function visit_(key, node, visitor, path6) {
132
- const ctrl = callVisitor(key, node, visitor, path6);
113
+ function visit_(key, node, visitor, path7) {
114
+ const ctrl = callVisitor(key, node, visitor, path7);
133
115
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
134
- replaceNode(key, path6, ctrl);
135
- return visit_(key, ctrl, visitor, path6);
116
+ replaceNode(key, path7, ctrl);
117
+ return visit_(key, ctrl, visitor, path7);
136
118
  }
137
119
  if (typeof ctrl !== "symbol") {
138
120
  if (identity.isCollection(node)) {
139
- path6 = Object.freeze(path6.concat(node));
121
+ path7 = Object.freeze(path7.concat(node));
140
122
  for (let i = 0; i < node.items.length; ++i) {
141
- const ci = visit_(i, node.items[i], visitor, path6);
123
+ const ci = visit_(i, node.items[i], visitor, path7);
142
124
  if (typeof ci === "number")
143
125
  i = ci - 1;
144
126
  else if (ci === BREAK)
@@ -149,13 +131,13 @@ var require_visit = __commonJS({
149
131
  }
150
132
  }
151
133
  } else if (identity.isPair(node)) {
152
- path6 = Object.freeze(path6.concat(node));
153
- const ck = visit_("key", node.key, visitor, path6);
134
+ path7 = Object.freeze(path7.concat(node));
135
+ const ck = visit_("key", node.key, visitor, path7);
154
136
  if (ck === BREAK)
155
137
  return BREAK;
156
138
  else if (ck === REMOVE)
157
139
  node.key = null;
158
- const cv = visit_("value", node.value, visitor, path6);
140
+ const cv = visit_("value", node.value, visitor, path7);
159
141
  if (cv === BREAK)
160
142
  return BREAK;
161
143
  else if (cv === REMOVE)
@@ -176,17 +158,17 @@ var require_visit = __commonJS({
176
158
  visitAsync.BREAK = BREAK;
177
159
  visitAsync.SKIP = SKIP;
178
160
  visitAsync.REMOVE = REMOVE;
179
- async function visitAsync_(key, node, visitor, path6) {
180
- const ctrl = await callVisitor(key, node, visitor, path6);
161
+ async function visitAsync_(key, node, visitor, path7) {
162
+ const ctrl = await callVisitor(key, node, visitor, path7);
181
163
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
182
- replaceNode(key, path6, ctrl);
183
- return visitAsync_(key, ctrl, visitor, path6);
164
+ replaceNode(key, path7, ctrl);
165
+ return visitAsync_(key, ctrl, visitor, path7);
184
166
  }
185
167
  if (typeof ctrl !== "symbol") {
186
168
  if (identity.isCollection(node)) {
187
- path6 = Object.freeze(path6.concat(node));
169
+ path7 = Object.freeze(path7.concat(node));
188
170
  for (let i = 0; i < node.items.length; ++i) {
189
- const ci = await visitAsync_(i, node.items[i], visitor, path6);
171
+ const ci = await visitAsync_(i, node.items[i], visitor, path7);
190
172
  if (typeof ci === "number")
191
173
  i = ci - 1;
192
174
  else if (ci === BREAK)
@@ -197,13 +179,13 @@ var require_visit = __commonJS({
197
179
  }
198
180
  }
199
181
  } else if (identity.isPair(node)) {
200
- path6 = Object.freeze(path6.concat(node));
201
- const ck = await visitAsync_("key", node.key, visitor, path6);
182
+ path7 = Object.freeze(path7.concat(node));
183
+ const ck = await visitAsync_("key", node.key, visitor, path7);
202
184
  if (ck === BREAK)
203
185
  return BREAK;
204
186
  else if (ck === REMOVE)
205
187
  node.key = null;
206
- const cv = await visitAsync_("value", node.value, visitor, path6);
188
+ const cv = await visitAsync_("value", node.value, visitor, path7);
207
189
  if (cv === BREAK)
208
190
  return BREAK;
209
191
  else if (cv === REMOVE)
@@ -230,23 +212,23 @@ var require_visit = __commonJS({
230
212
  }
231
213
  return visitor;
232
214
  }
233
- function callVisitor(key, node, visitor, path6) {
215
+ function callVisitor(key, node, visitor, path7) {
234
216
  if (typeof visitor === "function")
235
- return visitor(key, node, path6);
217
+ return visitor(key, node, path7);
236
218
  if (identity.isMap(node))
237
- return visitor.Map?.(key, node, path6);
219
+ return visitor.Map?.(key, node, path7);
238
220
  if (identity.isSeq(node))
239
- return visitor.Seq?.(key, node, path6);
221
+ return visitor.Seq?.(key, node, path7);
240
222
  if (identity.isPair(node))
241
- return visitor.Pair?.(key, node, path6);
223
+ return visitor.Pair?.(key, node, path7);
242
224
  if (identity.isScalar(node))
243
- return visitor.Scalar?.(key, node, path6);
225
+ return visitor.Scalar?.(key, node, path7);
244
226
  if (identity.isAlias(node))
245
- return visitor.Alias?.(key, node, path6);
227
+ return visitor.Alias?.(key, node, path7);
246
228
  return void 0;
247
229
  }
248
- function replaceNode(key, path6, node) {
249
- const parent = path6[path6.length - 1];
230
+ function replaceNode(key, path7, node) {
231
+ const parent = path7[path7.length - 1];
250
232
  if (identity.isCollection(parent)) {
251
233
  parent.items[key] = node;
252
234
  } else if (identity.isPair(parent)) {
@@ -854,10 +836,10 @@ var require_Collection = __commonJS({
854
836
  var createNode = require_createNode();
855
837
  var identity = require_identity();
856
838
  var Node = require_Node();
857
- function collectionFromPath(schema, path6, value) {
839
+ function collectionFromPath(schema, path7, value) {
858
840
  let v = value;
859
- for (let i = path6.length - 1; i >= 0; --i) {
860
- const k = path6[i];
841
+ for (let i = path7.length - 1; i >= 0; --i) {
842
+ const k = path7[i];
861
843
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
862
844
  const a = [];
863
845
  a[k] = v;
@@ -876,7 +858,7 @@ var require_Collection = __commonJS({
876
858
  sourceObjects: /* @__PURE__ */ new Map()
877
859
  });
878
860
  }
879
- var isEmptyPath = (path6) => path6 == null || typeof path6 === "object" && !!path6[Symbol.iterator]().next().done;
861
+ var isEmptyPath = (path7) => path7 == null || typeof path7 === "object" && !!path7[Symbol.iterator]().next().done;
880
862
  var Collection = class extends Node.NodeBase {
881
863
  constructor(type, schema) {
882
864
  super(type);
@@ -906,11 +888,11 @@ var require_Collection = __commonJS({
906
888
  * be a Pair instance or a `{ key, value }` object, which may not have a key
907
889
  * that already exists in the map.
908
890
  */
909
- addIn(path6, value) {
910
- if (isEmptyPath(path6))
891
+ addIn(path7, value) {
892
+ if (isEmptyPath(path7))
911
893
  this.add(value);
912
894
  else {
913
- const [key, ...rest] = path6;
895
+ const [key, ...rest] = path7;
914
896
  const node = this.get(key, true);
915
897
  if (identity.isCollection(node))
916
898
  node.addIn(rest, value);
@@ -924,8 +906,8 @@ var require_Collection = __commonJS({
924
906
  * Removes a value from the collection.
925
907
  * @returns `true` if the item was found and removed.
926
908
  */
927
- deleteIn(path6) {
928
- const [key, ...rest] = path6;
909
+ deleteIn(path7) {
910
+ const [key, ...rest] = path7;
929
911
  if (rest.length === 0)
930
912
  return this.delete(key);
931
913
  const node = this.get(key, true);
@@ -939,8 +921,8 @@ var require_Collection = __commonJS({
939
921
  * scalar values from their surrounding node; to disable set `keepScalar` to
940
922
  * `true` (collections are always returned intact).
941
923
  */
942
- getIn(path6, keepScalar) {
943
- const [key, ...rest] = path6;
924
+ getIn(path7, keepScalar) {
925
+ const [key, ...rest] = path7;
944
926
  const node = this.get(key, true);
945
927
  if (rest.length === 0)
946
928
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -958,8 +940,8 @@ var require_Collection = __commonJS({
958
940
  /**
959
941
  * Checks if the collection includes a value with the key `key`.
960
942
  */
961
- hasIn(path6) {
962
- const [key, ...rest] = path6;
943
+ hasIn(path7) {
944
+ const [key, ...rest] = path7;
963
945
  if (rest.length === 0)
964
946
  return this.has(key);
965
947
  const node = this.get(key, true);
@@ -969,8 +951,8 @@ var require_Collection = __commonJS({
969
951
  * Sets a value in this collection. For `!!set`, `value` needs to be a
970
952
  * boolean to add/remove the item from the set.
971
953
  */
972
- setIn(path6, value) {
973
- const [key, ...rest] = path6;
954
+ setIn(path7, value) {
955
+ const [key, ...rest] = path7;
974
956
  if (rest.length === 0) {
975
957
  this.set(key, value);
976
958
  } else {
@@ -3474,9 +3456,9 @@ var require_Document = __commonJS({
3474
3456
  this.contents.add(value);
3475
3457
  }
3476
3458
  /** Adds a value to the document. */
3477
- addIn(path6, value) {
3459
+ addIn(path7, value) {
3478
3460
  if (assertCollection(this.contents))
3479
- this.contents.addIn(path6, value);
3461
+ this.contents.addIn(path7, value);
3480
3462
  }
3481
3463
  /**
3482
3464
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -3551,14 +3533,14 @@ var require_Document = __commonJS({
3551
3533
  * Removes a value from the document.
3552
3534
  * @returns `true` if the item was found and removed.
3553
3535
  */
3554
- deleteIn(path6) {
3555
- if (Collection.isEmptyPath(path6)) {
3536
+ deleteIn(path7) {
3537
+ if (Collection.isEmptyPath(path7)) {
3556
3538
  if (this.contents == null)
3557
3539
  return false;
3558
3540
  this.contents = null;
3559
3541
  return true;
3560
3542
  }
3561
- return assertCollection(this.contents) ? this.contents.deleteIn(path6) : false;
3543
+ return assertCollection(this.contents) ? this.contents.deleteIn(path7) : false;
3562
3544
  }
3563
3545
  /**
3564
3546
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -3573,10 +3555,10 @@ var require_Document = __commonJS({
3573
3555
  * scalar values from their surrounding node; to disable set `keepScalar` to
3574
3556
  * `true` (collections are always returned intact).
3575
3557
  */
3576
- getIn(path6, keepScalar) {
3577
- if (Collection.isEmptyPath(path6))
3558
+ getIn(path7, keepScalar) {
3559
+ if (Collection.isEmptyPath(path7))
3578
3560
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
3579
- return identity.isCollection(this.contents) ? this.contents.getIn(path6, keepScalar) : void 0;
3561
+ return identity.isCollection(this.contents) ? this.contents.getIn(path7, keepScalar) : void 0;
3580
3562
  }
3581
3563
  /**
3582
3564
  * Checks if the document includes a value with the key `key`.
@@ -3587,10 +3569,10 @@ var require_Document = __commonJS({
3587
3569
  /**
3588
3570
  * Checks if the document includes a value at `path`.
3589
3571
  */
3590
- hasIn(path6) {
3591
- if (Collection.isEmptyPath(path6))
3572
+ hasIn(path7) {
3573
+ if (Collection.isEmptyPath(path7))
3592
3574
  return this.contents !== void 0;
3593
- return identity.isCollection(this.contents) ? this.contents.hasIn(path6) : false;
3575
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path7) : false;
3594
3576
  }
3595
3577
  /**
3596
3578
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -3607,13 +3589,13 @@ var require_Document = __commonJS({
3607
3589
  * Sets a value in this document. For `!!set`, `value` needs to be a
3608
3590
  * boolean to add/remove the item from the set.
3609
3591
  */
3610
- setIn(path6, value) {
3611
- if (Collection.isEmptyPath(path6)) {
3592
+ setIn(path7, value) {
3593
+ if (Collection.isEmptyPath(path7)) {
3612
3594
  this.contents = value;
3613
3595
  } else if (this.contents == null) {
3614
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path6), value);
3596
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path7), value);
3615
3597
  } else if (assertCollection(this.contents)) {
3616
- this.contents.setIn(path6, value);
3598
+ this.contents.setIn(path7, value);
3617
3599
  }
3618
3600
  }
3619
3601
  /**
@@ -5561,9 +5543,9 @@ var require_cst_visit = __commonJS({
5561
5543
  visit.BREAK = BREAK;
5562
5544
  visit.SKIP = SKIP;
5563
5545
  visit.REMOVE = REMOVE;
5564
- visit.itemAtPath = (cst, path6) => {
5546
+ visit.itemAtPath = (cst, path7) => {
5565
5547
  let item = cst;
5566
- for (const [field, index] of path6) {
5548
+ for (const [field, index] of path7) {
5567
5549
  const tok = item?.[field];
5568
5550
  if (tok && "items" in tok) {
5569
5551
  item = tok.items[index];
@@ -5572,23 +5554,23 @@ var require_cst_visit = __commonJS({
5572
5554
  }
5573
5555
  return item;
5574
5556
  };
5575
- visit.parentCollection = (cst, path6) => {
5576
- const parent = visit.itemAtPath(cst, path6.slice(0, -1));
5577
- const field = path6[path6.length - 1][0];
5557
+ visit.parentCollection = (cst, path7) => {
5558
+ const parent = visit.itemAtPath(cst, path7.slice(0, -1));
5559
+ const field = path7[path7.length - 1][0];
5578
5560
  const coll = parent?.[field];
5579
5561
  if (coll && "items" in coll)
5580
5562
  return coll;
5581
5563
  throw new Error("Parent collection not found");
5582
5564
  };
5583
- function _visit(path6, item, visitor) {
5584
- let ctrl = visitor(item, path6);
5565
+ function _visit(path7, item, visitor) {
5566
+ let ctrl = visitor(item, path7);
5585
5567
  if (typeof ctrl === "symbol")
5586
5568
  return ctrl;
5587
5569
  for (const field of ["key", "value"]) {
5588
5570
  const token = item[field];
5589
5571
  if (token && "items" in token) {
5590
5572
  for (let i = 0; i < token.items.length; ++i) {
5591
- const ci = _visit(Object.freeze(path6.concat([[field, i]])), token.items[i], visitor);
5573
+ const ci = _visit(Object.freeze(path7.concat([[field, i]])), token.items[i], visitor);
5592
5574
  if (typeof ci === "number")
5593
5575
  i = ci - 1;
5594
5576
  else if (ci === BREAK)
@@ -5599,10 +5581,10 @@ var require_cst_visit = __commonJS({
5599
5581
  }
5600
5582
  }
5601
5583
  if (typeof ctrl === "function" && field === "key")
5602
- ctrl = ctrl(item, path6);
5584
+ ctrl = ctrl(item, path7);
5603
5585
  }
5604
5586
  }
5605
- return typeof ctrl === "function" ? ctrl(item, path6) : ctrl;
5587
+ return typeof ctrl === "function" ? ctrl(item, path7) : ctrl;
5606
5588
  }
5607
5589
  exports2.visit = visit;
5608
5590
  }
@@ -6881,14 +6863,14 @@ var require_parser = __commonJS({
6881
6863
  case "scalar":
6882
6864
  case "single-quoted-scalar":
6883
6865
  case "double-quoted-scalar": {
6884
- const fs5 = this.flowScalar(this.type);
6866
+ const fs6 = this.flowScalar(this.type);
6885
6867
  if (atNextItem || it.value) {
6886
- map2.items.push({ start, key: fs5, sep: [] });
6868
+ map2.items.push({ start, key: fs6, sep: [] });
6887
6869
  this.onKeyLine = true;
6888
6870
  } else if (it.sep) {
6889
- this.stack.push(fs5);
6871
+ this.stack.push(fs6);
6890
6872
  } else {
6891
- Object.assign(it, { key: fs5, sep: [] });
6873
+ Object.assign(it, { key: fs6, sep: [] });
6892
6874
  this.onKeyLine = true;
6893
6875
  }
6894
6876
  return;
@@ -7016,13 +6998,13 @@ var require_parser = __commonJS({
7016
6998
  case "scalar":
7017
6999
  case "single-quoted-scalar":
7018
7000
  case "double-quoted-scalar": {
7019
- const fs5 = this.flowScalar(this.type);
7001
+ const fs6 = this.flowScalar(this.type);
7020
7002
  if (!it || it.value)
7021
- fc.items.push({ start: [], key: fs5, sep: [] });
7003
+ fc.items.push({ start: [], key: fs6, sep: [] });
7022
7004
  else if (it.sep)
7023
- this.stack.push(fs5);
7005
+ this.stack.push(fs6);
7024
7006
  else
7025
- Object.assign(it, { key: fs5, sep: [] });
7007
+ Object.assign(it, { key: fs6, sep: [] });
7026
7008
  return;
7027
7009
  }
7028
7010
  case "flow-map-end":
@@ -7372,12 +7354,12 @@ var require_code = __commonJS({
7372
7354
  return item === "" || item === '""';
7373
7355
  }
7374
7356
  get str() {
7375
- var _a3;
7376
- return (_a3 = this._str) !== null && _a3 !== void 0 ? _a3 : this._str = this._items.reduce((s, c) => `${s}${c}`, "");
7357
+ var _a2;
7358
+ return (_a2 = this._str) !== null && _a2 !== void 0 ? _a2 : this._str = this._items.reduce((s, c) => `${s}${c}`, "");
7377
7359
  }
7378
7360
  get names() {
7379
- var _a3;
7380
- return (_a3 = this._names) !== null && _a3 !== void 0 ? _a3 : this._names = this._items.reduce((names, c) => {
7361
+ var _a2;
7362
+ return (_a2 = this._names) !== null && _a2 !== void 0 ? _a2 : this._names = this._items.reduce((names, c) => {
7381
7363
  if (c instanceof Name)
7382
7364
  names[c.str] = (names[c.str] || 0) + 1;
7383
7365
  return names;
@@ -7523,8 +7505,8 @@ var require_scope = __commonJS({
7523
7505
  return `${prefix}${ng.index++}`;
7524
7506
  }
7525
7507
  _nameGroup(prefix) {
7526
- var _a3, _b;
7527
- if (((_b = (_a3 = this._parent) === null || _a3 === void 0 ? void 0 : _a3._prefixes) === null || _b === void 0 ? void 0 : _b.has(prefix)) || this._prefixes && !this._prefixes.has(prefix)) {
7508
+ var _a2, _b;
7509
+ if (((_b = (_a2 = this._parent) === null || _a2 === void 0 ? void 0 : _a2._prefixes) === null || _b === void 0 ? void 0 : _b.has(prefix)) || this._prefixes && !this._prefixes.has(prefix)) {
7528
7510
  throw new Error(`CodeGen: prefix "${prefix}" is not allowed in this scope`);
7529
7511
  }
7530
7512
  return this._names[prefix] = { prefix, index: 0 };
@@ -7557,12 +7539,12 @@ var require_scope = __commonJS({
7557
7539
  return new ValueScopeName(prefix, this._newName(prefix));
7558
7540
  }
7559
7541
  value(nameOrPrefix, value) {
7560
- var _a3;
7542
+ var _a2;
7561
7543
  if (value.ref === void 0)
7562
7544
  throw new Error("CodeGen: ref must be passed in value");
7563
7545
  const name = this.toName(nameOrPrefix);
7564
7546
  const { prefix } = name;
7565
- const valueKey = (_a3 = value.key) !== null && _a3 !== void 0 ? _a3 : value.ref;
7547
+ const valueKey = (_a2 = value.key) !== null && _a2 !== void 0 ? _a2 : value.ref;
7566
7548
  let vs = this._values[prefix];
7567
7549
  if (vs) {
7568
7550
  const _name = vs.get(valueKey);
@@ -7880,8 +7862,8 @@ var require_codegen = __commonJS({
7880
7862
  return this;
7881
7863
  }
7882
7864
  optimizeNames(names, constants) {
7883
- var _a3;
7884
- this.else = (_a3 = this.else) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants);
7865
+ var _a2;
7866
+ this.else = (_a2 = this.else) === null || _a2 === void 0 ? void 0 : _a2.optimizeNames(names, constants);
7885
7867
  if (!(super.optimizeNames(names, constants) || this.else))
7886
7868
  return;
7887
7869
  this.condition = optimizeExpr(this.condition, names, constants);
@@ -7985,16 +7967,16 @@ var require_codegen = __commonJS({
7985
7967
  return code;
7986
7968
  }
7987
7969
  optimizeNodes() {
7988
- var _a3, _b;
7970
+ var _a2, _b;
7989
7971
  super.optimizeNodes();
7990
- (_a3 = this.catch) === null || _a3 === void 0 ? void 0 : _a3.optimizeNodes();
7972
+ (_a2 = this.catch) === null || _a2 === void 0 ? void 0 : _a2.optimizeNodes();
7991
7973
  (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
7992
7974
  return this;
7993
7975
  }
7994
7976
  optimizeNames(names, constants) {
7995
- var _a3, _b;
7977
+ var _a2, _b;
7996
7978
  super.optimizeNames(names, constants);
7997
- (_a3 = this.catch) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants);
7979
+ (_a2 = this.catch) === null || _a2 === void 0 ? void 0 : _a2.optimizeNames(names, constants);
7998
7980
  (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants);
7999
7981
  return this;
8000
7982
  }
@@ -8394,11 +8376,11 @@ var require_util = __commonJS({
8394
8376
  return false;
8395
8377
  }
8396
8378
  exports2.schemaHasRules = schemaHasRules;
8397
- function schemaHasRulesButRef(schema, RULES2) {
8379
+ function schemaHasRulesButRef(schema, RULES) {
8398
8380
  if (typeof schema == "boolean")
8399
8381
  return !schema;
8400
8382
  for (const key in schema)
8401
- if (key !== "$ref" && RULES2.all[key])
8383
+ if (key !== "$ref" && RULES.all[key])
8402
8384
  return true;
8403
8385
  return false;
8404
8386
  }
@@ -8774,8 +8756,8 @@ var require_applicability = __commonJS({
8774
8756
  }
8775
8757
  exports2.shouldUseGroup = shouldUseGroup;
8776
8758
  function shouldUseRule(schema, rule) {
8777
- var _a3;
8778
- return schema[rule.keyword] !== void 0 || ((_a3 = rule.definition.implements) === null || _a3 === void 0 ? void 0 : _a3.some((kwd) => schema[kwd] !== void 0));
8759
+ var _a2;
8760
+ return schema[rule.keyword] !== void 0 || ((_a2 = rule.definition.implements) === null || _a2 === void 0 ? void 0 : _a2.some((kwd) => schema[kwd] !== void 0));
8779
8761
  }
8780
8762
  exports2.shouldUseRule = shouldUseRule;
8781
8763
  }
@@ -9163,14 +9145,14 @@ var require_keyword = __commonJS({
9163
9145
  }
9164
9146
  exports2.macroKeywordCode = macroKeywordCode;
9165
9147
  function funcKeywordCode(cxt, def) {
9166
- var _a3;
9148
+ var _a2;
9167
9149
  const { gen, keyword, schema, parentSchema, $data, it } = cxt;
9168
9150
  checkAsyncKeyword(it, def);
9169
9151
  const validate = !$data && def.compile ? def.compile.call(it.self, schema, parentSchema, it) : def.validate;
9170
9152
  const validateRef = useKeyword(gen, keyword, validate);
9171
9153
  const valid = gen.let("valid");
9172
9154
  cxt.block$data(valid, validateKeyword);
9173
- cxt.ok((_a3 = def.valid) !== null && _a3 !== void 0 ? _a3 : valid);
9155
+ cxt.ok((_a2 = def.valid) !== null && _a2 !== void 0 ? _a2 : valid);
9174
9156
  function validateKeyword() {
9175
9157
  if (def.errors === false) {
9176
9158
  assignValid();
@@ -9201,8 +9183,8 @@ var require_keyword = __commonJS({
9201
9183
  gen.assign(valid, (0, codegen_1._)`${_await}${(0, code_1.callValidateCode)(cxt, validateRef, passCxt, passSchema)}`, def.modifying);
9202
9184
  }
9203
9185
  function reportErrs(errors) {
9204
- var _a4;
9205
- gen.if((0, codegen_1.not)((_a4 = def.valid) !== null && _a4 !== void 0 ? _a4 : valid), errors);
9186
+ var _a3;
9187
+ gen.if((0, codegen_1.not)((_a3 = def.valid) !== null && _a3 !== void 0 ? _a3 : valid), errors);
9206
9188
  }
9207
9189
  }
9208
9190
  exports2.funcKeywordCode = funcKeywordCode;
@@ -9802,17 +9784,17 @@ var require_validate = __commonJS({
9802
9784
  }
9803
9785
  function schemaKeywords(it, types, typeErrors, errsCount) {
9804
9786
  const { gen, schema, data, allErrors, opts, self } = it;
9805
- const { RULES: RULES2 } = self;
9806
- if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES2))) {
9807
- gen.block(() => keywordCode(it, "$ref", RULES2.all.$ref.definition));
9787
+ const { RULES } = self;
9788
+ if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) {
9789
+ gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition));
9808
9790
  return;
9809
9791
  }
9810
9792
  if (!opts.jtd)
9811
9793
  checkStrictTypes(it, types);
9812
9794
  gen.block(() => {
9813
- for (const group of RULES2.rules)
9795
+ for (const group of RULES.rules)
9814
9796
  groupKeywords(group);
9815
- groupKeywords(RULES2.post);
9797
+ groupKeywords(RULES.post);
9816
9798
  });
9817
9799
  function groupKeywords(group) {
9818
9800
  if (!(0, applicability_1.shouldUseGroup)(schema, group))
@@ -10180,7 +10162,7 @@ var require_compile = __commonJS({
10180
10162
  var validate_1 = require_validate();
10181
10163
  var SchemaEnv = class {
10182
10164
  constructor(env) {
10183
- var _a3;
10165
+ var _a2;
10184
10166
  this.refs = {};
10185
10167
  this.dynamicAnchors = {};
10186
10168
  let schema;
@@ -10189,7 +10171,7 @@ var require_compile = __commonJS({
10189
10171
  this.schema = env.schema;
10190
10172
  this.schemaId = env.schemaId;
10191
10173
  this.root = env.root || this;
10192
- this.baseId = (_a3 = env.baseId) !== null && _a3 !== void 0 ? _a3 : (0, resolve_1.normalizeId)(schema === null || schema === void 0 ? void 0 : schema[env.schemaId || "$id"]);
10174
+ this.baseId = (_a2 = env.baseId) !== null && _a2 !== void 0 ? _a2 : (0, resolve_1.normalizeId)(schema === null || schema === void 0 ? void 0 : schema[env.schemaId || "$id"]);
10193
10175
  this.schemaPath = env.schemaPath;
10194
10176
  this.localRefs = env.localRefs;
10195
10177
  this.meta = env.meta;
@@ -10285,14 +10267,14 @@ var require_compile = __commonJS({
10285
10267
  }
10286
10268
  exports2.compileSchema = compileSchema;
10287
10269
  function resolveRef2(root, baseId, ref) {
10288
- var _a3;
10270
+ var _a2;
10289
10271
  ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
10290
10272
  const schOrFunc = root.refs[ref];
10291
10273
  if (schOrFunc)
10292
10274
  return schOrFunc;
10293
10275
  let _sch = resolve3.call(this, root, ref);
10294
10276
  if (_sch === void 0) {
10295
- const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
10277
+ const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
10296
10278
  const { schemaId } = this.opts;
10297
10279
  if (schema)
10298
10280
  _sch = new SchemaEnv({ schema, schemaId, root, baseId });
@@ -10361,8 +10343,8 @@ var require_compile = __commonJS({
10361
10343
  "definitions"
10362
10344
  ]);
10363
10345
  function getJsonPointer(parsedRef, { baseId, schema, root }) {
10364
- var _a3;
10365
- if (((_a3 = parsedRef.fragment) === null || _a3 === void 0 ? void 0 : _a3[0]) !== "/")
10346
+ var _a2;
10347
+ if (((_a2 = parsedRef.fragment) === null || _a2 === void 0 ? void 0 : _a2[0]) !== "/")
10366
10348
  return;
10367
10349
  for (const part of parsedRef.fragment.slice(1).split("/")) {
10368
10350
  if (typeof schema === "boolean")
@@ -10533,8 +10515,8 @@ var require_utils = __commonJS({
10533
10515
  }
10534
10516
  return ind;
10535
10517
  }
10536
- function removeDotSegments(path6) {
10537
- let input = path6;
10518
+ function removeDotSegments(path7) {
10519
+ let input = path7;
10538
10520
  const output = [];
10539
10521
  let nextSlash = -1;
10540
10522
  let len = 0;
@@ -10733,8 +10715,8 @@ var require_schemes = __commonJS({
10733
10715
  wsComponent.secure = void 0;
10734
10716
  }
10735
10717
  if (wsComponent.resourceName) {
10736
- const [path6, query] = wsComponent.resourceName.split("?");
10737
- wsComponent.path = path6 && path6 !== "/" ? path6 : void 0;
10718
+ const [path7, query] = wsComponent.resourceName.split("?");
10719
+ wsComponent.path = path7 && path7 !== "/" ? path7 : void 0;
10738
10720
  wsComponent.query = query;
10739
10721
  wsComponent.resourceName = void 0;
10740
10722
  }
@@ -10793,7 +10775,7 @@ var require_schemes = __commonJS({
10793
10775
  urnComponent.nss = (uuidComponent.uuid || "").toLowerCase();
10794
10776
  return urnComponent;
10795
10777
  }
10796
- var http2 = (
10778
+ var http = (
10797
10779
  /** @type {SchemeHandler} */
10798
10780
  {
10799
10781
  scheme: "http",
@@ -10806,7 +10788,7 @@ var require_schemes = __commonJS({
10806
10788
  /** @type {SchemeHandler} */
10807
10789
  {
10808
10790
  scheme: "https",
10809
- domainHost: http2.domainHost,
10791
+ domainHost: http.domainHost,
10810
10792
  parse: httpParse,
10811
10793
  serialize: httpSerialize
10812
10794
  }
@@ -10850,7 +10832,7 @@ var require_schemes = __commonJS({
10850
10832
  var SCHEMES = (
10851
10833
  /** @type {Record<SchemeName, SchemeHandler>} */
10852
10834
  {
10853
- http: http2,
10835
+ http,
10854
10836
  https,
10855
10837
  ws,
10856
10838
  wss,
@@ -11225,9 +11207,9 @@ var require_core = __commonJS({
11225
11207
  };
11226
11208
  var MAX_EXPRESSION = 200;
11227
11209
  function requiredOptions(o) {
11228
- var _a3, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
11210
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
11229
11211
  const s = o.strict;
11230
- const _optz = (_a3 = o.code) === null || _a3 === void 0 ? void 0 : _a3.optimize;
11212
+ const _optz = (_a2 = o.code) === null || _a2 === void 0 ? void 0 : _a2.optimize;
11231
11213
  const optimize = _optz === true || _optz === void 0 ? 1 : _optz || 0;
11232
11214
  const regExp = (_c = (_b = o.code) === null || _b === void 0 ? void 0 : _b.regExp) !== null && _c !== void 0 ? _c : defaultRegExp;
11233
11215
  const uriResolver = (_d = o.uriResolver) !== null && _d !== void 0 ? _d : uri_1.default;
@@ -11459,8 +11441,8 @@ var require_core = __commonJS({
11459
11441
  return this;
11460
11442
  }
11461
11443
  case "object": {
11462
- const cacheKey2 = schemaKeyRef;
11463
- this._cache.delete(cacheKey2);
11444
+ const cacheKey = schemaKeyRef;
11445
+ this._cache.delete(cacheKey);
11464
11446
  let id = schemaKeyRef[this.opts.schemaId];
11465
11447
  if (id) {
11466
11448
  id = (0, resolve_1.normalizeId)(id);
@@ -11516,10 +11498,10 @@ var require_core = __commonJS({
11516
11498
  }
11517
11499
  // Remove keyword
11518
11500
  removeKeyword(keyword) {
11519
- const { RULES: RULES2 } = this;
11520
- delete RULES2.keywords[keyword];
11521
- delete RULES2.all[keyword];
11522
- for (const group of RULES2.rules) {
11501
+ const { RULES } = this;
11502
+ delete RULES.keywords[keyword];
11503
+ delete RULES.all[keyword];
11504
+ for (const group of RULES.rules) {
11523
11505
  const i = group.rules.findIndex((rule) => rule.keyword === keyword);
11524
11506
  if (i >= 0)
11525
11507
  group.rules.splice(i, 1);
@@ -11687,9 +11669,9 @@ var require_core = __commonJS({
11687
11669
  }
11688
11670
  var KEYWORD_NAME = /^[a-z_$][a-z0-9_$:-]*$/i;
11689
11671
  function checkKeyword(keyword, def) {
11690
- const { RULES: RULES2 } = this;
11672
+ const { RULES } = this;
11691
11673
  (0, util_1.eachItem)(keyword, (kwd) => {
11692
- if (RULES2.keywords[kwd])
11674
+ if (RULES.keywords[kwd])
11693
11675
  throw new Error(`Keyword ${kwd} is already defined`);
11694
11676
  if (!KEYWORD_NAME.test(kwd))
11695
11677
  throw new Error(`Keyword ${kwd} has invalid name`);
@@ -11701,17 +11683,17 @@ var require_core = __commonJS({
11701
11683
  }
11702
11684
  }
11703
11685
  function addRule(keyword, definition, dataType) {
11704
- var _a3;
11686
+ var _a2;
11705
11687
  const post = definition === null || definition === void 0 ? void 0 : definition.post;
11706
11688
  if (dataType && post)
11707
11689
  throw new Error('keyword with "post" flag cannot have "type"');
11708
- const { RULES: RULES2 } = this;
11709
- let ruleGroup = post ? RULES2.post : RULES2.rules.find(({ type: t }) => t === dataType);
11690
+ const { RULES } = this;
11691
+ let ruleGroup = post ? RULES.post : RULES.rules.find(({ type: t }) => t === dataType);
11710
11692
  if (!ruleGroup) {
11711
11693
  ruleGroup = { type: dataType, rules: [] };
11712
- RULES2.rules.push(ruleGroup);
11694
+ RULES.rules.push(ruleGroup);
11713
11695
  }
11714
- RULES2.keywords[keyword] = true;
11696
+ RULES.keywords[keyword] = true;
11715
11697
  if (!definition)
11716
11698
  return;
11717
11699
  const rule = {
@@ -11726,8 +11708,8 @@ var require_core = __commonJS({
11726
11708
  addBeforeRule.call(this, ruleGroup, rule, definition.before);
11727
11709
  else
11728
11710
  ruleGroup.rules.push(rule);
11729
- RULES2.all[keyword] = rule;
11730
- (_a3 = definition.implements) === null || _a3 === void 0 ? void 0 : _a3.forEach((kwd) => this.addKeyword(kwd));
11711
+ RULES.all[keyword] = rule;
11712
+ (_a2 = definition.implements) === null || _a2 === void 0 ? void 0 : _a2.forEach((kwd) => this.addKeyword(kwd));
11731
11713
  }
11732
11714
  function addBeforeRule(ruleGroup, rule, before) {
11733
11715
  const i = ruleGroup.rules.findIndex((_rule) => _rule.keyword === before);
@@ -11861,10 +11843,10 @@ var require_ref = __commonJS({
11861
11843
  gen.assign(names_1.default.errors, (0, codegen_1._)`${names_1.default.vErrors}.length`);
11862
11844
  }
11863
11845
  function addEvaluatedFrom(source) {
11864
- var _a3;
11846
+ var _a2;
11865
11847
  if (!it.opts.unevaluated)
11866
11848
  return;
11867
- const schEvaluated = (_a3 = sch === null || sch === void 0 ? void 0 : sch.validate) === null || _a3 === void 0 ? void 0 : _a3.evaluated;
11849
+ const schEvaluated = (_a2 = sch === null || sch === void 0 ? void 0 : sch.validate) === null || _a2 === void 0 ? void 0 : _a2.evaluated;
11868
11850
  if (it.props !== true) {
11869
11851
  if (schEvaluated && !schEvaluated.dynamicProps) {
11870
11852
  if (schEvaluated.props !== void 0) {
@@ -13515,7 +13497,7 @@ var require_discriminator = __commonJS({
13515
13497
  return _valid;
13516
13498
  }
13517
13499
  function getMapping() {
13518
- var _a3;
13500
+ var _a2;
13519
13501
  const oneOfMapping = {};
13520
13502
  const topRequired = hasRequired(parentSchema);
13521
13503
  let tagRequired = true;
@@ -13529,7 +13511,7 @@ var require_discriminator = __commonJS({
13529
13511
  if (sch === void 0)
13530
13512
  throw new ref_error_1.default(it.opts.uriResolver, it.baseId, ref);
13531
13513
  }
13532
- const propSch = (_a3 = sch === null || sch === void 0 ? void 0 : sch.properties) === null || _a3 === void 0 ? void 0 : _a3[tagName];
13514
+ const propSch = (_a2 = sch === null || sch === void 0 ? void 0 : sch.properties) === null || _a2 === void 0 ? void 0 : _a2[tagName];
13533
13515
  if (typeof propSch != "object") {
13534
13516
  throw new Error(`discriminator: oneOf subschemas (or referenced schemas) must have "properties/${tagName}"`);
13535
13517
  }
@@ -14097,12 +14079,12 @@ var require_dist2 = __commonJS({
14097
14079
  throw new Error(`Unknown format "${name}"`);
14098
14080
  return f;
14099
14081
  };
14100
- function addFormats(ajv, list, fs5, exportName) {
14101
- var _a3;
14082
+ function addFormats(ajv, list, fs6, exportName) {
14083
+ var _a2;
14102
14084
  var _b;
14103
- (_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
14085
+ (_a2 = (_b = ajv.opts.code).formats) !== null && _a2 !== void 0 ? _a2 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
14104
14086
  for (const f of list)
14105
- ajv.addFormat(f, fs5[f]);
14087
+ ajv.addFormat(f, fs6[f]);
14106
14088
  }
14107
14089
  module2.exports = exports2 = formatsPlugin;
14108
14090
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -14117,31 +14099,126 @@ __export(config_exports, {
14117
14099
  loadSiteConfig: () => loadSiteConfig
14118
14100
  });
14119
14101
  function loadOmtConfig(basePath) {
14120
- const configPath = path4.join(basePath, "oh-my-til.json");
14102
+ const configPath = path5.join(basePath, "oh-my-til.json");
14121
14103
  try {
14122
- const raw = fs3.readFileSync(configPath, "utf-8");
14104
+ const raw = fs4.readFileSync(configPath, "utf-8");
14123
14105
  const parsed = JSON.parse(raw);
14124
14106
  return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
14125
14107
  } catch {
14126
14108
  return {};
14127
14109
  }
14128
14110
  }
14129
- var path4, fs3, loadSiteConfig;
14111
+ var path5, fs4, loadSiteConfig;
14130
14112
  var init_config = __esm({
14131
14113
  "src/core/config.ts"() {
14132
- path4 = __toESM(require("path"));
14133
- fs3 = __toESM(require("fs"));
14114
+ path5 = __toESM(require("path"));
14115
+ fs4 = __toESM(require("fs"));
14134
14116
  loadSiteConfig = loadOmtConfig;
14135
14117
  }
14136
14118
  });
14137
14119
 
14138
- // src/adapters/fs-adapter.ts
14139
- var fs = __toESM(require("fs/promises"));
14120
+ // src/cli/global-config.ts
14121
+ var fs = __toESM(require("fs"));
14122
+ var os = __toESM(require("os"));
14140
14123
  var path = __toESM(require("path"));
14124
+ var CONFIG_DIR = path.join(os.homedir(), ".config", "oh-my-til");
14125
+ var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
14126
+ var VALID_PROVIDERS = ["anthropic", "openai", "ollama"];
14127
+ function readConfig() {
14128
+ if (!fs.existsSync(CONFIG_FILE))
14129
+ return {};
14130
+ try {
14131
+ const raw = fs.readFileSync(CONFIG_FILE, "utf-8");
14132
+ return JSON.parse(raw);
14133
+ } catch {
14134
+ return {};
14135
+ }
14136
+ }
14137
+ function writeConfig(config2) {
14138
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
14139
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config2, null, 2), { encoding: "utf-8", mode: 384 });
14140
+ }
14141
+ function maskApiKey(key) {
14142
+ if (key.length <= 8)
14143
+ return "***";
14144
+ return key.slice(0, 4) + "..." + key.slice(-4);
14145
+ }
14146
+ function runConfigCommand(args) {
14147
+ const subcommand = args[0];
14148
+ if (!subcommand || subcommand === "get") {
14149
+ const config2 = readConfig();
14150
+ const display = {};
14151
+ if (config2.vault)
14152
+ display["vault"] = config2.vault;
14153
+ if (config2.ai) {
14154
+ display["ai"] = {
14155
+ provider: config2.ai.provider,
14156
+ ...config2.ai.model ? { model: config2.ai.model } : {},
14157
+ ...config2.ai.apiKey ? { apiKey: maskApiKey(config2.ai.apiKey) } : {}
14158
+ };
14159
+ }
14160
+ if (Object.keys(display).length === 0) {
14161
+ console.log("No config set. Use `omt config set <key> <value>`");
14162
+ } else {
14163
+ console.log(JSON.stringify(display, null, 2));
14164
+ }
14165
+ return;
14166
+ }
14167
+ if (subcommand === "set") {
14168
+ const key = args[1];
14169
+ const value = args[2];
14170
+ if (!key || value === void 0) {
14171
+ console.error("Usage: omt config set <key> <value>");
14172
+ console.error("Keys: vault, ai.provider, ai.model, ai.apiKey");
14173
+ process.exit(1);
14174
+ }
14175
+ const config2 = readConfig();
14176
+ if (key === "vault") {
14177
+ config2.vault = value;
14178
+ writeConfig(config2);
14179
+ console.log(`vault = ${value}`);
14180
+ } else if (key === "ai.provider") {
14181
+ if (!VALID_PROVIDERS.includes(value)) {
14182
+ console.error(`Invalid provider. Choose from: ${VALID_PROVIDERS.join(", ")}`);
14183
+ process.exit(1);
14184
+ }
14185
+ config2.ai = { ...config2.ai, provider: value };
14186
+ writeConfig(config2);
14187
+ console.log(`ai.provider = ${value}`);
14188
+ } else if (key === "ai.model") {
14189
+ if (!config2.ai) {
14190
+ console.error("Set ai.provider first.");
14191
+ process.exit(1);
14192
+ }
14193
+ config2.ai.model = value;
14194
+ writeConfig(config2);
14195
+ console.log(`ai.model = ${value}`);
14196
+ } else if (key === "ai.apiKey") {
14197
+ if (!config2.ai) {
14198
+ console.error("Set ai.provider first.");
14199
+ process.exit(1);
14200
+ }
14201
+ config2.ai.apiKey = value;
14202
+ writeConfig(config2);
14203
+ console.log(`ai.apiKey = ${maskApiKey(value)}`);
14204
+ } else {
14205
+ console.error(`Unknown key: ${key}`);
14206
+ console.error("Keys: vault, ai.provider, ai.model, ai.apiKey");
14207
+ process.exit(1);
14208
+ }
14209
+ return;
14210
+ }
14211
+ console.error(`Unknown config subcommand: ${subcommand}`);
14212
+ process.exit(1);
14213
+ }
14214
+
14215
+ // src/adapters/fs-adapter.ts
14216
+ var fs2 = __toESM(require("fs/promises"));
14217
+ var path2 = __toESM(require("path"));
14141
14218
  var import_yaml = __toESM(require_dist());
14142
14219
  function resolveSafe(resolvedBase, filePath) {
14143
- const resolved = path.resolve(resolvedBase, filePath);
14144
- if (resolved !== resolvedBase && !resolved.startsWith(resolvedBase + path.sep)) {
14220
+ const resolved = path2.resolve(resolvedBase, filePath);
14221
+ if (resolved !== resolvedBase && !resolved.startsWith(resolvedBase + path2.sep)) {
14145
14222
  throw new Error(`Path traversal denied: ${filePath}`);
14146
14223
  }
14147
14224
  return resolved;
@@ -14149,11 +14226,11 @@ function resolveSafe(resolvedBase, filePath) {
14149
14226
  var FsStorage = class {
14150
14227
  constructor(basePath) {
14151
14228
  this.basePath = basePath;
14152
- this.resolvedBase = path.resolve(basePath);
14229
+ this.resolvedBase = path2.resolve(basePath);
14153
14230
  }
14154
14231
  async readFile(filePath) {
14155
14232
  try {
14156
- return await fs.readFile(resolveSafe(this.resolvedBase, filePath), "utf-8");
14233
+ return await fs2.readFile(resolveSafe(this.resolvedBase, filePath), "utf-8");
14157
14234
  } catch {
14158
14235
  return null;
14159
14236
  }
@@ -14167,7 +14244,7 @@ var FsStorage = class {
14167
14244
  const fullDir = resolveSafe(this.resolvedBase, dir || ".");
14168
14245
  let dirents;
14169
14246
  try {
14170
- dirents = await fs.readdir(fullDir, { withFileTypes: true });
14247
+ dirents = await fs2.readdir(fullDir, { withFileTypes: true });
14171
14248
  } catch {
14172
14249
  return;
14173
14250
  }
@@ -14180,7 +14257,7 @@ var FsStorage = class {
14180
14257
  } else if (d.isFile()) {
14181
14258
  const ext = d.name.includes(".") ? d.name.split(".").pop() : "";
14182
14259
  try {
14183
- const stat2 = await fs.stat(resolveSafe(this.resolvedBase, relative));
14260
+ const stat2 = await fs2.stat(resolveSafe(this.resolvedBase, relative));
14184
14261
  entries.push({
14185
14262
  path: relative,
14186
14263
  extension: ext,
@@ -14195,7 +14272,7 @@ var FsStorage = class {
14195
14272
  }
14196
14273
  async exists(filePath) {
14197
14274
  try {
14198
- await fs.access(resolveSafe(this.resolvedBase, filePath));
14275
+ await fs2.access(resolveSafe(this.resolvedBase, filePath));
14199
14276
  return true;
14200
14277
  } catch {
14201
14278
  return false;
@@ -14203,15 +14280,15 @@ var FsStorage = class {
14203
14280
  }
14204
14281
  async writeFile(filePath, content) {
14205
14282
  const fullPath = resolveSafe(this.resolvedBase, filePath);
14206
- await fs.mkdir(path.dirname(fullPath), { recursive: true });
14207
- await fs.writeFile(fullPath, content, "utf-8");
14283
+ await fs2.mkdir(path2.dirname(fullPath), { recursive: true });
14284
+ await fs2.writeFile(fullPath, content, "utf-8");
14208
14285
  }
14209
14286
  async mkdir(dirPath) {
14210
- await fs.mkdir(resolveSafe(this.resolvedBase, dirPath), { recursive: true });
14287
+ await fs2.mkdir(resolveSafe(this.resolvedBase, dirPath), { recursive: true });
14211
14288
  }
14212
14289
  async remove(filePath) {
14213
14290
  try {
14214
- await fs.unlink(resolveSafe(this.resolvedBase, filePath));
14291
+ await fs2.unlink(resolveSafe(this.resolvedBase, filePath));
14215
14292
  } catch {
14216
14293
  }
14217
14294
  }
@@ -14224,13 +14301,13 @@ var FsMetadata = class {
14224
14301
  constructor(basePath, storage) {
14225
14302
  this.basePath = basePath;
14226
14303
  this.linkScanCache = null;
14227
- this.resolvedBase = path.resolve(basePath);
14304
+ this.resolvedBase = path2.resolve(basePath);
14228
14305
  this.storage = storage ?? new FsStorage(basePath);
14229
14306
  }
14230
14307
  async getFileMetadata(filePath) {
14231
14308
  let content;
14232
14309
  try {
14233
- content = await fs.readFile(resolveSafe(this.resolvedBase, filePath), "utf-8");
14310
+ content = await fs2.readFile(resolveSafe(this.resolvedBase, filePath), "utf-8");
14234
14311
  } catch {
14235
14312
  return null;
14236
14313
  }
@@ -14760,8 +14837,8 @@ function getErrorMap() {
14760
14837
 
14761
14838
  // node_modules/zod/v3/helpers/parseUtil.js
14762
14839
  var makeIssue = (params) => {
14763
- const { data, path: path6, errorMaps, issueData } = params;
14764
- const fullPath = [...path6, ...issueData.path || []];
14840
+ const { data, path: path7, errorMaps, issueData } = params;
14841
+ const fullPath = [...path7, ...issueData.path || []];
14765
14842
  const fullIssue = {
14766
14843
  ...issueData,
14767
14844
  path: fullPath
@@ -14876,11 +14953,11 @@ var errorUtil;
14876
14953
 
14877
14954
  // node_modules/zod/v3/types.js
14878
14955
  var ParseInputLazyPath = class {
14879
- constructor(parent, value, path6, key) {
14956
+ constructor(parent, value, path7, key) {
14880
14957
  this._cachedPath = [];
14881
14958
  this.parent = parent;
14882
14959
  this.data = value;
14883
- this._path = path6;
14960
+ this._path = path7;
14884
14961
  this._key = key;
14885
14962
  }
14886
14963
  get path() {
@@ -18592,10 +18669,10 @@ function $constructor(name, initializer3, params) {
18592
18669
  }
18593
18670
  Object.defineProperty(Definition, "name", { value: name });
18594
18671
  function _(def) {
18595
- var _a3;
18672
+ var _a2;
18596
18673
  const inst = params?.Parent ? new Definition() : this;
18597
18674
  init(inst, def);
18598
- (_a3 = inst._zod).deferred ?? (_a3.deferred = []);
18675
+ (_a2 = inst._zod).deferred ?? (_a2.deferred = []);
18599
18676
  for (const fn of inst._zod.deferred) {
18600
18677
  fn();
18601
18678
  }
@@ -18804,10 +18881,10 @@ function mergeDefs(...defs) {
18804
18881
  function cloneDef(schema) {
18805
18882
  return mergeDefs(schema._zod.def);
18806
18883
  }
18807
- function getElementAtPath(obj, path6) {
18808
- if (!path6)
18884
+ function getElementAtPath(obj, path7) {
18885
+ if (!path7)
18809
18886
  return obj;
18810
- return path6.reduce((acc, key) => acc?.[key], obj);
18887
+ return path7.reduce((acc, key) => acc?.[key], obj);
18811
18888
  }
18812
18889
  function promiseAllObject(promisesObj) {
18813
18890
  const keys = Object.keys(promisesObj);
@@ -19190,11 +19267,11 @@ function aborted(x, startIndex = 0) {
19190
19267
  }
19191
19268
  return false;
19192
19269
  }
19193
- function prefixIssues(path6, issues) {
19270
+ function prefixIssues(path7, issues) {
19194
19271
  return issues.map((iss) => {
19195
- var _a3;
19196
- (_a3 = iss).path ?? (_a3.path = []);
19197
- iss.path.unshift(path6);
19272
+ var _a2;
19273
+ (_a2 = iss).path ?? (_a2.path = []);
19274
+ iss.path.unshift(path7);
19198
19275
  return iss;
19199
19276
  });
19200
19277
  }
@@ -19377,8 +19454,8 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
19377
19454
  }
19378
19455
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
19379
19456
  const result = { errors: [] };
19380
- const processError = (error49, path6 = []) => {
19381
- var _a3, _b;
19457
+ const processError = (error49, path7 = []) => {
19458
+ var _a2, _b;
19382
19459
  for (const issue2 of error49.issues) {
19383
19460
  if (issue2.code === "invalid_union" && issue2.errors.length) {
19384
19461
  issue2.errors.map((issues) => processError({ issues }, issue2.path));
@@ -19387,7 +19464,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
19387
19464
  } else if (issue2.code === "invalid_element") {
19388
19465
  processError({ issues: issue2.issues }, issue2.path);
19389
19466
  } else {
19390
- const fullpath = [...path6, ...issue2.path];
19467
+ const fullpath = [...path7, ...issue2.path];
19391
19468
  if (fullpath.length === 0) {
19392
19469
  result.errors.push(mapper(issue2));
19393
19470
  continue;
@@ -19399,7 +19476,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
19399
19476
  const terminal = i === fullpath.length - 1;
19400
19477
  if (typeof el === "string") {
19401
19478
  curr.properties ?? (curr.properties = {});
19402
- (_a3 = curr.properties)[el] ?? (_a3[el] = { errors: [] });
19479
+ (_a2 = curr.properties)[el] ?? (_a2[el] = { errors: [] });
19403
19480
  curr = curr.properties[el];
19404
19481
  } else {
19405
19482
  curr.items ?? (curr.items = []);
@@ -19419,8 +19496,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
19419
19496
  }
19420
19497
  function toDotPath(_path) {
19421
19498
  const segs = [];
19422
- const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
19423
- for (const seg of path6) {
19499
+ const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
19500
+ for (const seg of path7) {
19424
19501
  if (typeof seg === "number")
19425
19502
  segs.push(`[${seg}]`);
19426
19503
  else if (typeof seg === "symbol")
@@ -19693,10 +19770,10 @@ var sha512_base64url = /* @__PURE__ */ fixedBase64url(86);
19693
19770
 
19694
19771
  // node_modules/zod/v4/core/checks.js
19695
19772
  var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
19696
- var _a3;
19773
+ var _a2;
19697
19774
  inst._zod ?? (inst._zod = {});
19698
19775
  inst._zod.def = def;
19699
- (_a3 = inst._zod).onattach ?? (_a3.onattach = []);
19776
+ (_a2 = inst._zod).onattach ?? (_a2.onattach = []);
19700
19777
  });
19701
19778
  var numericOriginMap = {
19702
19779
  number: "number",
@@ -19762,8 +19839,8 @@ var $ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan",
19762
19839
  var $ZodCheckMultipleOf = /* @__PURE__ */ $constructor("$ZodCheckMultipleOf", (inst, def) => {
19763
19840
  $ZodCheck.init(inst, def);
19764
19841
  inst._zod.onattach.push((inst2) => {
19765
- var _a3;
19766
- (_a3 = inst2._zod.bag).multipleOf ?? (_a3.multipleOf = def.value);
19842
+ var _a2;
19843
+ (_a2 = inst2._zod.bag).multipleOf ?? (_a2.multipleOf = def.value);
19767
19844
  });
19768
19845
  inst._zod.check = (payload) => {
19769
19846
  if (typeof payload.value !== typeof def.value)
@@ -19896,9 +19973,9 @@ var $ZodCheckBigIntFormat = /* @__PURE__ */ $constructor("$ZodCheckBigIntFormat"
19896
19973
  };
19897
19974
  });
19898
19975
  var $ZodCheckMaxSize = /* @__PURE__ */ $constructor("$ZodCheckMaxSize", (inst, def) => {
19899
- var _a3;
19976
+ var _a2;
19900
19977
  $ZodCheck.init(inst, def);
19901
- (_a3 = inst._zod.def).when ?? (_a3.when = (payload) => {
19978
+ (_a2 = inst._zod.def).when ?? (_a2.when = (payload) => {
19902
19979
  const val = payload.value;
19903
19980
  return !nullish(val) && val.size !== void 0;
19904
19981
  });
@@ -19924,9 +20001,9 @@ var $ZodCheckMaxSize = /* @__PURE__ */ $constructor("$ZodCheckMaxSize", (inst, d
19924
20001
  };
19925
20002
  });
19926
20003
  var $ZodCheckMinSize = /* @__PURE__ */ $constructor("$ZodCheckMinSize", (inst, def) => {
19927
- var _a3;
20004
+ var _a2;
19928
20005
  $ZodCheck.init(inst, def);
19929
- (_a3 = inst._zod.def).when ?? (_a3.when = (payload) => {
20006
+ (_a2 = inst._zod.def).when ?? (_a2.when = (payload) => {
19930
20007
  const val = payload.value;
19931
20008
  return !nullish(val) && val.size !== void 0;
19932
20009
  });
@@ -19952,9 +20029,9 @@ var $ZodCheckMinSize = /* @__PURE__ */ $constructor("$ZodCheckMinSize", (inst, d
19952
20029
  };
19953
20030
  });
19954
20031
  var $ZodCheckSizeEquals = /* @__PURE__ */ $constructor("$ZodCheckSizeEquals", (inst, def) => {
19955
- var _a3;
20032
+ var _a2;
19956
20033
  $ZodCheck.init(inst, def);
19957
- (_a3 = inst._zod.def).when ?? (_a3.when = (payload) => {
20034
+ (_a2 = inst._zod.def).when ?? (_a2.when = (payload) => {
19958
20035
  const val = payload.value;
19959
20036
  return !nullish(val) && val.size !== void 0;
19960
20037
  });
@@ -19982,9 +20059,9 @@ var $ZodCheckSizeEquals = /* @__PURE__ */ $constructor("$ZodCheckSizeEquals", (i
19982
20059
  };
19983
20060
  });
19984
20061
  var $ZodCheckMaxLength = /* @__PURE__ */ $constructor("$ZodCheckMaxLength", (inst, def) => {
19985
- var _a3;
20062
+ var _a2;
19986
20063
  $ZodCheck.init(inst, def);
19987
- (_a3 = inst._zod.def).when ?? (_a3.when = (payload) => {
20064
+ (_a2 = inst._zod.def).when ?? (_a2.when = (payload) => {
19988
20065
  const val = payload.value;
19989
20066
  return !nullish(val) && val.length !== void 0;
19990
20067
  });
@@ -20011,9 +20088,9 @@ var $ZodCheckMaxLength = /* @__PURE__ */ $constructor("$ZodCheckMaxLength", (ins
20011
20088
  };
20012
20089
  });
20013
20090
  var $ZodCheckMinLength = /* @__PURE__ */ $constructor("$ZodCheckMinLength", (inst, def) => {
20014
- var _a3;
20091
+ var _a2;
20015
20092
  $ZodCheck.init(inst, def);
20016
- (_a3 = inst._zod.def).when ?? (_a3.when = (payload) => {
20093
+ (_a2 = inst._zod.def).when ?? (_a2.when = (payload) => {
20017
20094
  const val = payload.value;
20018
20095
  return !nullish(val) && val.length !== void 0;
20019
20096
  });
@@ -20040,9 +20117,9 @@ var $ZodCheckMinLength = /* @__PURE__ */ $constructor("$ZodCheckMinLength", (ins
20040
20117
  };
20041
20118
  });
20042
20119
  var $ZodCheckLengthEquals = /* @__PURE__ */ $constructor("$ZodCheckLengthEquals", (inst, def) => {
20043
- var _a3;
20120
+ var _a2;
20044
20121
  $ZodCheck.init(inst, def);
20045
- (_a3 = inst._zod.def).when ?? (_a3.when = (payload) => {
20122
+ (_a2 = inst._zod.def).when ?? (_a2.when = (payload) => {
20046
20123
  const val = payload.value;
20047
20124
  return !nullish(val) && val.length !== void 0;
20048
20125
  });
@@ -20071,7 +20148,7 @@ var $ZodCheckLengthEquals = /* @__PURE__ */ $constructor("$ZodCheckLengthEquals"
20071
20148
  };
20072
20149
  });
20073
20150
  var $ZodCheckStringFormat = /* @__PURE__ */ $constructor("$ZodCheckStringFormat", (inst, def) => {
20074
- var _a3, _b;
20151
+ var _a2, _b;
20075
20152
  $ZodCheck.init(inst, def);
20076
20153
  inst._zod.onattach.push((inst2) => {
20077
20154
  const bag = inst2._zod.bag;
@@ -20082,7 +20159,7 @@ var $ZodCheckStringFormat = /* @__PURE__ */ $constructor("$ZodCheckStringFormat"
20082
20159
  }
20083
20160
  });
20084
20161
  if (def.pattern)
20085
- (_a3 = inst._zod).check ?? (_a3.check = (payload) => {
20162
+ (_a2 = inst._zod).check ?? (_a2.check = (payload) => {
20086
20163
  def.pattern.lastIndex = 0;
20087
20164
  if (def.pattern.test(payload.value))
20088
20165
  return;
@@ -20284,7 +20361,7 @@ var version = {
20284
20361
 
20285
20362
  // node_modules/zod/v4/core/schemas.js
20286
20363
  var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
20287
- var _a3;
20364
+ var _a2;
20288
20365
  inst ?? (inst = {});
20289
20366
  inst._zod.def = def;
20290
20367
  inst._zod.bag = inst._zod.bag || {};
@@ -20299,7 +20376,7 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
20299
20376
  }
20300
20377
  }
20301
20378
  if (checks.length === 0) {
20302
- (_a3 = inst._zod).deferred ?? (_a3.deferred = []);
20379
+ (_a2 = inst._zod).deferred ?? (_a2.deferred = []);
20303
20380
  inst._zod.deferred?.push(() => {
20304
20381
  inst._zod.run = inst._zod.parse;
20305
20382
  });
@@ -28941,7 +29018,7 @@ function initializeContext(params) {
28941
29018
  };
28942
29019
  }
28943
29020
  function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
28944
- var _a3;
29021
+ var _a2;
28945
29022
  const def = schema._zod.def;
28946
29023
  const seen = ctx.seen.get(schema);
28947
29024
  if (seen) {
@@ -28989,7 +29066,7 @@ function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
28989
29066
  delete result.schema.default;
28990
29067
  }
28991
29068
  if (ctx.io === "input" && result.schema._prefault)
28992
- (_a3 = result.schema).default ?? (_a3.default = result.schema._prefault);
29069
+ (_a2 = result.schema).default ?? (_a2.default = result.schema._prefault);
28993
29070
  delete result.schema._prefault;
28994
29071
  const _result = ctx.seen.get(schema);
28995
29072
  return _result.schema;
@@ -31825,13 +31902,13 @@ function resolveRef(ref, ctx) {
31825
31902
  if (!ref.startsWith("#")) {
31826
31903
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
31827
31904
  }
31828
- const path6 = ref.slice(1).split("/").filter(Boolean);
31829
- if (path6.length === 0) {
31905
+ const path7 = ref.slice(1).split("/").filter(Boolean);
31906
+ if (path7.length === 0) {
31830
31907
  return ctx.rootSchema;
31831
31908
  }
31832
31909
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
31833
- if (path6[0] === defsKey) {
31834
- const key = path6[1];
31910
+ if (path7[0] === defsKey) {
31911
+ const key = path7[1];
31835
31912
  if (!key || !ctx.defs[key]) {
31836
31913
  throw new Error(`Reference not found: ${ref}`);
31837
31914
  }
@@ -32235,7 +32312,6 @@ config(en_default2());
32235
32312
 
32236
32313
  // node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
32237
32314
  var LATEST_PROTOCOL_VERSION = "2025-11-25";
32238
- var DEFAULT_NEGOTIATED_PROTOCOL_VERSION = "2025-03-26";
32239
32315
  var SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, "2025-06-18", "2025-03-26", "2024-11-05", "2024-10-07"];
32240
32316
  var RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task";
32241
32317
  var JSONRPC_VERSION = "2.0";
@@ -32561,7 +32637,6 @@ var InitializeRequestSchema = RequestSchema.extend({
32561
32637
  method: literal("initialize"),
32562
32638
  params: InitializeRequestParamsSchema
32563
32639
  });
32564
- var isInitializeRequest = (value) => InitializeRequestSchema.safeParse(value).success;
32565
32640
  var ServerCapabilitiesSchema = object2({
32566
32641
  /**
32567
32642
  * Experimental, non-standard capabilities that the server supports.
@@ -36121,345 +36196,486 @@ var ExperimentalServerTasks = class {
36121
36196
  return this._server.requestStream(request, resultSchema, options);
36122
36197
  }
36123
36198
  /**
36124
- * Gets the current status of a task.
36125
- *
36126
- * @param taskId - The task identifier
36127
- * @param options - Optional request options
36128
- * @returns The task status
36129
- *
36130
- * @experimental
36131
- */
36132
- async getTask(taskId, options) {
36133
- return this._server.getTask({ taskId }, options);
36134
- }
36135
- /**
36136
- * Retrieves the result of a completed task.
36137
- *
36138
- * @param taskId - The task identifier
36139
- * @param resultSchema - Zod schema for validating the result
36140
- * @param options - Optional request options
36141
- * @returns The task result
36142
- *
36143
- * @experimental
36144
- */
36145
- async getTaskResult(taskId, resultSchema, options) {
36146
- return this._server.getTaskResult({ taskId }, resultSchema, options);
36147
- }
36148
- /**
36149
- * Lists tasks with optional pagination.
36199
+ * Sends a sampling request and returns an AsyncGenerator that yields response messages.
36200
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
36150
36201
  *
36151
- * @param cursor - Optional pagination cursor
36152
- * @param options - Optional request options
36153
- * @returns List of tasks with optional next cursor
36202
+ * For task-augmented requests, yields 'taskCreated' and 'taskStatus' messages
36203
+ * before the final result.
36154
36204
  *
36155
- * @experimental
36156
- */
36157
- async listTasks(cursor, options) {
36158
- return this._server.listTasks(cursor ? { cursor } : void 0, options);
36159
- }
36160
- /**
36161
- * Cancels a running task.
36162
- *
36163
- * @param taskId - The task identifier
36164
- * @param options - Optional request options
36205
+ * @example
36206
+ * ```typescript
36207
+ * const stream = server.experimental.tasks.createMessageStream({
36208
+ * messages: [{ role: 'user', content: { type: 'text', text: 'Hello' } }],
36209
+ * maxTokens: 100
36210
+ * }, {
36211
+ * onprogress: (progress) => {
36212
+ * // Handle streaming tokens via progress notifications
36213
+ * console.log('Progress:', progress.message);
36214
+ * }
36215
+ * });
36165
36216
  *
36166
- * @experimental
36167
- */
36168
- async cancelTask(taskId, options) {
36169
- return this._server.cancelTask({ taskId }, options);
36170
- }
36171
- };
36172
-
36173
- // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
36174
- function assertToolsCallTaskCapability(requests, method, entityName) {
36175
- if (!requests) {
36176
- throw new Error(`${entityName} does not support task creation (required for ${method})`);
36177
- }
36178
- switch (method) {
36179
- case "tools/call":
36180
- if (!requests.tools?.call) {
36181
- throw new Error(`${entityName} does not support task creation for tools/call (required for ${method})`);
36182
- }
36183
- break;
36184
- default:
36185
- break;
36186
- }
36187
- }
36188
- function assertClientRequestTaskCapability(requests, method, entityName) {
36189
- if (!requests) {
36190
- throw new Error(`${entityName} does not support task creation (required for ${method})`);
36191
- }
36192
- switch (method) {
36193
- case "sampling/createMessage":
36194
- if (!requests.sampling?.createMessage) {
36195
- throw new Error(`${entityName} does not support task creation for sampling/createMessage (required for ${method})`);
36196
- }
36197
- break;
36198
- case "elicitation/create":
36199
- if (!requests.elicitation?.create) {
36200
- throw new Error(`${entityName} does not support task creation for elicitation/create (required for ${method})`);
36201
- }
36202
- break;
36203
- default:
36204
- break;
36205
- }
36206
- }
36207
-
36208
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
36209
- var Server = class extends Protocol {
36210
- /**
36211
- * Initializes this server with the given name and version information.
36212
- */
36213
- constructor(_serverInfo, options) {
36214
- super(options);
36215
- this._serverInfo = _serverInfo;
36216
- this._loggingLevels = /* @__PURE__ */ new Map();
36217
- this.LOG_LEVEL_SEVERITY = new Map(LoggingLevelSchema.options.map((level, index) => [level, index]));
36218
- this.isMessageIgnored = (level, sessionId) => {
36219
- const currentLevel = this._loggingLevels.get(sessionId);
36220
- return currentLevel ? this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(currentLevel) : false;
36221
- };
36222
- this._capabilities = options?.capabilities ?? {};
36223
- this._instructions = options?.instructions;
36224
- this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new AjvJsonSchemaValidator();
36225
- this.setRequestHandler(InitializeRequestSchema, (request) => this._oninitialize(request));
36226
- this.setNotificationHandler(InitializedNotificationSchema, () => this.oninitialized?.());
36227
- if (this._capabilities.logging) {
36228
- this.setRequestHandler(SetLevelRequestSchema, async (request, extra) => {
36229
- const transportSessionId = extra.sessionId || extra.requestInfo?.headers["mcp-session-id"] || void 0;
36230
- const { level } = request.params;
36231
- const parseResult = LoggingLevelSchema.safeParse(level);
36232
- if (parseResult.success) {
36233
- this._loggingLevels.set(transportSessionId, parseResult.data);
36234
- }
36235
- return {};
36236
- });
36237
- }
36238
- }
36239
- /**
36240
- * Access experimental features.
36217
+ * for await (const message of stream) {
36218
+ * switch (message.type) {
36219
+ * case 'taskCreated':
36220
+ * console.log('Task created:', message.task.taskId);
36221
+ * break;
36222
+ * case 'taskStatus':
36223
+ * console.log('Task status:', message.task.status);
36224
+ * break;
36225
+ * case 'result':
36226
+ * console.log('Final result:', message.result);
36227
+ * break;
36228
+ * case 'error':
36229
+ * console.error('Error:', message.error);
36230
+ * break;
36231
+ * }
36232
+ * }
36233
+ * ```
36241
36234
  *
36242
- * WARNING: These APIs are experimental and may change without notice.
36235
+ * @param params - The sampling request parameters
36236
+ * @param options - Optional request options (timeout, signal, task creation params, onprogress, etc.)
36237
+ * @returns AsyncGenerator that yields ResponseMessage objects
36243
36238
  *
36244
36239
  * @experimental
36245
36240
  */
36246
- get experimental() {
36247
- if (!this._experimental) {
36248
- this._experimental = {
36249
- tasks: new ExperimentalServerTasks(this)
36250
- };
36251
- }
36252
- return this._experimental;
36253
- }
36254
- /**
36255
- * Registers new capabilities. This can only be called before connecting to a transport.
36256
- *
36257
- * The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).
36258
- */
36259
- registerCapabilities(capabilities) {
36260
- if (this.transport) {
36261
- throw new Error("Cannot register capabilities after connecting to transport");
36262
- }
36263
- this._capabilities = mergeCapabilities(this._capabilities, capabilities);
36264
- }
36265
- /**
36266
- * Override request handler registration to enforce server-side validation for tools/call.
36267
- */
36268
- setRequestHandler(requestSchema, handler) {
36269
- const shape = getObjectShape(requestSchema);
36270
- const methodSchema = shape?.method;
36271
- if (!methodSchema) {
36272
- throw new Error("Schema is missing a method literal");
36273
- }
36274
- let methodValue;
36275
- if (isZ4Schema(methodSchema)) {
36276
- const v4Schema = methodSchema;
36277
- const v4Def = v4Schema._zod?.def;
36278
- methodValue = v4Def?.value ?? v4Schema.value;
36279
- } else {
36280
- const v3Schema = methodSchema;
36281
- const legacyDef = v3Schema._def;
36282
- methodValue = legacyDef?.value ?? v3Schema.value;
36283
- }
36284
- if (typeof methodValue !== "string") {
36285
- throw new Error("Schema method literal must be a string");
36286
- }
36287
- const method = methodValue;
36288
- if (method === "tools/call") {
36289
- const wrappedHandler = async (request, extra) => {
36290
- const validatedRequest = safeParse2(CallToolRequestSchema, request);
36291
- if (!validatedRequest.success) {
36292
- const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
36293
- throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage}`);
36294
- }
36295
- const { params } = validatedRequest.data;
36296
- const result = await Promise.resolve(handler(request, extra));
36297
- if (params.task) {
36298
- const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
36299
- if (!taskValidationResult.success) {
36300
- const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
36301
- throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
36302
- }
36303
- return taskValidationResult.data;
36304
- }
36305
- const validationResult = safeParse2(CallToolResultSchema, result);
36306
- if (!validationResult.success) {
36307
- const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
36308
- throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${errorMessage}`);
36309
- }
36310
- return validationResult.data;
36311
- };
36312
- return super.setRequestHandler(requestSchema, wrappedHandler);
36313
- }
36314
- return super.setRequestHandler(requestSchema, handler);
36315
- }
36316
- assertCapabilityForMethod(method) {
36317
- switch (method) {
36318
- case "sampling/createMessage":
36319
- if (!this._clientCapabilities?.sampling) {
36320
- throw new Error(`Client does not support sampling (required for ${method})`);
36321
- }
36322
- break;
36323
- case "elicitation/create":
36324
- if (!this._clientCapabilities?.elicitation) {
36325
- throw new Error(`Client does not support elicitation (required for ${method})`);
36326
- }
36327
- break;
36328
- case "roots/list":
36329
- if (!this._clientCapabilities?.roots) {
36330
- throw new Error(`Client does not support listing roots (required for ${method})`);
36331
- }
36332
- break;
36333
- case "ping":
36334
- break;
36335
- }
36336
- }
36337
- assertNotificationCapability(method) {
36338
- switch (method) {
36339
- case "notifications/message":
36340
- if (!this._capabilities.logging) {
36341
- throw new Error(`Server does not support logging (required for ${method})`);
36342
- }
36343
- break;
36344
- case "notifications/resources/updated":
36345
- case "notifications/resources/list_changed":
36346
- if (!this._capabilities.resources) {
36347
- throw new Error(`Server does not support notifying about resources (required for ${method})`);
36348
- }
36349
- break;
36350
- case "notifications/tools/list_changed":
36351
- if (!this._capabilities.tools) {
36352
- throw new Error(`Server does not support notifying of tool list changes (required for ${method})`);
36353
- }
36354
- break;
36355
- case "notifications/prompts/list_changed":
36356
- if (!this._capabilities.prompts) {
36357
- throw new Error(`Server does not support notifying of prompt list changes (required for ${method})`);
36358
- }
36359
- break;
36360
- case "notifications/elicitation/complete":
36361
- if (!this._clientCapabilities?.elicitation?.url) {
36362
- throw new Error(`Client does not support URL elicitation (required for ${method})`);
36363
- }
36364
- break;
36365
- case "notifications/cancelled":
36366
- break;
36367
- case "notifications/progress":
36368
- break;
36369
- }
36370
- }
36371
- assertRequestHandlerCapability(method) {
36372
- if (!this._capabilities) {
36373
- return;
36374
- }
36375
- switch (method) {
36376
- case "completion/complete":
36377
- if (!this._capabilities.completions) {
36378
- throw new Error(`Server does not support completions (required for ${method})`);
36379
- }
36380
- break;
36381
- case "logging/setLevel":
36382
- if (!this._capabilities.logging) {
36383
- throw new Error(`Server does not support logging (required for ${method})`);
36384
- }
36385
- break;
36386
- case "prompts/get":
36387
- case "prompts/list":
36388
- if (!this._capabilities.prompts) {
36389
- throw new Error(`Server does not support prompts (required for ${method})`);
36390
- }
36391
- break;
36392
- case "resources/list":
36393
- case "resources/templates/list":
36394
- case "resources/read":
36395
- if (!this._capabilities.resources) {
36396
- throw new Error(`Server does not support resources (required for ${method})`);
36397
- }
36398
- break;
36399
- case "tools/call":
36400
- case "tools/list":
36401
- if (!this._capabilities.tools) {
36402
- throw new Error(`Server does not support tools (required for ${method})`);
36403
- }
36404
- break;
36405
- case "tasks/get":
36406
- case "tasks/list":
36407
- case "tasks/result":
36408
- case "tasks/cancel":
36409
- if (!this._capabilities.tasks) {
36410
- throw new Error(`Server does not support tasks capability (required for ${method})`);
36411
- }
36412
- break;
36413
- case "ping":
36414
- case "initialize":
36415
- break;
36416
- }
36417
- }
36418
- assertTaskCapability(method) {
36419
- assertClientRequestTaskCapability(this._clientCapabilities?.tasks?.requests, method, "Client");
36420
- }
36421
- assertTaskHandlerCapability(method) {
36422
- if (!this._capabilities) {
36423
- return;
36424
- }
36425
- assertToolsCallTaskCapability(this._capabilities.tasks?.requests, method, "Server");
36426
- }
36427
- async _oninitialize(request) {
36428
- const requestedVersion = request.params.protocolVersion;
36429
- this._clientCapabilities = request.params.capabilities;
36430
- this._clientVersion = request.params.clientInfo;
36431
- const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion) ? requestedVersion : LATEST_PROTOCOL_VERSION;
36432
- return {
36433
- protocolVersion,
36434
- capabilities: this.getCapabilities(),
36435
- serverInfo: this._serverInfo,
36436
- ...this._instructions && { instructions: this._instructions }
36437
- };
36438
- }
36439
- /**
36440
- * After initialization has completed, this will be populated with the client's reported capabilities.
36441
- */
36442
- getClientCapabilities() {
36443
- return this._clientCapabilities;
36444
- }
36445
- /**
36446
- * After initialization has completed, this will be populated with information about the client's name and version.
36447
- */
36448
- getClientVersion() {
36449
- return this._clientVersion;
36450
- }
36451
- getCapabilities() {
36452
- return this._capabilities;
36453
- }
36454
- async ping() {
36455
- return this.request({ method: "ping" }, EmptyResultSchema);
36456
- }
36457
- // Implementation
36458
- async createMessage(params, options) {
36459
- if (params.tools || params.toolChoice) {
36460
- if (!this._clientCapabilities?.sampling?.tools) {
36461
- throw new Error("Client does not support sampling tools capability.");
36462
- }
36241
+ createMessageStream(params, options) {
36242
+ const clientCapabilities = this._server.getClientCapabilities();
36243
+ if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
36244
+ throw new Error("Client does not support sampling tools capability.");
36245
+ }
36246
+ if (params.messages.length > 0) {
36247
+ const lastMessage = params.messages[params.messages.length - 1];
36248
+ const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
36249
+ const hasToolResults = lastContent.some((c) => c.type === "tool_result");
36250
+ const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : void 0;
36251
+ const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
36252
+ const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
36253
+ if (hasToolResults) {
36254
+ if (lastContent.some((c) => c.type !== "tool_result")) {
36255
+ throw new Error("The last message must contain only tool_result content if any is present");
36256
+ }
36257
+ if (!hasPreviousToolUse) {
36258
+ throw new Error("tool_result blocks are not matching any tool_use from the previous message");
36259
+ }
36260
+ }
36261
+ if (hasPreviousToolUse) {
36262
+ const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
36263
+ const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
36264
+ if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
36265
+ throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
36266
+ }
36267
+ }
36268
+ }
36269
+ return this.requestStream({
36270
+ method: "sampling/createMessage",
36271
+ params
36272
+ }, CreateMessageResultSchema, options);
36273
+ }
36274
+ /**
36275
+ * Sends an elicitation request and returns an AsyncGenerator that yields response messages.
36276
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
36277
+ *
36278
+ * For task-augmented requests (especially URL-based elicitation), yields 'taskCreated'
36279
+ * and 'taskStatus' messages before the final result.
36280
+ *
36281
+ * @example
36282
+ * ```typescript
36283
+ * const stream = server.experimental.tasks.elicitInputStream({
36284
+ * mode: 'url',
36285
+ * message: 'Please authenticate',
36286
+ * elicitationId: 'auth-123',
36287
+ * url: 'https://example.com/auth'
36288
+ * }, {
36289
+ * task: { ttl: 300000 } // Task-augmented for long-running auth flow
36290
+ * });
36291
+ *
36292
+ * for await (const message of stream) {
36293
+ * switch (message.type) {
36294
+ * case 'taskCreated':
36295
+ * console.log('Task created:', message.task.taskId);
36296
+ * break;
36297
+ * case 'taskStatus':
36298
+ * console.log('Task status:', message.task.status);
36299
+ * break;
36300
+ * case 'result':
36301
+ * console.log('User action:', message.result.action);
36302
+ * break;
36303
+ * case 'error':
36304
+ * console.error('Error:', message.error);
36305
+ * break;
36306
+ * }
36307
+ * }
36308
+ * ```
36309
+ *
36310
+ * @param params - The elicitation request parameters
36311
+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
36312
+ * @returns AsyncGenerator that yields ResponseMessage objects
36313
+ *
36314
+ * @experimental
36315
+ */
36316
+ elicitInputStream(params, options) {
36317
+ const clientCapabilities = this._server.getClientCapabilities();
36318
+ const mode = params.mode ?? "form";
36319
+ switch (mode) {
36320
+ case "url": {
36321
+ if (!clientCapabilities?.elicitation?.url) {
36322
+ throw new Error("Client does not support url elicitation.");
36323
+ }
36324
+ break;
36325
+ }
36326
+ case "form": {
36327
+ if (!clientCapabilities?.elicitation?.form) {
36328
+ throw new Error("Client does not support form elicitation.");
36329
+ }
36330
+ break;
36331
+ }
36332
+ }
36333
+ const normalizedParams = mode === "form" && params.mode === void 0 ? { ...params, mode: "form" } : params;
36334
+ return this.requestStream({
36335
+ method: "elicitation/create",
36336
+ params: normalizedParams
36337
+ }, ElicitResultSchema, options);
36338
+ }
36339
+ /**
36340
+ * Gets the current status of a task.
36341
+ *
36342
+ * @param taskId - The task identifier
36343
+ * @param options - Optional request options
36344
+ * @returns The task status
36345
+ *
36346
+ * @experimental
36347
+ */
36348
+ async getTask(taskId, options) {
36349
+ return this._server.getTask({ taskId }, options);
36350
+ }
36351
+ /**
36352
+ * Retrieves the result of a completed task.
36353
+ *
36354
+ * @param taskId - The task identifier
36355
+ * @param resultSchema - Zod schema for validating the result
36356
+ * @param options - Optional request options
36357
+ * @returns The task result
36358
+ *
36359
+ * @experimental
36360
+ */
36361
+ async getTaskResult(taskId, resultSchema, options) {
36362
+ return this._server.getTaskResult({ taskId }, resultSchema, options);
36363
+ }
36364
+ /**
36365
+ * Lists tasks with optional pagination.
36366
+ *
36367
+ * @param cursor - Optional pagination cursor
36368
+ * @param options - Optional request options
36369
+ * @returns List of tasks with optional next cursor
36370
+ *
36371
+ * @experimental
36372
+ */
36373
+ async listTasks(cursor, options) {
36374
+ return this._server.listTasks(cursor ? { cursor } : void 0, options);
36375
+ }
36376
+ /**
36377
+ * Cancels a running task.
36378
+ *
36379
+ * @param taskId - The task identifier
36380
+ * @param options - Optional request options
36381
+ *
36382
+ * @experimental
36383
+ */
36384
+ async cancelTask(taskId, options) {
36385
+ return this._server.cancelTask({ taskId }, options);
36386
+ }
36387
+ };
36388
+
36389
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
36390
+ function assertToolsCallTaskCapability(requests, method, entityName) {
36391
+ if (!requests) {
36392
+ throw new Error(`${entityName} does not support task creation (required for ${method})`);
36393
+ }
36394
+ switch (method) {
36395
+ case "tools/call":
36396
+ if (!requests.tools?.call) {
36397
+ throw new Error(`${entityName} does not support task creation for tools/call (required for ${method})`);
36398
+ }
36399
+ break;
36400
+ default:
36401
+ break;
36402
+ }
36403
+ }
36404
+ function assertClientRequestTaskCapability(requests, method, entityName) {
36405
+ if (!requests) {
36406
+ throw new Error(`${entityName} does not support task creation (required for ${method})`);
36407
+ }
36408
+ switch (method) {
36409
+ case "sampling/createMessage":
36410
+ if (!requests.sampling?.createMessage) {
36411
+ throw new Error(`${entityName} does not support task creation for sampling/createMessage (required for ${method})`);
36412
+ }
36413
+ break;
36414
+ case "elicitation/create":
36415
+ if (!requests.elicitation?.create) {
36416
+ throw new Error(`${entityName} does not support task creation for elicitation/create (required for ${method})`);
36417
+ }
36418
+ break;
36419
+ default:
36420
+ break;
36421
+ }
36422
+ }
36423
+
36424
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
36425
+ var Server = class extends Protocol {
36426
+ /**
36427
+ * Initializes this server with the given name and version information.
36428
+ */
36429
+ constructor(_serverInfo, options) {
36430
+ super(options);
36431
+ this._serverInfo = _serverInfo;
36432
+ this._loggingLevels = /* @__PURE__ */ new Map();
36433
+ this.LOG_LEVEL_SEVERITY = new Map(LoggingLevelSchema.options.map((level, index) => [level, index]));
36434
+ this.isMessageIgnored = (level, sessionId) => {
36435
+ const currentLevel = this._loggingLevels.get(sessionId);
36436
+ return currentLevel ? this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(currentLevel) : false;
36437
+ };
36438
+ this._capabilities = options?.capabilities ?? {};
36439
+ this._instructions = options?.instructions;
36440
+ this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new AjvJsonSchemaValidator();
36441
+ this.setRequestHandler(InitializeRequestSchema, (request) => this._oninitialize(request));
36442
+ this.setNotificationHandler(InitializedNotificationSchema, () => this.oninitialized?.());
36443
+ if (this._capabilities.logging) {
36444
+ this.setRequestHandler(SetLevelRequestSchema, async (request, extra) => {
36445
+ const transportSessionId = extra.sessionId || extra.requestInfo?.headers["mcp-session-id"] || void 0;
36446
+ const { level } = request.params;
36447
+ const parseResult = LoggingLevelSchema.safeParse(level);
36448
+ if (parseResult.success) {
36449
+ this._loggingLevels.set(transportSessionId, parseResult.data);
36450
+ }
36451
+ return {};
36452
+ });
36453
+ }
36454
+ }
36455
+ /**
36456
+ * Access experimental features.
36457
+ *
36458
+ * WARNING: These APIs are experimental and may change without notice.
36459
+ *
36460
+ * @experimental
36461
+ */
36462
+ get experimental() {
36463
+ if (!this._experimental) {
36464
+ this._experimental = {
36465
+ tasks: new ExperimentalServerTasks(this)
36466
+ };
36467
+ }
36468
+ return this._experimental;
36469
+ }
36470
+ /**
36471
+ * Registers new capabilities. This can only be called before connecting to a transport.
36472
+ *
36473
+ * The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).
36474
+ */
36475
+ registerCapabilities(capabilities) {
36476
+ if (this.transport) {
36477
+ throw new Error("Cannot register capabilities after connecting to transport");
36478
+ }
36479
+ this._capabilities = mergeCapabilities(this._capabilities, capabilities);
36480
+ }
36481
+ /**
36482
+ * Override request handler registration to enforce server-side validation for tools/call.
36483
+ */
36484
+ setRequestHandler(requestSchema, handler) {
36485
+ const shape = getObjectShape(requestSchema);
36486
+ const methodSchema = shape?.method;
36487
+ if (!methodSchema) {
36488
+ throw new Error("Schema is missing a method literal");
36489
+ }
36490
+ let methodValue;
36491
+ if (isZ4Schema(methodSchema)) {
36492
+ const v4Schema = methodSchema;
36493
+ const v4Def = v4Schema._zod?.def;
36494
+ methodValue = v4Def?.value ?? v4Schema.value;
36495
+ } else {
36496
+ const v3Schema = methodSchema;
36497
+ const legacyDef = v3Schema._def;
36498
+ methodValue = legacyDef?.value ?? v3Schema.value;
36499
+ }
36500
+ if (typeof methodValue !== "string") {
36501
+ throw new Error("Schema method literal must be a string");
36502
+ }
36503
+ const method = methodValue;
36504
+ if (method === "tools/call") {
36505
+ const wrappedHandler = async (request, extra) => {
36506
+ const validatedRequest = safeParse2(CallToolRequestSchema, request);
36507
+ if (!validatedRequest.success) {
36508
+ const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
36509
+ throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage}`);
36510
+ }
36511
+ const { params } = validatedRequest.data;
36512
+ const result = await Promise.resolve(handler(request, extra));
36513
+ if (params.task) {
36514
+ const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
36515
+ if (!taskValidationResult.success) {
36516
+ const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
36517
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
36518
+ }
36519
+ return taskValidationResult.data;
36520
+ }
36521
+ const validationResult = safeParse2(CallToolResultSchema, result);
36522
+ if (!validationResult.success) {
36523
+ const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
36524
+ throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${errorMessage}`);
36525
+ }
36526
+ return validationResult.data;
36527
+ };
36528
+ return super.setRequestHandler(requestSchema, wrappedHandler);
36529
+ }
36530
+ return super.setRequestHandler(requestSchema, handler);
36531
+ }
36532
+ assertCapabilityForMethod(method) {
36533
+ switch (method) {
36534
+ case "sampling/createMessage":
36535
+ if (!this._clientCapabilities?.sampling) {
36536
+ throw new Error(`Client does not support sampling (required for ${method})`);
36537
+ }
36538
+ break;
36539
+ case "elicitation/create":
36540
+ if (!this._clientCapabilities?.elicitation) {
36541
+ throw new Error(`Client does not support elicitation (required for ${method})`);
36542
+ }
36543
+ break;
36544
+ case "roots/list":
36545
+ if (!this._clientCapabilities?.roots) {
36546
+ throw new Error(`Client does not support listing roots (required for ${method})`);
36547
+ }
36548
+ break;
36549
+ case "ping":
36550
+ break;
36551
+ }
36552
+ }
36553
+ assertNotificationCapability(method) {
36554
+ switch (method) {
36555
+ case "notifications/message":
36556
+ if (!this._capabilities.logging) {
36557
+ throw new Error(`Server does not support logging (required for ${method})`);
36558
+ }
36559
+ break;
36560
+ case "notifications/resources/updated":
36561
+ case "notifications/resources/list_changed":
36562
+ if (!this._capabilities.resources) {
36563
+ throw new Error(`Server does not support notifying about resources (required for ${method})`);
36564
+ }
36565
+ break;
36566
+ case "notifications/tools/list_changed":
36567
+ if (!this._capabilities.tools) {
36568
+ throw new Error(`Server does not support notifying of tool list changes (required for ${method})`);
36569
+ }
36570
+ break;
36571
+ case "notifications/prompts/list_changed":
36572
+ if (!this._capabilities.prompts) {
36573
+ throw new Error(`Server does not support notifying of prompt list changes (required for ${method})`);
36574
+ }
36575
+ break;
36576
+ case "notifications/elicitation/complete":
36577
+ if (!this._clientCapabilities?.elicitation?.url) {
36578
+ throw new Error(`Client does not support URL elicitation (required for ${method})`);
36579
+ }
36580
+ break;
36581
+ case "notifications/cancelled":
36582
+ break;
36583
+ case "notifications/progress":
36584
+ break;
36585
+ }
36586
+ }
36587
+ assertRequestHandlerCapability(method) {
36588
+ if (!this._capabilities) {
36589
+ return;
36590
+ }
36591
+ switch (method) {
36592
+ case "completion/complete":
36593
+ if (!this._capabilities.completions) {
36594
+ throw new Error(`Server does not support completions (required for ${method})`);
36595
+ }
36596
+ break;
36597
+ case "logging/setLevel":
36598
+ if (!this._capabilities.logging) {
36599
+ throw new Error(`Server does not support logging (required for ${method})`);
36600
+ }
36601
+ break;
36602
+ case "prompts/get":
36603
+ case "prompts/list":
36604
+ if (!this._capabilities.prompts) {
36605
+ throw new Error(`Server does not support prompts (required for ${method})`);
36606
+ }
36607
+ break;
36608
+ case "resources/list":
36609
+ case "resources/templates/list":
36610
+ case "resources/read":
36611
+ if (!this._capabilities.resources) {
36612
+ throw new Error(`Server does not support resources (required for ${method})`);
36613
+ }
36614
+ break;
36615
+ case "tools/call":
36616
+ case "tools/list":
36617
+ if (!this._capabilities.tools) {
36618
+ throw new Error(`Server does not support tools (required for ${method})`);
36619
+ }
36620
+ break;
36621
+ case "tasks/get":
36622
+ case "tasks/list":
36623
+ case "tasks/result":
36624
+ case "tasks/cancel":
36625
+ if (!this._capabilities.tasks) {
36626
+ throw new Error(`Server does not support tasks capability (required for ${method})`);
36627
+ }
36628
+ break;
36629
+ case "ping":
36630
+ case "initialize":
36631
+ break;
36632
+ }
36633
+ }
36634
+ assertTaskCapability(method) {
36635
+ assertClientRequestTaskCapability(this._clientCapabilities?.tasks?.requests, method, "Client");
36636
+ }
36637
+ assertTaskHandlerCapability(method) {
36638
+ if (!this._capabilities) {
36639
+ return;
36640
+ }
36641
+ assertToolsCallTaskCapability(this._capabilities.tasks?.requests, method, "Server");
36642
+ }
36643
+ async _oninitialize(request) {
36644
+ const requestedVersion = request.params.protocolVersion;
36645
+ this._clientCapabilities = request.params.capabilities;
36646
+ this._clientVersion = request.params.clientInfo;
36647
+ const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion) ? requestedVersion : LATEST_PROTOCOL_VERSION;
36648
+ return {
36649
+ protocolVersion,
36650
+ capabilities: this.getCapabilities(),
36651
+ serverInfo: this._serverInfo,
36652
+ ...this._instructions && { instructions: this._instructions }
36653
+ };
36654
+ }
36655
+ /**
36656
+ * After initialization has completed, this will be populated with the client's reported capabilities.
36657
+ */
36658
+ getClientCapabilities() {
36659
+ return this._clientCapabilities;
36660
+ }
36661
+ /**
36662
+ * After initialization has completed, this will be populated with information about the client's name and version.
36663
+ */
36664
+ getClientVersion() {
36665
+ return this._clientVersion;
36666
+ }
36667
+ getCapabilities() {
36668
+ return this._capabilities;
36669
+ }
36670
+ async ping() {
36671
+ return this.request({ method: "ping" }, EmptyResultSchema);
36672
+ }
36673
+ // Implementation
36674
+ async createMessage(params, options) {
36675
+ if (params.tools || params.toolChoice) {
36676
+ if (!this._clientCapabilities?.sampling?.tools) {
36677
+ throw new Error("Client does not support sampling tools capability.");
36678
+ }
36463
36679
  }
36464
36680
  if (params.messages.length > 0) {
36465
36681
  const lastMessage = params.messages[params.messages.length - 1];
@@ -37458,1229 +37674,98 @@ var EMPTY_COMPLETION_RESULT = {
37458
37674
  }
37459
37675
  };
37460
37676
 
37461
- // node_modules/@hono/node-server/dist/index.mjs
37462
- var import_http = require("http");
37463
- var import_http2 = require("http2");
37464
- var import_http22 = require("http2");
37465
- var import_stream = require("stream");
37466
- var import_crypto = __toESM(require("crypto"), 1);
37467
- var RequestError = class extends Error {
37468
- constructor(message, options) {
37469
- super(message, options);
37470
- this.name = "RequestError";
37471
- }
37472
- };
37473
- var toRequestError = (e) => {
37474
- if (e instanceof RequestError) {
37475
- return e;
37476
- }
37477
- return new RequestError(e.message, { cause: e });
37478
- };
37479
- var GlobalRequest = global.Request;
37480
- var Request = class extends GlobalRequest {
37481
- constructor(input, options) {
37482
- if (typeof input === "object" && getRequestCache in input) {
37483
- input = input[getRequestCache]();
37484
- }
37485
- if (typeof options?.body?.getReader !== "undefined") {
37486
- ;
37487
- options.duplex ?? (options.duplex = "half");
37488
- }
37489
- super(input, options);
37490
- }
37491
- };
37492
- var newHeadersFromIncoming = (incoming) => {
37493
- const headerRecord = [];
37494
- const rawHeaders = incoming.rawHeaders;
37495
- for (let i = 0; i < rawHeaders.length; i += 2) {
37496
- const { [i]: key, [i + 1]: value } = rawHeaders;
37497
- if (key.charCodeAt(0) !== /*:*/
37498
- 58) {
37499
- headerRecord.push([key, value]);
37500
- }
37501
- }
37502
- return new Headers(headerRecord);
37503
- };
37504
- var wrapBodyStream = Symbol("wrapBodyStream");
37505
- var newRequestFromIncoming = (method, url2, headers, incoming, abortController) => {
37506
- const init = {
37507
- method,
37508
- headers,
37509
- signal: abortController.signal
37510
- };
37511
- if (method === "TRACE") {
37512
- init.method = "GET";
37513
- const req = new Request(url2, init);
37514
- Object.defineProperty(req, "method", {
37515
- get() {
37516
- return "TRACE";
37517
- }
37518
- });
37519
- return req;
37520
- }
37521
- if (!(method === "GET" || method === "HEAD")) {
37522
- if ("rawBody" in incoming && incoming.rawBody instanceof Buffer) {
37523
- init.body = new ReadableStream({
37524
- start(controller) {
37525
- controller.enqueue(incoming.rawBody);
37526
- controller.close();
37527
- }
37528
- });
37529
- } else if (incoming[wrapBodyStream]) {
37530
- let reader;
37531
- init.body = new ReadableStream({
37532
- async pull(controller) {
37533
- try {
37534
- reader || (reader = import_stream.Readable.toWeb(incoming).getReader());
37535
- const { done, value } = await reader.read();
37536
- if (done) {
37537
- controller.close();
37538
- } else {
37539
- controller.enqueue(value);
37540
- }
37541
- } catch (error48) {
37542
- controller.error(error48);
37543
- }
37544
- }
37545
- });
37546
- } else {
37547
- init.body = import_stream.Readable.toWeb(incoming);
37548
- }
37549
- }
37550
- return new Request(url2, init);
37551
- };
37552
- var getRequestCache = Symbol("getRequestCache");
37553
- var requestCache = Symbol("requestCache");
37554
- var incomingKey = Symbol("incomingKey");
37555
- var urlKey = Symbol("urlKey");
37556
- var headersKey = Symbol("headersKey");
37557
- var abortControllerKey = Symbol("abortControllerKey");
37558
- var getAbortController = Symbol("getAbortController");
37559
- var requestPrototype = {
37560
- get method() {
37561
- return this[incomingKey].method || "GET";
37562
- },
37563
- get url() {
37564
- return this[urlKey];
37565
- },
37566
- get headers() {
37567
- return this[headersKey] || (this[headersKey] = newHeadersFromIncoming(this[incomingKey]));
37568
- },
37569
- [getAbortController]() {
37570
- this[getRequestCache]();
37571
- return this[abortControllerKey];
37572
- },
37573
- [getRequestCache]() {
37574
- this[abortControllerKey] || (this[abortControllerKey] = new AbortController());
37575
- return this[requestCache] || (this[requestCache] = newRequestFromIncoming(
37576
- this.method,
37577
- this[urlKey],
37578
- this.headers,
37579
- this[incomingKey],
37580
- this[abortControllerKey]
37581
- ));
37677
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
37678
+ var import_node_process = __toESM(require("process"), 1);
37679
+
37680
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
37681
+ var ReadBuffer = class {
37682
+ append(chunk) {
37683
+ this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
37582
37684
  }
37583
- };
37584
- [
37585
- "body",
37586
- "bodyUsed",
37587
- "cache",
37588
- "credentials",
37589
- "destination",
37590
- "integrity",
37591
- "mode",
37592
- "redirect",
37593
- "referrer",
37594
- "referrerPolicy",
37595
- "signal",
37596
- "keepalive"
37597
- ].forEach((k) => {
37598
- Object.defineProperty(requestPrototype, k, {
37599
- get() {
37600
- return this[getRequestCache]()[k];
37601
- }
37602
- });
37603
- });
37604
- ["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
37605
- Object.defineProperty(requestPrototype, k, {
37606
- value: function() {
37607
- return this[getRequestCache]()[k]();
37608
- }
37609
- });
37610
- });
37611
- Object.setPrototypeOf(requestPrototype, Request.prototype);
37612
- var newRequest = (incoming, defaultHostname) => {
37613
- const req = Object.create(requestPrototype);
37614
- req[incomingKey] = incoming;
37615
- const incomingUrl = incoming.url || "";
37616
- if (incomingUrl[0] !== "/" && // short-circuit for performance. most requests are relative URL.
37617
- (incomingUrl.startsWith("http://") || incomingUrl.startsWith("https://"))) {
37618
- if (incoming instanceof import_http22.Http2ServerRequest) {
37619
- throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
37620
- }
37621
- try {
37622
- const url22 = new URL(incomingUrl);
37623
- req[urlKey] = url22.href;
37624
- } catch (e) {
37625
- throw new RequestError("Invalid absolute URL", { cause: e });
37685
+ readMessage() {
37686
+ if (!this._buffer) {
37687
+ return null;
37626
37688
  }
37627
- return req;
37628
- }
37629
- const host = (incoming instanceof import_http22.Http2ServerRequest ? incoming.authority : incoming.headers.host) || defaultHostname;
37630
- if (!host) {
37631
- throw new RequestError("Missing host header");
37632
- }
37633
- let scheme;
37634
- if (incoming instanceof import_http22.Http2ServerRequest) {
37635
- scheme = incoming.scheme;
37636
- if (!(scheme === "http" || scheme === "https")) {
37637
- throw new RequestError("Unsupported scheme");
37689
+ const index = this._buffer.indexOf("\n");
37690
+ if (index === -1) {
37691
+ return null;
37638
37692
  }
37639
- } else {
37640
- scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
37693
+ const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
37694
+ this._buffer = this._buffer.subarray(index + 1);
37695
+ return deserializeMessage(line);
37641
37696
  }
37642
- const url2 = new URL(`${scheme}://${host}${incomingUrl}`);
37643
- if (url2.hostname.length !== host.length && url2.hostname !== host.replace(/:\d+$/, "")) {
37644
- throw new RequestError("Invalid host header");
37697
+ clear() {
37698
+ this._buffer = void 0;
37645
37699
  }
37646
- req[urlKey] = url2.href;
37647
- return req;
37648
37700
  };
37649
- var responseCache = Symbol("responseCache");
37650
- var getResponseCache = Symbol("getResponseCache");
37651
- var cacheKey = Symbol("cache");
37652
- var GlobalResponse = global.Response;
37653
- var _body, _init, _a2;
37654
- var Response2 = (_a2 = class {
37655
- constructor(body, init) {
37656
- __privateAdd(this, _body, void 0);
37657
- __privateAdd(this, _init, void 0);
37658
- let headers;
37659
- __privateSet(this, _body, body);
37660
- if (init instanceof _a2) {
37661
- const cachedGlobalResponse = init[responseCache];
37662
- if (cachedGlobalResponse) {
37663
- __privateSet(this, _init, cachedGlobalResponse);
37664
- this[getResponseCache]();
37665
- return;
37666
- } else {
37667
- __privateSet(this, _init, __privateGet(init, _init));
37668
- headers = new Headers(__privateGet(init, _init).headers);
37669
- }
37670
- } else {
37671
- __privateSet(this, _init, init);
37672
- }
37673
- if (typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) {
37674
- headers || (headers = init?.headers || { "content-type": "text/plain; charset=UTF-8" });
37675
- this[cacheKey] = [init?.status || 200, body, headers];
37676
- }
37677
- }
37678
- [getResponseCache]() {
37679
- delete this[cacheKey];
37680
- return this[responseCache] || (this[responseCache] = new GlobalResponse(__privateGet(this, _body), __privateGet(this, _init)));
37681
- }
37682
- get headers() {
37683
- const cache = this[cacheKey];
37684
- if (cache) {
37685
- if (!(cache[2] instanceof Headers)) {
37686
- cache[2] = new Headers(cache[2]);
37687
- }
37688
- return cache[2];
37689
- }
37690
- return this[getResponseCache]().headers;
37691
- }
37692
- get status() {
37693
- return this[cacheKey]?.[0] ?? this[getResponseCache]().status;
37694
- }
37695
- get ok() {
37696
- const status = this.status;
37697
- return status >= 200 && status < 300;
37698
- }
37699
- }, _body = new WeakMap(), _init = new WeakMap(), _a2);
37700
- ["body", "bodyUsed", "redirected", "statusText", "trailers", "type", "url"].forEach((k) => {
37701
- Object.defineProperty(Response2.prototype, k, {
37702
- get() {
37703
- return this[getResponseCache]()[k];
37704
- }
37705
- });
37706
- });
37707
- ["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
37708
- Object.defineProperty(Response2.prototype, k, {
37709
- value: function() {
37710
- return this[getResponseCache]()[k]();
37711
- }
37712
- });
37713
- });
37714
- Object.setPrototypeOf(Response2, GlobalResponse);
37715
- Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
37716
- async function readWithoutBlocking(readPromise) {
37717
- return Promise.race([readPromise, Promise.resolve().then(() => Promise.resolve(void 0))]);
37718
- }
37719
- function writeFromReadableStreamDefaultReader(reader, writable, currentReadPromise) {
37720
- const cancel = (error48) => {
37721
- reader.cancel(error48).catch(() => {
37722
- });
37723
- };
37724
- writable.on("close", cancel);
37725
- writable.on("error", cancel);
37726
- (currentReadPromise ?? reader.read()).then(flow, handleStreamError);
37727
- return reader.closed.finally(() => {
37728
- writable.off("close", cancel);
37729
- writable.off("error", cancel);
37730
- });
37731
- function handleStreamError(error48) {
37732
- if (error48) {
37733
- writable.destroy(error48);
37734
- }
37735
- }
37736
- function onDrain() {
37737
- reader.read().then(flow, handleStreamError);
37738
- }
37739
- function flow({ done, value }) {
37740
- try {
37741
- if (done) {
37742
- writable.end();
37743
- } else if (!writable.write(value)) {
37744
- writable.once("drain", onDrain);
37745
- } else {
37746
- return reader.read().then(flow, handleStreamError);
37747
- }
37748
- } catch (e) {
37749
- handleStreamError(e);
37750
- }
37751
- }
37752
- }
37753
- function writeFromReadableStream(stream, writable) {
37754
- if (stream.locked) {
37755
- throw new TypeError("ReadableStream is locked.");
37756
- } else if (writable.destroyed) {
37757
- return;
37758
- }
37759
- return writeFromReadableStreamDefaultReader(stream.getReader(), writable);
37701
+ function deserializeMessage(line) {
37702
+ return JSONRPCMessageSchema.parse(JSON.parse(line));
37760
37703
  }
37761
- var buildOutgoingHttpHeaders = (headers) => {
37762
- const res = {};
37763
- if (!(headers instanceof Headers)) {
37764
- headers = new Headers(headers ?? void 0);
37765
- }
37766
- const cookies = [];
37767
- for (const [k, v] of headers) {
37768
- if (k === "set-cookie") {
37769
- cookies.push(v);
37770
- } else {
37771
- res[k] = v;
37772
- }
37773
- }
37774
- if (cookies.length > 0) {
37775
- res["set-cookie"] = cookies;
37776
- }
37777
- res["content-type"] ?? (res["content-type"] = "text/plain; charset=UTF-8");
37778
- return res;
37779
- };
37780
- var X_ALREADY_SENT = "x-hono-already-sent";
37781
- if (typeof global.crypto === "undefined") {
37782
- global.crypto = import_crypto.default;
37704
+ function serializeMessage(message) {
37705
+ return JSON.stringify(message) + "\n";
37783
37706
  }
37784
- var outgoingEnded = Symbol("outgoingEnded");
37785
- var handleRequestError = () => new Response(null, {
37786
- status: 400
37787
- });
37788
- var handleFetchError = (e) => new Response(null, {
37789
- status: e instanceof Error && (e.name === "TimeoutError" || e.constructor.name === "TimeoutError") ? 504 : 500
37790
- });
37791
- var handleResponseError = (e, outgoing) => {
37792
- const err = e instanceof Error ? e : new Error("unknown error", { cause: e });
37793
- if (err.code === "ERR_STREAM_PREMATURE_CLOSE") {
37794
- console.info("The user aborted a request.");
37795
- } else {
37796
- console.error(e);
37797
- if (!outgoing.headersSent) {
37798
- outgoing.writeHead(500, { "Content-Type": "text/plain" });
37799
- }
37800
- outgoing.end(`Error: ${err.message}`);
37801
- outgoing.destroy(err);
37802
- }
37803
- };
37804
- var flushHeaders = (outgoing) => {
37805
- if ("flushHeaders" in outgoing && outgoing.writable) {
37806
- outgoing.flushHeaders();
37807
- }
37808
- };
37809
- var responseViaCache = async (res, outgoing) => {
37810
- let [status, body, header] = res[cacheKey];
37811
- if (header instanceof Headers) {
37812
- header = buildOutgoingHttpHeaders(header);
37813
- }
37814
- if (typeof body === "string") {
37815
- header["Content-Length"] = Buffer.byteLength(body);
37816
- } else if (body instanceof Uint8Array) {
37817
- header["Content-Length"] = body.byteLength;
37818
- } else if (body instanceof Blob) {
37819
- header["Content-Length"] = body.size;
37820
- }
37821
- outgoing.writeHead(status, header);
37822
- if (typeof body === "string" || body instanceof Uint8Array) {
37823
- outgoing.end(body);
37824
- } else if (body instanceof Blob) {
37825
- outgoing.end(new Uint8Array(await body.arrayBuffer()));
37826
- } else {
37827
- flushHeaders(outgoing);
37828
- await writeFromReadableStream(body, outgoing)?.catch(
37829
- (e) => handleResponseError(e, outgoing)
37830
- );
37831
- }
37832
- ;
37833
- outgoing[outgoingEnded]?.();
37834
- };
37835
- var isPromise = (res) => typeof res.then === "function";
37836
- var responseViaResponseObject = async (res, outgoing, options = {}) => {
37837
- if (isPromise(res)) {
37838
- if (options.errorHandler) {
37839
- try {
37840
- res = await res;
37841
- } catch (err) {
37842
- const errRes = await options.errorHandler(err);
37843
- if (!errRes) {
37844
- return;
37845
- }
37846
- res = errRes;
37847
- }
37848
- } else {
37849
- res = await res.catch(handleFetchError);
37850
- }
37851
- }
37852
- if (cacheKey in res) {
37853
- return responseViaCache(res, outgoing);
37854
- }
37855
- const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
37856
- if (res.body) {
37857
- const reader = res.body.getReader();
37858
- const values = [];
37859
- let done = false;
37860
- let currentReadPromise = void 0;
37861
- if (resHeaderRecord["transfer-encoding"] !== "chunked") {
37862
- let maxReadCount = 2;
37863
- for (let i = 0; i < maxReadCount; i++) {
37864
- currentReadPromise || (currentReadPromise = reader.read());
37865
- const chunk = await readWithoutBlocking(currentReadPromise).catch((e) => {
37866
- console.error(e);
37867
- done = true;
37868
- });
37869
- if (!chunk) {
37870
- if (i === 1) {
37871
- await new Promise((resolve3) => setTimeout(resolve3));
37872
- maxReadCount = 3;
37873
- continue;
37874
- }
37875
- break;
37876
- }
37877
- currentReadPromise = void 0;
37878
- if (chunk.value) {
37879
- values.push(chunk.value);
37880
- }
37881
- if (chunk.done) {
37882
- done = true;
37883
- break;
37884
- }
37885
- }
37886
- if (done && !("content-length" in resHeaderRecord)) {
37887
- resHeaderRecord["content-length"] = values.reduce((acc, value) => acc + value.length, 0);
37888
- }
37889
- }
37890
- outgoing.writeHead(res.status, resHeaderRecord);
37891
- values.forEach((value) => {
37892
- ;
37893
- outgoing.write(value);
37894
- });
37895
- if (done) {
37896
- outgoing.end();
37897
- } else {
37898
- if (values.length === 0) {
37899
- flushHeaders(outgoing);
37900
- }
37901
- await writeFromReadableStreamDefaultReader(reader, outgoing, currentReadPromise);
37902
- }
37903
- } else if (resHeaderRecord[X_ALREADY_SENT]) {
37904
- } else {
37905
- outgoing.writeHead(res.status, resHeaderRecord);
37906
- outgoing.end();
37907
- }
37908
- ;
37909
- outgoing[outgoingEnded]?.();
37910
- };
37911
- var getRequestListener = (fetchCallback, options = {}) => {
37912
- const autoCleanupIncoming = options.autoCleanupIncoming ?? true;
37913
- if (options.overrideGlobalObjects !== false && global.Request !== Request) {
37914
- Object.defineProperty(global, "Request", {
37915
- value: Request
37916
- });
37917
- Object.defineProperty(global, "Response", {
37918
- value: Response2
37919
- });
37920
- }
37921
- return async (incoming, outgoing) => {
37922
- let res, req;
37923
- try {
37924
- req = newRequest(incoming, options.hostname);
37925
- let incomingEnded = !autoCleanupIncoming || incoming.method === "GET" || incoming.method === "HEAD";
37926
- if (!incomingEnded) {
37927
- ;
37928
- incoming[wrapBodyStream] = true;
37929
- incoming.on("end", () => {
37930
- incomingEnded = true;
37931
- });
37932
- if (incoming instanceof import_http2.Http2ServerRequest) {
37933
- ;
37934
- outgoing[outgoingEnded] = () => {
37935
- if (!incomingEnded) {
37936
- setTimeout(() => {
37937
- if (!incomingEnded) {
37938
- setTimeout(() => {
37939
- incoming.destroy();
37940
- outgoing.destroy();
37941
- });
37942
- }
37943
- });
37944
- }
37945
- };
37946
- }
37947
- }
37948
- outgoing.on("close", () => {
37949
- const abortController = req[abortControllerKey];
37950
- if (abortController) {
37951
- if (incoming.errored) {
37952
- req[abortControllerKey].abort(incoming.errored.toString());
37953
- } else if (!outgoing.writableFinished) {
37954
- req[abortControllerKey].abort("Client connection prematurely closed.");
37955
- }
37956
- }
37957
- if (!incomingEnded) {
37958
- setTimeout(() => {
37959
- if (!incomingEnded) {
37960
- setTimeout(() => {
37961
- incoming.destroy();
37962
- });
37963
- }
37964
- });
37965
- }
37966
- });
37967
- res = fetchCallback(req, { incoming, outgoing });
37968
- if (cacheKey in res) {
37969
- return responseViaCache(res, outgoing);
37970
- }
37971
- } catch (e) {
37972
- if (!res) {
37973
- if (options.errorHandler) {
37974
- res = await options.errorHandler(req ? e : toRequestError(e));
37975
- if (!res) {
37976
- return;
37977
- }
37978
- } else if (!req) {
37979
- res = handleRequestError();
37980
- } else {
37981
- res = handleFetchError(e);
37982
- }
37983
- } else {
37984
- return handleResponseError(e, outgoing);
37985
- }
37986
- }
37987
- try {
37988
- return await responseViaResponseObject(res, outgoing, options);
37989
- } catch (e) {
37990
- return handleResponseError(e, outgoing);
37991
- }
37992
- };
37993
- };
37994
37707
 
37995
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js
37996
- var WebStandardStreamableHTTPServerTransport = class {
37997
- constructor(options = {}) {
37708
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
37709
+ var StdioServerTransport = class {
37710
+ constructor(_stdin = import_node_process.default.stdin, _stdout = import_node_process.default.stdout) {
37711
+ this._stdin = _stdin;
37712
+ this._stdout = _stdout;
37713
+ this._readBuffer = new ReadBuffer();
37998
37714
  this._started = false;
37999
- this._hasHandledRequest = false;
38000
- this._streamMapping = /* @__PURE__ */ new Map();
38001
- this._requestToStreamMapping = /* @__PURE__ */ new Map();
38002
- this._requestResponseMap = /* @__PURE__ */ new Map();
38003
- this._initialized = false;
38004
- this._enableJsonResponse = false;
38005
- this._standaloneSseStreamId = "_GET_stream";
38006
- this.sessionIdGenerator = options.sessionIdGenerator;
38007
- this._enableJsonResponse = options.enableJsonResponse ?? false;
38008
- this._eventStore = options.eventStore;
38009
- this._onsessioninitialized = options.onsessioninitialized;
38010
- this._onsessionclosed = options.onsessionclosed;
38011
- this._allowedHosts = options.allowedHosts;
38012
- this._allowedOrigins = options.allowedOrigins;
38013
- this._enableDnsRebindingProtection = options.enableDnsRebindingProtection ?? false;
38014
- this._retryInterval = options.retryInterval;
37715
+ this._ondata = (chunk) => {
37716
+ this._readBuffer.append(chunk);
37717
+ this.processReadBuffer();
37718
+ };
37719
+ this._onerror = (error48) => {
37720
+ this.onerror?.(error48);
37721
+ };
38015
37722
  }
38016
37723
  /**
38017
- * Starts the transport. This is required by the Transport interface but is a no-op
38018
- * for the Streamable HTTP transport as connections are managed per-request.
37724
+ * Starts listening for messages on stdin.
38019
37725
  */
38020
37726
  async start() {
38021
37727
  if (this._started) {
38022
- throw new Error("Transport already started");
37728
+ throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
38023
37729
  }
38024
37730
  this._started = true;
37731
+ this._stdin.on("data", this._ondata);
37732
+ this._stdin.on("error", this._onerror);
38025
37733
  }
38026
- /**
38027
- * Helper to create a JSON error response
38028
- */
38029
- createJsonErrorResponse(status, code, message, options) {
38030
- const error48 = { code, message };
38031
- if (options?.data !== void 0) {
38032
- error48.data = options.data;
38033
- }
38034
- return new Response(JSON.stringify({
38035
- jsonrpc: "2.0",
38036
- error: error48,
38037
- id: null
38038
- }), {
38039
- status,
38040
- headers: {
38041
- "Content-Type": "application/json",
38042
- ...options?.headers
38043
- }
38044
- });
38045
- }
38046
- /**
38047
- * Validates request headers for DNS rebinding protection.
38048
- * @returns Error response if validation fails, undefined if validation passes.
38049
- */
38050
- validateRequestHeaders(req) {
38051
- if (!this._enableDnsRebindingProtection) {
38052
- return void 0;
38053
- }
38054
- if (this._allowedHosts && this._allowedHosts.length > 0) {
38055
- const hostHeader = req.headers.get("host");
38056
- if (!hostHeader || !this._allowedHosts.includes(hostHeader)) {
38057
- const error48 = `Invalid Host header: ${hostHeader}`;
38058
- this.onerror?.(new Error(error48));
38059
- return this.createJsonErrorResponse(403, -32e3, error48);
38060
- }
38061
- }
38062
- if (this._allowedOrigins && this._allowedOrigins.length > 0) {
38063
- const originHeader = req.headers.get("origin");
38064
- if (originHeader && !this._allowedOrigins.includes(originHeader)) {
38065
- const error48 = `Invalid Origin header: ${originHeader}`;
38066
- this.onerror?.(new Error(error48));
38067
- return this.createJsonErrorResponse(403, -32e3, error48);
38068
- }
38069
- }
38070
- return void 0;
38071
- }
38072
- /**
38073
- * Handles an incoming HTTP request, whether GET, POST, or DELETE
38074
- * Returns a Response object (Web Standard)
38075
- */
38076
- async handleRequest(req, options) {
38077
- if (!this.sessionIdGenerator && this._hasHandledRequest) {
38078
- throw new Error("Stateless transport cannot be reused across requests. Create a new transport per request.");
38079
- }
38080
- this._hasHandledRequest = true;
38081
- const validationError = this.validateRequestHeaders(req);
38082
- if (validationError) {
38083
- return validationError;
38084
- }
38085
- switch (req.method) {
38086
- case "POST":
38087
- return this.handlePostRequest(req, options);
38088
- case "GET":
38089
- return this.handleGetRequest(req);
38090
- case "DELETE":
38091
- return this.handleDeleteRequest(req);
38092
- default:
38093
- return this.handleUnsupportedRequest();
38094
- }
38095
- }
38096
- /**
38097
- * Writes a priming event to establish resumption capability.
38098
- * Only sends if eventStore is configured (opt-in for resumability) and
38099
- * the client's protocol version supports empty SSE data (>= 2025-11-25).
38100
- */
38101
- async writePrimingEvent(controller, encoder, streamId, protocolVersion) {
38102
- if (!this._eventStore) {
38103
- return;
38104
- }
38105
- if (protocolVersion < "2025-11-25") {
38106
- return;
38107
- }
38108
- const primingEventId = await this._eventStore.storeEvent(streamId, {});
38109
- let primingEvent = `id: ${primingEventId}
38110
- data:
38111
-
38112
- `;
38113
- if (this._retryInterval !== void 0) {
38114
- primingEvent = `id: ${primingEventId}
38115
- retry: ${this._retryInterval}
38116
- data:
38117
-
38118
- `;
38119
- }
38120
- controller.enqueue(encoder.encode(primingEvent));
38121
- }
38122
- /**
38123
- * Handles GET requests for SSE stream
38124
- */
38125
- async handleGetRequest(req) {
38126
- const acceptHeader = req.headers.get("accept");
38127
- if (!acceptHeader?.includes("text/event-stream")) {
38128
- return this.createJsonErrorResponse(406, -32e3, "Not Acceptable: Client must accept text/event-stream");
38129
- }
38130
- const sessionError = this.validateSession(req);
38131
- if (sessionError) {
38132
- return sessionError;
38133
- }
38134
- const protocolError = this.validateProtocolVersion(req);
38135
- if (protocolError) {
38136
- return protocolError;
38137
- }
38138
- if (this._eventStore) {
38139
- const lastEventId = req.headers.get("last-event-id");
38140
- if (lastEventId) {
38141
- return this.replayEvents(lastEventId);
38142
- }
38143
- }
38144
- if (this._streamMapping.get(this._standaloneSseStreamId) !== void 0) {
38145
- return this.createJsonErrorResponse(409, -32e3, "Conflict: Only one SSE stream is allowed per session");
38146
- }
38147
- const encoder = new TextEncoder();
38148
- let streamController;
38149
- const readable = new ReadableStream({
38150
- start: (controller) => {
38151
- streamController = controller;
38152
- },
38153
- cancel: () => {
38154
- this._streamMapping.delete(this._standaloneSseStreamId);
38155
- }
38156
- });
38157
- const headers = {
38158
- "Content-Type": "text/event-stream",
38159
- "Cache-Control": "no-cache, no-transform",
38160
- Connection: "keep-alive"
38161
- };
38162
- if (this.sessionId !== void 0) {
38163
- headers["mcp-session-id"] = this.sessionId;
38164
- }
38165
- this._streamMapping.set(this._standaloneSseStreamId, {
38166
- controller: streamController,
38167
- encoder,
38168
- cleanup: () => {
38169
- this._streamMapping.delete(this._standaloneSseStreamId);
38170
- try {
38171
- streamController.close();
38172
- } catch {
38173
- }
38174
- }
38175
- });
38176
- return new Response(readable, { headers });
38177
- }
38178
- /**
38179
- * Replays events that would have been sent after the specified event ID
38180
- * Only used when resumability is enabled
38181
- */
38182
- async replayEvents(lastEventId) {
38183
- if (!this._eventStore) {
38184
- return this.createJsonErrorResponse(400, -32e3, "Event store not configured");
38185
- }
38186
- try {
38187
- let streamId;
38188
- if (this._eventStore.getStreamIdForEventId) {
38189
- streamId = await this._eventStore.getStreamIdForEventId(lastEventId);
38190
- if (!streamId) {
38191
- return this.createJsonErrorResponse(400, -32e3, "Invalid event ID format");
38192
- }
38193
- if (this._streamMapping.get(streamId) !== void 0) {
38194
- return this.createJsonErrorResponse(409, -32e3, "Conflict: Stream already has an active connection");
38195
- }
38196
- }
38197
- const headers = {
38198
- "Content-Type": "text/event-stream",
38199
- "Cache-Control": "no-cache, no-transform",
38200
- Connection: "keep-alive"
38201
- };
38202
- if (this.sessionId !== void 0) {
38203
- headers["mcp-session-id"] = this.sessionId;
38204
- }
38205
- const encoder = new TextEncoder();
38206
- let streamController;
38207
- const readable = new ReadableStream({
38208
- start: (controller) => {
38209
- streamController = controller;
38210
- },
38211
- cancel: () => {
38212
- }
38213
- });
38214
- const replayedStreamId = await this._eventStore.replayEventsAfter(lastEventId, {
38215
- send: async (eventId, message) => {
38216
- const success2 = this.writeSSEEvent(streamController, encoder, message, eventId);
38217
- if (!success2) {
38218
- this.onerror?.(new Error("Failed replay events"));
38219
- try {
38220
- streamController.close();
38221
- } catch {
38222
- }
38223
- }
38224
- }
38225
- });
38226
- this._streamMapping.set(replayedStreamId, {
38227
- controller: streamController,
38228
- encoder,
38229
- cleanup: () => {
38230
- this._streamMapping.delete(replayedStreamId);
38231
- try {
38232
- streamController.close();
38233
- } catch {
38234
- }
38235
- }
38236
- });
38237
- return new Response(readable, { headers });
38238
- } catch (error48) {
38239
- this.onerror?.(error48);
38240
- return this.createJsonErrorResponse(500, -32e3, "Error replaying events");
38241
- }
38242
- }
38243
- /**
38244
- * Writes an event to an SSE stream via controller with proper formatting
38245
- */
38246
- writeSSEEvent(controller, encoder, message, eventId) {
38247
- try {
38248
- let eventData = `event: message
38249
- `;
38250
- if (eventId) {
38251
- eventData += `id: ${eventId}
38252
- `;
38253
- }
38254
- eventData += `data: ${JSON.stringify(message)}
38255
-
38256
- `;
38257
- controller.enqueue(encoder.encode(eventData));
38258
- return true;
38259
- } catch {
38260
- return false;
38261
- }
38262
- }
38263
- /**
38264
- * Handles unsupported requests (PUT, PATCH, etc.)
38265
- */
38266
- handleUnsupportedRequest() {
38267
- return new Response(JSON.stringify({
38268
- jsonrpc: "2.0",
38269
- error: {
38270
- code: -32e3,
38271
- message: "Method not allowed."
38272
- },
38273
- id: null
38274
- }), {
38275
- status: 405,
38276
- headers: {
38277
- Allow: "GET, POST, DELETE",
38278
- "Content-Type": "application/json"
38279
- }
38280
- });
38281
- }
38282
- /**
38283
- * Handles POST requests containing JSON-RPC messages
38284
- */
38285
- async handlePostRequest(req, options) {
38286
- try {
38287
- const acceptHeader = req.headers.get("accept");
38288
- if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) {
38289
- return this.createJsonErrorResponse(406, -32e3, "Not Acceptable: Client must accept both application/json and text/event-stream");
38290
- }
38291
- const ct = req.headers.get("content-type");
38292
- if (!ct || !ct.includes("application/json")) {
38293
- return this.createJsonErrorResponse(415, -32e3, "Unsupported Media Type: Content-Type must be application/json");
38294
- }
38295
- const requestInfo = {
38296
- headers: Object.fromEntries(req.headers.entries())
38297
- };
38298
- let rawMessage;
38299
- if (options?.parsedBody !== void 0) {
38300
- rawMessage = options.parsedBody;
38301
- } else {
38302
- try {
38303
- rawMessage = await req.json();
38304
- } catch {
38305
- return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON");
38306
- }
38307
- }
38308
- let messages;
37734
+ processReadBuffer() {
37735
+ while (true) {
38309
37736
  try {
38310
- if (Array.isArray(rawMessage)) {
38311
- messages = rawMessage.map((msg) => JSONRPCMessageSchema.parse(msg));
38312
- } else {
38313
- messages = [JSONRPCMessageSchema.parse(rawMessage)];
38314
- }
38315
- } catch {
38316
- return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON-RPC message");
38317
- }
38318
- const isInitializationRequest = messages.some(isInitializeRequest);
38319
- if (isInitializationRequest) {
38320
- if (this._initialized && this.sessionId !== void 0) {
38321
- return this.createJsonErrorResponse(400, -32600, "Invalid Request: Server already initialized");
38322
- }
38323
- if (messages.length > 1) {
38324
- return this.createJsonErrorResponse(400, -32600, "Invalid Request: Only one initialization request is allowed");
38325
- }
38326
- this.sessionId = this.sessionIdGenerator?.();
38327
- this._initialized = true;
38328
- if (this.sessionId && this._onsessioninitialized) {
38329
- await Promise.resolve(this._onsessioninitialized(this.sessionId));
38330
- }
38331
- }
38332
- if (!isInitializationRequest) {
38333
- const sessionError = this.validateSession(req);
38334
- if (sessionError) {
38335
- return sessionError;
38336
- }
38337
- const protocolError = this.validateProtocolVersion(req);
38338
- if (protocolError) {
38339
- return protocolError;
38340
- }
38341
- }
38342
- const hasRequests = messages.some(isJSONRPCRequest);
38343
- if (!hasRequests) {
38344
- for (const message of messages) {
38345
- this.onmessage?.(message, { authInfo: options?.authInfo, requestInfo });
38346
- }
38347
- return new Response(null, { status: 202 });
38348
- }
38349
- const streamId = crypto.randomUUID();
38350
- const initRequest = messages.find((m) => isInitializeRequest(m));
38351
- const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
38352
- if (this._enableJsonResponse) {
38353
- return new Promise((resolve3) => {
38354
- this._streamMapping.set(streamId, {
38355
- resolveJson: resolve3,
38356
- cleanup: () => {
38357
- this._streamMapping.delete(streamId);
38358
- }
38359
- });
38360
- for (const message of messages) {
38361
- if (isJSONRPCRequest(message)) {
38362
- this._requestToStreamMapping.set(message.id, streamId);
38363
- }
38364
- }
38365
- for (const message of messages) {
38366
- this.onmessage?.(message, { authInfo: options?.authInfo, requestInfo });
38367
- }
38368
- });
38369
- }
38370
- const encoder = new TextEncoder();
38371
- let streamController;
38372
- const readable = new ReadableStream({
38373
- start: (controller) => {
38374
- streamController = controller;
38375
- },
38376
- cancel: () => {
38377
- this._streamMapping.delete(streamId);
38378
- }
38379
- });
38380
- const headers = {
38381
- "Content-Type": "text/event-stream",
38382
- "Cache-Control": "no-cache",
38383
- Connection: "keep-alive"
38384
- };
38385
- if (this.sessionId !== void 0) {
38386
- headers["mcp-session-id"] = this.sessionId;
38387
- }
38388
- for (const message of messages) {
38389
- if (isJSONRPCRequest(message)) {
38390
- this._streamMapping.set(streamId, {
38391
- controller: streamController,
38392
- encoder,
38393
- cleanup: () => {
38394
- this._streamMapping.delete(streamId);
38395
- try {
38396
- streamController.close();
38397
- } catch {
38398
- }
38399
- }
38400
- });
38401
- this._requestToStreamMapping.set(message.id, streamId);
38402
- }
38403
- }
38404
- await this.writePrimingEvent(streamController, encoder, streamId, clientProtocolVersion);
38405
- for (const message of messages) {
38406
- let closeSSEStream;
38407
- let closeStandaloneSSEStream;
38408
- if (isJSONRPCRequest(message) && this._eventStore && clientProtocolVersion >= "2025-11-25") {
38409
- closeSSEStream = () => {
38410
- this.closeSSEStream(message.id);
38411
- };
38412
- closeStandaloneSSEStream = () => {
38413
- this.closeStandaloneSSEStream();
38414
- };
37737
+ const message = this._readBuffer.readMessage();
37738
+ if (message === null) {
37739
+ break;
38415
37740
  }
38416
- this.onmessage?.(message, { authInfo: options?.authInfo, requestInfo, closeSSEStream, closeStandaloneSSEStream });
37741
+ this.onmessage?.(message);
37742
+ } catch (error48) {
37743
+ this.onerror?.(error48);
38417
37744
  }
38418
- return new Response(readable, { status: 200, headers });
38419
- } catch (error48) {
38420
- this.onerror?.(error48);
38421
- return this.createJsonErrorResponse(400, -32700, "Parse error", { data: String(error48) });
38422
- }
38423
- }
38424
- /**
38425
- * Handles DELETE requests to terminate sessions
38426
- */
38427
- async handleDeleteRequest(req) {
38428
- const sessionError = this.validateSession(req);
38429
- if (sessionError) {
38430
- return sessionError;
38431
- }
38432
- const protocolError = this.validateProtocolVersion(req);
38433
- if (protocolError) {
38434
- return protocolError;
38435
- }
38436
- await Promise.resolve(this._onsessionclosed?.(this.sessionId));
38437
- await this.close();
38438
- return new Response(null, { status: 200 });
38439
- }
38440
- /**
38441
- * Validates session ID for non-initialization requests.
38442
- * Returns Response error if invalid, undefined otherwise
38443
- */
38444
- validateSession(req) {
38445
- if (this.sessionIdGenerator === void 0) {
38446
- return void 0;
38447
- }
38448
- if (!this._initialized) {
38449
- return this.createJsonErrorResponse(400, -32e3, "Bad Request: Server not initialized");
38450
- }
38451
- const sessionId = req.headers.get("mcp-session-id");
38452
- if (!sessionId) {
38453
- return this.createJsonErrorResponse(400, -32e3, "Bad Request: Mcp-Session-Id header is required");
38454
37745
  }
38455
- if (sessionId !== this.sessionId) {
38456
- return this.createJsonErrorResponse(404, -32001, "Session not found");
38457
- }
38458
- return void 0;
38459
- }
38460
- /**
38461
- * Validates the MCP-Protocol-Version header on incoming requests.
38462
- *
38463
- * For initialization: Version negotiation handles unknown versions gracefully
38464
- * (server responds with its supported version).
38465
- *
38466
- * For subsequent requests with MCP-Protocol-Version header:
38467
- * - Accept if in supported list
38468
- * - 400 if unsupported
38469
- *
38470
- * For HTTP requests without the MCP-Protocol-Version header:
38471
- * - Accept and default to the version negotiated at initialization
38472
- */
38473
- validateProtocolVersion(req) {
38474
- const protocolVersion = req.headers.get("mcp-protocol-version");
38475
- if (protocolVersion !== null && !SUPPORTED_PROTOCOL_VERSIONS.includes(protocolVersion)) {
38476
- return this.createJsonErrorResponse(400, -32e3, `Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(", ")})`);
38477
- }
38478
- return void 0;
38479
37746
  }
38480
37747
  async close() {
38481
- this._streamMapping.forEach(({ cleanup }) => {
38482
- cleanup();
38483
- });
38484
- this._streamMapping.clear();
38485
- this._requestResponseMap.clear();
38486
- this.onclose?.();
38487
- }
38488
- /**
38489
- * Close an SSE stream for a specific request, triggering client reconnection.
38490
- * Use this to implement polling behavior during long-running operations -
38491
- * client will reconnect after the retry interval specified in the priming event.
38492
- */
38493
- closeSSEStream(requestId) {
38494
- const streamId = this._requestToStreamMapping.get(requestId);
38495
- if (!streamId)
38496
- return;
38497
- const stream = this._streamMapping.get(streamId);
38498
- if (stream) {
38499
- stream.cleanup();
38500
- }
38501
- }
38502
- /**
38503
- * Close the standalone GET SSE stream, triggering client reconnection.
38504
- * Use this to implement polling behavior for server-initiated notifications.
38505
- */
38506
- closeStandaloneSSEStream() {
38507
- const stream = this._streamMapping.get(this._standaloneSseStreamId);
38508
- if (stream) {
38509
- stream.cleanup();
37748
+ this._stdin.off("data", this._ondata);
37749
+ this._stdin.off("error", this._onerror);
37750
+ const remainingDataListeners = this._stdin.listenerCount("data");
37751
+ if (remainingDataListeners === 0) {
37752
+ this._stdin.pause();
38510
37753
  }
37754
+ this._readBuffer.clear();
37755
+ this.onclose?.();
38511
37756
  }
38512
- async send(message, options) {
38513
- let requestId = options?.relatedRequestId;
38514
- if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
38515
- requestId = message.id;
38516
- }
38517
- if (requestId === void 0) {
38518
- if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
38519
- throw new Error("Cannot send a response on a standalone SSE stream unless resuming a previous client request");
38520
- }
38521
- let eventId;
38522
- if (this._eventStore) {
38523
- eventId = await this._eventStore.storeEvent(this._standaloneSseStreamId, message);
38524
- }
38525
- const standaloneSse = this._streamMapping.get(this._standaloneSseStreamId);
38526
- if (standaloneSse === void 0) {
38527
- return;
38528
- }
38529
- if (standaloneSse.controller && standaloneSse.encoder) {
38530
- this.writeSSEEvent(standaloneSse.controller, standaloneSse.encoder, message, eventId);
38531
- }
38532
- return;
38533
- }
38534
- const streamId = this._requestToStreamMapping.get(requestId);
38535
- if (!streamId) {
38536
- throw new Error(`No connection established for request ID: ${String(requestId)}`);
38537
- }
38538
- const stream = this._streamMapping.get(streamId);
38539
- if (!this._enableJsonResponse && stream?.controller && stream?.encoder) {
38540
- let eventId;
38541
- if (this._eventStore) {
38542
- eventId = await this._eventStore.storeEvent(streamId, message);
38543
- }
38544
- this.writeSSEEvent(stream.controller, stream.encoder, message, eventId);
38545
- }
38546
- if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
38547
- this._requestResponseMap.set(requestId, message);
38548
- const relatedIds = Array.from(this._requestToStreamMapping.entries()).filter(([_, sid]) => sid === streamId).map(([id]) => id);
38549
- const allResponsesReady = relatedIds.every((id) => this._requestResponseMap.has(id));
38550
- if (allResponsesReady) {
38551
- if (!stream) {
38552
- throw new Error(`No connection established for request ID: ${String(requestId)}`);
38553
- }
38554
- if (this._enableJsonResponse && stream.resolveJson) {
38555
- const headers = {
38556
- "Content-Type": "application/json"
38557
- };
38558
- if (this.sessionId !== void 0) {
38559
- headers["mcp-session-id"] = this.sessionId;
38560
- }
38561
- const responses = relatedIds.map((id) => this._requestResponseMap.get(id));
38562
- if (responses.length === 1) {
38563
- stream.resolveJson(new Response(JSON.stringify(responses[0]), { status: 200, headers }));
38564
- } else {
38565
- stream.resolveJson(new Response(JSON.stringify(responses), { status: 200, headers }));
38566
- }
38567
- } else {
38568
- stream.cleanup();
38569
- }
38570
- for (const id of relatedIds) {
38571
- this._requestResponseMap.delete(id);
38572
- this._requestToStreamMapping.delete(id);
38573
- }
37757
+ send(message) {
37758
+ return new Promise((resolve3) => {
37759
+ const json2 = serializeMessage(message);
37760
+ if (this._stdout.write(json2)) {
37761
+ resolve3();
37762
+ } else {
37763
+ this._stdout.once("drain", resolve3);
38574
37764
  }
38575
- }
38576
- }
38577
- };
38578
-
38579
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/streamableHttp.js
38580
- var StreamableHTTPServerTransport = class {
38581
- constructor(options = {}) {
38582
- this._requestContext = /* @__PURE__ */ new WeakMap();
38583
- this._webStandardTransport = new WebStandardStreamableHTTPServerTransport(options);
38584
- this._requestListener = getRequestListener(async (webRequest) => {
38585
- const context = this._requestContext.get(webRequest);
38586
- return this._webStandardTransport.handleRequest(webRequest, {
38587
- authInfo: context?.authInfo,
38588
- parsedBody: context?.parsedBody
38589
- });
38590
- }, { overrideGlobalObjects: false });
38591
- }
38592
- /**
38593
- * Gets the session ID for this transport instance.
38594
- */
38595
- get sessionId() {
38596
- return this._webStandardTransport.sessionId;
38597
- }
38598
- /**
38599
- * Sets callback for when the transport is closed.
38600
- */
38601
- set onclose(handler) {
38602
- this._webStandardTransport.onclose = handler;
38603
- }
38604
- get onclose() {
38605
- return this._webStandardTransport.onclose;
38606
- }
38607
- /**
38608
- * Sets callback for transport errors.
38609
- */
38610
- set onerror(handler) {
38611
- this._webStandardTransport.onerror = handler;
38612
- }
38613
- get onerror() {
38614
- return this._webStandardTransport.onerror;
38615
- }
38616
- /**
38617
- * Sets callback for incoming messages.
38618
- */
38619
- set onmessage(handler) {
38620
- this._webStandardTransport.onmessage = handler;
38621
- }
38622
- get onmessage() {
38623
- return this._webStandardTransport.onmessage;
38624
- }
38625
- /**
38626
- * Starts the transport. This is required by the Transport interface but is a no-op
38627
- * for the Streamable HTTP transport as connections are managed per-request.
38628
- */
38629
- async start() {
38630
- return this._webStandardTransport.start();
38631
- }
38632
- /**
38633
- * Closes the transport and all active connections.
38634
- */
38635
- async close() {
38636
- return this._webStandardTransport.close();
38637
- }
38638
- /**
38639
- * Sends a JSON-RPC message through the transport.
38640
- */
38641
- async send(message, options) {
38642
- return this._webStandardTransport.send(message, options);
38643
- }
38644
- /**
38645
- * Handles an incoming HTTP request, whether GET or POST.
38646
- *
38647
- * This method converts Node.js HTTP objects to Web Standard Request/Response
38648
- * and delegates to the underlying WebStandardStreamableHTTPServerTransport.
38649
- *
38650
- * @param req - Node.js IncomingMessage, optionally with auth property from middleware
38651
- * @param res - Node.js ServerResponse
38652
- * @param parsedBody - Optional pre-parsed body from body-parser middleware
38653
- */
38654
- async handleRequest(req, res, parsedBody) {
38655
- const authInfo = req.auth;
38656
- const handler = getRequestListener(async (webRequest) => {
38657
- return this._webStandardTransport.handleRequest(webRequest, {
38658
- authInfo,
38659
- parsedBody
38660
- });
38661
- }, { overrideGlobalObjects: false });
38662
- await handler(req, res);
38663
- }
38664
- /**
38665
- * Close an SSE stream for a specific request, triggering client reconnection.
38666
- * Use this to implement polling behavior during long-running operations -
38667
- * client will reconnect after the retry interval specified in the priming event.
38668
- */
38669
- closeSSEStream(requestId) {
38670
- this._webStandardTransport.closeSSEStream(requestId);
38671
- }
38672
- /**
38673
- * Close the standalone GET SSE stream, triggering client reconnection.
38674
- * Use this to implement polling behavior for server-initiated notifications.
38675
- */
38676
- closeStandaloneSSEStream() {
38677
- this._webStandardTransport.closeStandaloneSSEStream();
37765
+ });
38678
37766
  }
38679
37767
  };
38680
37768
 
38681
- // src/mcp/server.ts
38682
- var http = __toESM(require("http"));
38683
-
38684
37769
  // src/core/context.ts
38685
37770
  function findPathMatches(filePaths, topic, tilPath) {
38686
37771
  const lowerTopic = topic.toLowerCase();
@@ -38698,9 +37783,9 @@ function extractCategory(filePath, tilPath) {
38698
37783
  const parts = relative.split("/");
38699
37784
  return parts.length >= 2 ? parts[0] : "(uncategorized)";
38700
37785
  }
38701
- function buildFileContext(path6, tilPath, matchType, headings, outgoingLinks, backlinks, tags) {
38702
- const category = extractCategory(path6, tilPath);
38703
- return { path: path6, category, headings, outgoingLinks, backlinks, tags, matchType };
37786
+ function buildFileContext(path7, tilPath, matchType, headings, outgoingLinks, backlinks, tags) {
37787
+ const category = extractCategory(path7, tilPath);
37788
+ return { path: path7, category, headings, outgoingLinks, backlinks, tags, matchType };
38704
37789
  }
38705
37790
  function findUnresolvedMentions(unresolvedLinks, topic, tilPath) {
38706
37791
  const lowerTopic = topic.toLowerCase();
@@ -38875,10 +37960,10 @@ function parseBacklogSections(content) {
38875
37960
  if (itemMatch) {
38876
37961
  const done = itemMatch[1] !== " ";
38877
37962
  const rawPath = itemMatch[3].trim();
38878
- const path6 = rawPath.endsWith(".md") ? rawPath : rawPath + ".md";
38879
- const displayName = itemMatch[2]?.trim() || path6.replace(/\.md$/, "");
38880
- const slug = path6.replace(/\.md$/, "").split("/").pop() ?? "";
38881
- const item = { displayName, path: path6, done };
37963
+ const path7 = rawPath.endsWith(".md") ? rawPath : rawPath + ".md";
37964
+ const displayName = itemMatch[2]?.trim() || path7.replace(/\.md$/, "");
37965
+ const slug = path7.replace(/\.md$/, "").split("/").pop() ?? "";
37966
+ const item = { displayName, path: path7, done };
38882
37967
  if (sources[slug] && sources[slug].length > 0) {
38883
37968
  item.sourceUrls = sources[slug];
38884
37969
  }
@@ -39498,7 +38583,7 @@ function registerTools(server, storage, metadata, tilPath) {
39498
38583
  const texts = await Promise.all(batch.map((f) => storage.readFile(f.path)));
39499
38584
  for (let j = 0; j < batch.length; j++) {
39500
38585
  const text = texts[j];
39501
- if (text !== null && text.toLowerCase().includes(lowerTopic)) {
38586
+ if (text != null && text.toLowerCase().includes(lowerTopic)) {
39502
38587
  contentMatches.push(batch[j].path);
39503
38588
  }
39504
38589
  if (pathMatches.length + contentMatches.length >= 20)
@@ -39688,31 +38773,31 @@ function registerTools(server, storage, metadata, tilPath) {
39688
38773
  action: external_exports3.enum(["review", "remove"]).optional().describe("review (default): record review, remove: remove from review schedule")
39689
38774
  })
39690
38775
  },
39691
- async ({ path: path6, grade, action }) => {
38776
+ async ({ path: path7, grade, action }) => {
39692
38777
  const effectiveAction = action ?? "review";
39693
- const content = await storage.readFile(path6);
38778
+ const content = await storage.readFile(path7);
39694
38779
  if (content === null) {
39695
- return { content: [{ type: "text", text: JSON.stringify({ error: `File not found: ${path6}` }) }], isError: true };
38780
+ return { content: [{ type: "text", text: JSON.stringify({ error: `File not found: ${path7}` }) }], isError: true };
39696
38781
  }
39697
38782
  if (effectiveAction === "remove") {
39698
38783
  const updated2 = removeFrontmatterSrs(content);
39699
- await storage.writeFile(path6, updated2);
39700
- return { content: [{ type: "text", text: JSON.stringify({ path: path6, removed: true }) }] };
38784
+ await storage.writeFile(path7, updated2);
38785
+ return { content: [{ type: "text", text: JSON.stringify({ path: path7, removed: true }) }] };
39701
38786
  }
39702
38787
  if (grade === void 0) {
39703
38788
  return { content: [{ type: "text", text: "Error: grade (0-5) is required when action=review" }], isError: true };
39704
38789
  }
39705
- const fileMeta = await metadata.getFileMetadata(path6);
38790
+ const fileMeta = await metadata.getFileMetadata(path7);
39706
38791
  const fm = fileMeta?.frontmatter ?? {};
39707
38792
  const currentSrs = parseSrsMetadata(fm) ?? createDefaultSrsMetadata();
39708
38793
  const newSrs = computeNextReview(currentSrs, grade);
39709
38794
  const updated = updateFrontmatterSrs(content, newSrs);
39710
- await storage.writeFile(path6, updated);
38795
+ await storage.writeFile(path7, updated);
39711
38796
  return {
39712
38797
  content: [{
39713
38798
  type: "text",
39714
38799
  text: JSON.stringify({
39715
- path: path6,
38800
+ path: path7,
39716
38801
  grade,
39717
38802
  next_review: newSrs.next_review,
39718
38803
  interval: newSrs.interval,
@@ -39741,7 +38826,7 @@ function registerTools(server, storage, metadata, tilPath) {
39741
38826
  })
39742
38827
  },
39743
38828
  async ({ category, slug, title, content, tags, date: date5, fmCategory, aliases, auto_check_backlog }) => {
39744
- const path6 = `${tilPath}/${category}/${slug}.md`;
38829
+ const path7 = `${tilPath}/${category}/${slug}.md`;
39745
38830
  const noteDate = date5 || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
39746
38831
  const fmLines = ["---", `title: "${title.replace(/"/g, '\\"')}"`, `date: ${noteDate}`];
39747
38832
  const effectiveCategory = fmCategory ?? category;
@@ -39758,9 +38843,9 @@ function registerTools(server, storage, metadata, tilPath) {
39758
38843
  fmLines.push("---", "");
39759
38844
  const fullContent = fmLines.join("\n") + content;
39760
38845
  await storage.mkdir(`${tilPath}/${category}`);
39761
- const existed = await storage.exists(path6);
39762
- await storage.writeFile(path6, fullContent);
39763
- const data = { path: path6, created: !existed, category, slug, title };
38846
+ const existed = await storage.exists(path7);
38847
+ await storage.writeFile(path7, fullContent);
38848
+ const data = { path: path7, created: !existed, category, slug, title };
39764
38849
  if (auto_check_backlog) {
39765
38850
  const backlogPath = `${tilPath}/${category}/backlog.md`;
39766
38851
  const backlogContent = await storage.readFile(backlogPath);
@@ -39806,405 +38891,14 @@ function registerTools(server, storage, metadata, tilPath) {
39806
38891
  );
39807
38892
  }
39808
38893
 
39809
- // src/mcp/server.ts
39810
- var TILMcpServer = class {
39811
- constructor(storage, metadata, port, tilPath, version2, options) {
39812
- this.httpServer = null;
39813
- this.storage = storage;
39814
- this.metadata = metadata;
39815
- this.port = port;
39816
- this.tilPath = tilPath;
39817
- this.version = version2;
39818
- this.options = options;
39819
- }
39820
- async start() {
39821
- return new Promise((resolve3, reject) => {
39822
- this.httpServer = http.createServer(async (req, res) => {
39823
- await this.handleRequest(req, res);
39824
- });
39825
- this.httpServer.on("listening", () => {
39826
- console.log(`Oh My TIL: MCP server started (http://localhost:${this.port})`);
39827
- resolve3();
39828
- });
39829
- this.httpServer.on("error", (err) => {
39830
- if (err.code === "EADDRINUSE") {
39831
- const msg = `Oh My TIL: Port ${this.port} is already in use. Please change the MCP port in settings.`;
39832
- this.options?.onError?.(msg);
39833
- console.error(msg);
39834
- } else {
39835
- const msg = `Oh My TIL: MCP server failed to start \u2014 ${err.message}`;
39836
- this.options?.onError?.(msg);
39837
- console.error("Oh My TIL: MCP server error", err);
39838
- }
39839
- reject(err);
39840
- });
39841
- this.httpServer.listen(this.port);
39842
- });
39843
- }
39844
- async handleRequest(req, res) {
39845
- if (req.method === "OPTIONS") {
39846
- res.writeHead(204);
39847
- res.end();
39848
- return;
39849
- }
39850
- if (req.url === "/mcp" || req.url?.startsWith("/mcp?")) {
39851
- const mcpServer = new McpServer({
39852
- name: "oh-my-til",
39853
- version: this.version
39854
- });
39855
- registerTools(mcpServer, this.storage, this.metadata, this.tilPath);
39856
- const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
39857
- const cleanup = async () => {
39858
- await transport.close();
39859
- await mcpServer.close();
39860
- };
39861
- try {
39862
- await mcpServer.connect(transport);
39863
- await transport.handleRequest(req, res);
39864
- } catch (err) {
39865
- console.error("Oh My TIL: MCP request handling failed", err);
39866
- if (!res.headersSent) {
39867
- res.writeHead(500, { "Content-Type": "application/json" });
39868
- res.end(JSON.stringify({ error: "Internal error" }));
39869
- }
39870
- } finally {
39871
- if (res.writableEnded) {
39872
- await cleanup();
39873
- } else {
39874
- res.on("close", () => void cleanup());
39875
- }
39876
- }
39877
- return;
39878
- }
39879
- res.writeHead(404);
39880
- res.end("Not found");
39881
- }
39882
- async stop() {
39883
- if (this.httpServer) {
39884
- this.httpServer.closeAllConnections();
39885
- return new Promise((resolve3) => {
39886
- this.httpServer.close(() => {
39887
- console.log("Oh My TIL: MCP server stopped");
39888
- this.httpServer = null;
39889
- resolve3();
39890
- });
39891
- });
39892
- }
39893
- }
39894
- };
39895
-
39896
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
39897
- var import_node_process = __toESM(require("process"), 1);
39898
-
39899
- // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
39900
- var ReadBuffer = class {
39901
- append(chunk) {
39902
- this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
39903
- }
39904
- readMessage() {
39905
- if (!this._buffer) {
39906
- return null;
39907
- }
39908
- const index = this._buffer.indexOf("\n");
39909
- if (index === -1) {
39910
- return null;
39911
- }
39912
- const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
39913
- this._buffer = this._buffer.subarray(index + 1);
39914
- return deserializeMessage(line);
39915
- }
39916
- clear() {
39917
- this._buffer = void 0;
39918
- }
39919
- };
39920
- function deserializeMessage(line) {
39921
- return JSONRPCMessageSchema.parse(JSON.parse(line));
39922
- }
39923
- function serializeMessage(message) {
39924
- return JSON.stringify(message) + "\n";
39925
- }
39926
-
39927
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
39928
- var StdioServerTransport = class {
39929
- constructor(_stdin = import_node_process.default.stdin, _stdout = import_node_process.default.stdout) {
39930
- this._stdin = _stdin;
39931
- this._stdout = _stdout;
39932
- this._readBuffer = new ReadBuffer();
39933
- this._started = false;
39934
- this._ondata = (chunk) => {
39935
- this._readBuffer.append(chunk);
39936
- this.processReadBuffer();
39937
- };
39938
- this._onerror = (error48) => {
39939
- this.onerror?.(error48);
39940
- };
39941
- }
39942
- /**
39943
- * Starts listening for messages on stdin.
39944
- */
39945
- async start() {
39946
- if (this._started) {
39947
- throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
39948
- }
39949
- this._started = true;
39950
- this._stdin.on("data", this._ondata);
39951
- this._stdin.on("error", this._onerror);
39952
- }
39953
- processReadBuffer() {
39954
- while (true) {
39955
- try {
39956
- const message = this._readBuffer.readMessage();
39957
- if (message === null) {
39958
- break;
39959
- }
39960
- this.onmessage?.(message);
39961
- } catch (error48) {
39962
- this.onerror?.(error48);
39963
- }
39964
- }
39965
- }
39966
- async close() {
39967
- this._stdin.off("data", this._ondata);
39968
- this._stdin.off("error", this._onerror);
39969
- const remainingDataListeners = this._stdin.listenerCount("data");
39970
- if (remainingDataListeners === 0) {
39971
- this._stdin.pause();
39972
- }
39973
- this._readBuffer.clear();
39974
- this.onclose?.();
39975
- }
39976
- send(message) {
39977
- return new Promise((resolve3) => {
39978
- const json2 = serializeMessage(message);
39979
- if (this._stdout.write(json2)) {
39980
- resolve3();
39981
- } else {
39982
- this._stdout.once("drain", resolve3);
39983
- }
39984
- });
39985
- }
39986
- };
39987
-
39988
- // skills/til/SKILL.md
39989
- var SKILL_default = "---\nname: til\ndescription: \"Today I Learned \u2014 research a topic, learn interactively, then save as TIL markdown. Use when the user wants to learn about a topic, says 'teach me', 'what is X', 'deep dive into X', or asks to study something and save it as a TIL note.\"\nargument-hint: \"<topic> [category]\"\nplugin-version: \"__PLUGIN_VERSION__\"\n---\n\n# TIL Skill\n\nTopic research \u2192 Interactive learning \u2192 Save TIL.\n\n## MCP Tools\n\n- `til_list`: Check existing TILs (detect same/similar topics)\n- `til_get_context`: Find related TILs and backlog items, link candidates\n\n## Phase 1: Topic Research\n\n1. Use `Read` to check if `til/{category}/{slug}.md` exists \u2192 if so, offer to expand the existing TIL or start a new topic\n2. Use `til_get_context` to check existing TILs. Fall back to `til_list` if MCP is unavailable\n - When learning a backlog item, call `til_backlog_status`(category) \u2192 reference `sections[].items[].sourceUrls`\n - 1 URL: fetch directly with `WebFetch`\n - 2+ URLs: pass all URLs to a single `til-fetcher` subagent\n3. If no existing TIL is found, research the topic via web search\n4. Collect key concepts, examples, and references \u2192 summarize\n\n## Phase 2: Interactive Learning\n\n1. Explain based on research results\n2. Follow-up mode: focus on new perspectives; do not repeat existing content\n3. Answer user questions\n4. Move to Phase 3 only when the user explicitly requests to save\n\n## Phase 3: Save\n\nFollow `/save` skill rules to save. In follow-up mode, merge into the existing file (add `updated` date).\n\n## Arguments\n\n- First: learning topic (required)\n- Second: category (optional, automatically detected if omitted)\n\n## Rules\n\n- Links: `[display name](til/{category}/{slug}.md)` \u2014 no `[[wiki links]]` (links must work in static sites and non-Obsidian editors)\n- Use placeholder values for sensitive information (example.com, your-api-key) to avoid leaking real credentials\n";
39990
-
39991
- // skills/backlog/SKILL.md
39992
- var SKILL_default2 = "---\nname: backlog\ndescription: \"View learning backlog and show progress. Use when the user asks 'what's left to learn', 'show my progress', 'learning todo', or wants to check remaining topics in their study plan.\"\nargument-hint: \"[category]\"\ndisable-model-invocation: true\nplugin-version: \"__PLUGIN_VERSION__\"\n---\n\n# Backlog Skill\n\nView learning backlog + summarize progress (read-only).\n\n## MCP Tools\n\n- `til_backlog_status`: Overall/per-category progress (includes sections when category is specified)\n\n## Workflow\n\n### No arguments (`/backlog`)\n\n1. Call `til_backlog_status` (fall back to `./til/*/backlog.md` Glob if MCP unavailable)\n2. If no backlog found, show `/research` guidance and exit\n3. Summarize as table: category (link), progress, completed count, last activity date, progress bar\n\n### With arguments (`/backlog category`)\n\n1. Pass category to `til_backlog_status` \u2192 use sections\n2. Output per section:\n - `## {heading} ({completed}/{total})`\n - `- (x) [{displayName}]({path})` / `- ( ) [{displayName}]({path})`\n - Do not use `- [ ]`/`- [x]` markdown checkboxes (not rendered in terminal)\n\n## Output Rules\n\n- All category/item names as `[display name](path)` markdown links\n- Do not expose raw paths\n- Progress bar: 10 slots (`\u2588` completed, `\u2591` incomplete)\n- Do not modify backlog files (read-only)\n";
39993
-
39994
- // skills/research/SKILL.md
39995
- var SKILL_default3 = '---\nname: research\ndescription: "Research a topic to identify key concepts and terms, then organize as a learning backlog. Use when the user wants a learning roadmap, study plan, curriculum, or asks \'what should I learn about X\' \u2014 focuses on planning what to learn, not learning itself."\nargument-hint: "<topic> [category]"\nplugin-version: "__PLUGIN_VERSION__"\n---\n\n# Research Skill\n\nTopic research \u2192 Identify concepts and dependencies \u2192 Save backlog file.\n\n## MCP Tools\n\n- `til_list`: Check existing TILs (search by topic using the search parameter)\n\n## Phase 1: Topic Research\n\n1. Use `til_list(search=topic)` to check already-learned topics \u2192 avoid duplicate backlog entries\n2. Research the topic via web search, identify required concepts, terms, and prerequisites\n3. Break down into subtopics and research each directly\n4. Analyze dependencies between subtopics\n\n## Phase 2: Organize Backlog\n\n1. Sort by learning order: Prerequisites \u2192 Core Concepts \u2192 Advanced\n2. Add a one-line description per item\n3. Gather user feedback: allow adding, removing, or reordering items\n\n## Phase 3: Save\n\n1. Save to `./til/{category}/backlog.md` (auto-create folder)\n2. If `backlog.md` already exists, merge:\n - Preserve `[x]` completed items\n - Keep check state for matching items\n - Preserve existing sources, only add new items\n3. Add backlog link to TIL MOC\n4. Commit all changes: `\u{1F4CB} research: {topic} learning backlog - {category}` (do not push)\n\n## Backlog Template\n\nRead `references/templates.md` for the exact backlog template and field descriptions.\n\n## Arguments\n\n- First: research topic (required)\n- Second: category (optional, automatically detected if omitted)\n\n## Rules\n\n- One-line description per item, split into multiple files if over 20 items (long backlogs hurt readability and cause scroll fatigue)\n- Links: `[display name](til/{category}/{slug}.md)`\n';
39996
-
39997
- // skills/save/SKILL.md
39998
- var SKILL_default4 = '---\nname: save\ndescription: "Save learning content as a TIL file and batch-update Daily notes, MOC, and backlog. Use when the user says \'save this\', \'write up what I learned\', \'document this as a TIL\', or wants to persist a learning conversation as a note."\nargument-hint: "[topic] [category]"\nplugin-version: "__PLUGIN_VERSION__"\n---\n\n# Save Skill\n\nLearning conversation \u2192 Save TIL file \u2192 Update Daily/MOC/backlog \u2192 Review document \u2192 Commit.\n\n## MCP Tools\n\n- `til_get_context`: Find related TILs and backlog items\n- `til_list`: Check for duplicate existing TILs\n- `til_save_note`: Save TIL note (server guarantees frontmatter/path rules, auto_check_backlog auto-checks backlog)\n\n## Step 1: Check Context\n\n1. Identify topic and category. Ask the user if unclear.\n2. Use `Read` to check if `til/{category}/{slug}.md` exists.\n\n## Step 2: Identify Link Candidates\n\n1. Use `til_get_context` or MOC/backlog to find existing TILs and backlog items\n2. Existing TIL/backlog items \u2192 use markdown links in the body\n3. Concepts that don\'t exist \u2192 confirm with user, then add only to related notes\n\n## Step 3: Save TIL File\n\nPath: `./til/{category}/{topic-slug}.md` (slug: lowercase English with hyphens)\n\n**Save new file**: Save using the `til_save_note` MCP tool. The server guarantees frontmatter (title, date, category, tags, aliases) and path rules.\n\n```\ntil_save_note(category, slug, title, content, tags, date, fmCategory, aliases, auto_check_backlog: true)\n```\n\n- `date`: Get local time via `date +%Y-%m-%dT%H:%M:%S` command and pass it\n- `tags`: Must include "til"\n- `aliases`: ["Korean title", "English title"]\n- `content`: Body markdown excluding frontmatter\n\n**When a file with the same slug exists** (detected by `Read` in Step 1):\n- Auto-merge only when continuing a `/til` follow-up session (preserve existing content + reinforce, add `updated`)\n- Otherwise: ask user to confirm merge or overwrite\n- For merge: use Read\u2192Edit directly on existing content instead of `til_save_note`\n\n### TIL Body Template\n\nRead `references/templates.md` for the exact TIL body, Daily note, and MOC templates.\n\n- Links: `[display name](til/{category}/{slug}.md)` \u2014 no `[[wiki links]]`\n\n## Step 4: Update Related Files\n\nUpdate the following 3 files **directly** in sequence (no subagents \u2014 parallel edits can race and corrupt shared files like MOC):\n\n1. Daily note (`./Daily/YYYY-MM-DD.md`): Add TIL link by category (create if not exists)\n2. TIL MOC (`./til/TIL MOC.md`): Add item to category section (create if not exists)\n3. Backlog: Already handled by `til_save_note`\'s `auto_check_backlog: true` (no separate call needed)\n\nDaily/MOC: Read \u2192 find position \u2192 Edit. Create file if not exists.\n\n## Step 5: Document Review\n\nDisplay full saved TIL content \u2192 use `AskUserQuestion` to confirm ("Looks good" / "Needs revision").\n\n## Step 6: Register for Review\n\nAsk via `AskUserQuestion`: "Would you like to add this TIL to spaced repetition review?"\nIf user agrees, call `til_review_update` (action: "review", grade: 4) to create SRS metadata.\n\n## Step 7: git commit\n\n`\u{1F4DD} til: {English title}({Korean title}) - {category}` (no push)\n\n## Rules\n\n- frontmatter required: date, category, tags, aliases (fill in any missing fields before saving)\n- tags must include "til" (used to filter TILs on the static site)\n- No `[[wiki links]]` \u2014 use `[display name](path)` format only (links must work in static sites and non-Obsidian editors)\n- Always update Daily/MOC/backlog after saving the TIL\n- Use callouts: `> [!tldr]`, `> [!example]`, `> [!warning]`, `> [!tip]`\n- Visualize complex concepts with Mermaid diagrams (max 1 per TIL)\n- Use placeholder values for sensitive information (avoid leaking real credentials)\n';
39999
-
40000
- // skills/dashboard/SKILL.md
40001
- var SKILL_default5 = "---\nname: dashboard\ndescription: \"Learning dashboard \u2014 stats, activity heatmap, categories, backlog progress. Use when the user asks 'my stats', 'how much have I learned', 'show my streak', 'learning summary', or wants an overview of their TIL activity.\"\ndisable-model-invocation: true\nplugin-version: \"__PLUGIN_VERSION__\"\n---\n\n# Dashboard Skill\n\nRetrieve learning stats via the `til_dashboard` MCP tool and display in terminal.\n\n## MCP Tools\n\n- `til_dashboard`: Returns summary/heatmap/categories/backlog/trends as JSON\n\n## Output Format\n\n### 1. Summary Cards\nTotal TILs, categories, this week, streak \u2014 as table.\n\n### 2. Activity Trend\nSum heatmap cells by week \u2192 sparkline (`\u2581\u2582\u2583\u2585\u2587`).\n\n### 3. Category Status\nCategory (link), count, last modified date \u2014 sorted by file count descending.\n\n### 4. Backlog Progress\nSorted by progress descending, 10-slot progress bar (`\u2588`/`\u2591`).\n\n## Fallback (MCP Unavailable)\n\nIf `til_dashboard` is unavailable, combine `til_list` + `til_backlog_status` + `til_recent_context`.\n\n## Rules\n\n- Output as markdown links (no raw paths)\n- If no data: show \"No TILs yet. Run /til to get started!\"\n";
40002
-
40003
- // skills/omt-setup/SKILL.md
40004
- var SKILL_default6 = '---\nname: omt-setup\ndescription: "oh-my-til unified setup \u2014 deployment configuration"\nplugin-version: "__PLUGIN_VERSION__"\n---\n\n# OMT Setup Skill\n\nManage oh-my-til configuration in one place. Operates via subcommands.\n\n## Subcommands\n\n### `/omt-setup` (no arguments)\n\nRead `oh-my-til.json`, display current configuration + subcommand guide:\n- `deploy` \u2014 GitHub Pages deployment configuration\n\n### `/omt-setup deploy`\n\nConfigure GitHub Pages deployment:\n1. Check for `.git/` (if not found, notify and exit)\n2. Check `.github/workflows/deploy-til.yml` (if exists, ask whether modification is needed)\n3. Configure deploy section in `oh-my-til.json` (title, subtitle, GitHub URL)\n4. Generate workflow YAML\n5. Show completion guide (Settings \u2192 Pages \u2192 select GitHub Actions, commit & push commands)\n\n## Rules\n\n- Preserve existing settings in `oh-my-til.json`, only add/modify the relevant section\n- Do not commit (only show the user the commands)\n';
40005
-
40006
- // skills/til-review/SKILL.md
40007
- var SKILL_default7 = '---\nname: til-review\ndescription: "SRS-based TIL review session (spaced repetition). Use when the user says \'quiz me\', \'review what I learned\', \'flashcard session\', \'test my knowledge\', or wants to do spaced repetition review of their TIL notes."\nargument-hint: "[category]"\nplugin-version: "__PLUGIN_VERSION__"\n---\n\n# Review Skill\n\nSRS (spaced repetition) based TIL review session. Manages review schedule with the SM-2 algorithm.\n\n## MCP Tools\n\n- `til_review_list`: List of cards due for review today + stats (load note content with `include_content: true`)\n- `til_review_update`: Record review result (grade 0-5) or remove from review\n\n## Step 1: Load Review Cards\n\nCall `til_review_list` (`include_content: true`, pass category argument if provided).\n\n- 0 cards \u2192 Show "No reviews today" + suggest registering untracked TILs (go to Step 5)\n- Cards found \u2192 Display list + proceed to Step 2\n\n## Step 2: Select Evaluation Mode\n\nSelect via `AskUserQuestion`:\n- "Simple mode (Again / Good)"\n- "Detailed mode (Again / Hard / Good / Easy)"\n\n## Step 3: Per-Card Review Loop\n\nFor each card:\n\n1. Display title, category, review info (repetition count, EF, days overdue)\n2. Use `content` already loaded in Step 1 (no additional MCP calls needed)\n3. Present key content as questions (generate 1-2 questions based on content)\n4. Wait for user answer\n5. Provide feedback (correct answer / supplementary explanation)\n6. Input evaluation via `AskUserQuestion`:\n - Simple mode: "Good (Remembered)" / "Again (Forgot)" / "Skip" / "Stop Review"\n - Detailed mode: "Again (Failed)" / "Hard (Struggled)" / "Good (Normal)" / "Easy (Perfect)"\n - Grade mapping: Again=1, Hard=3, Good=4, Easy=5\n - "Skip": do not evaluate this card, move to next\n - "Stop Review": move to Step 4\n - Skip/Stop in detailed mode: select "Other" then type "Skip" or "Stop Review"\n7. If not skipped, call `til_review_update` (action: "review", grade)\n8. Display result summary (next review date, interval)\n\n## Step 4: Completion Stats\n\nAfter all cards are done:\n- Number of cards reviewed, average grade\n- If remaining > 0, show "N more remaining, continue tomorrow"\n- Re-call `til_review_list` to display latest stats\n\n## Step 5: Register TILs (Optional)\n\nWhen no cards exist or user requests:\n- Display full TIL list via `til_list`\n- User selects files to add to review\n- Call `til_review_update` (action: "review", grade: 4) for each selected file\n\n## Rules\n\n- Max 20 cards per session (prevent overload)\n- Prioritize overdue cards (most urgent first)\n- Remove from review: if user says "remove this card", call `til_review_update` (action: "remove")\n';
40008
-
40009
- // vault-assets/claude-md-section.md
40010
- var claude_md_section_default = "## Learning Workflow\n\n1. `/research <topic>` \u2014 Research \u2192 Generate backlog\n2. `/backlog [category]` \u2014 Check backlog progress\n3. `/til <topic>` \u2014 Research \u2192 Interactive learning \u2192 Save\n4. `/save` \u2014 Save TIL (auto-update Daily/MOC/backlog)\n5. `/til-review [category]` \u2014 SRS-based spaced repetition review\n\n## MCP Tools\n\n**Learning Context:**\n- `til_get_context` \u2014 Find existing TILs related to a topic (searches file paths, content, backlinks, and unresolved links)\n- `til_recent_context` \u2014 Recent learning activity (newest first)\n\n**TIL Management:**\n- `til_list` \u2014 TIL list + category grouping (search filter)\n- `til_save_note` \u2014 Save TIL (ensures valid frontmatter; set auto_check_backlog to auto-mark backlog items)\n\n**Backlog:**\n- `til_backlog_status` \u2014 Backlog progress\n- `til_backlog_check` \u2014 Mark backlog item as completed (standalone use)\n\n**Review (SRS):**\n- `til_review_list` \u2014 Review card list + stats (include_content)\n- `til_review_update` \u2014 Record review result\n\n**Stats:**\n- `til_dashboard` \u2014 Learning dashboard stats\n";
40011
-
40012
- // agents/til-fetcher.md
40013
- var til_fetcher_default = '---\nname: til-fetcher\ndescription: Dedicated agent that fetches source URL content and summarizes it as learning material\ntools: Read, WebFetch\nmodel: haiku\nplugin-version: "__PLUGIN_VERSION__"\n---\n\n# til-fetcher\n\nDedicated agent that fetches content from source URLs and summarizes key information needed for learning.\n\n## Role\n\n- Used as a sourceUrls fetching subagent in Phase 1 of the `/til` skill\n- Reads one or more URLs sequentially via WebFetch and summarizes key content needed for learning\n\n## Output Format\n\n- Provide a summary of the key content\n- Include code examples if any are present\n';
40014
-
40015
- // hooks/notify-complete.sh
40016
- var notify_complete_default = '#!/bin/bash\n# Oh My TIL \u2014 Task completion notification hook\n\nTITLE="Oh My TIL"\nMESSAGE="Task completed"\n\nif [[ "$OSTYPE" == "darwin"* ]]; then\n if command -v terminal-notifier &>/dev/null; then\n terminal-notifier -title "$TITLE" -message "$MESSAGE" -sound default 2>/dev/null\n else\n osascript -e "display notification \\"$MESSAGE\\" with title \\"$TITLE\\" sound name \\"default\\"" 2>/dev/null\n fi\nelif command -v notify-send &>/dev/null; then\n notify-send "$TITLE" "$MESSAGE" 2>/dev/null\nfi\n';
40017
-
40018
- // src/core/skills.ts
40019
- var VERSION_PLACEHOLDER = "__PLUGIN_VERSION__";
40020
- var MCP_MARKER_START = "<!-- oh-my-til:mcp-tools:start -->";
40021
- var MCP_MARKER_END = "<!-- oh-my-til:mcp-tools:end -->";
40022
- var SKILLS_BASE = ".claude/skills";
40023
- var RULES_BASE = ".claude/rules";
40024
- var AGENTS_BASE = ".claude/agents";
40025
- var HOOKS_BASE = ".claude/hooks";
40026
- var OLD_SKILLS_BASE = ".claude/skills/claude-til";
40027
- function resolveVersionPlaceholder(content, version2) {
40028
- return content.replace(VERSION_PLACEHOLDER, version2);
40029
- }
40030
- function extractPluginVersion(content) {
40031
- const match = content.match(/^---\n([\s\S]*?)\n---/);
40032
- if (!match)
40033
- return null;
40034
- const versionMatch = match[1].match(/plugin-version:\s*"?([^"\n]+)"?/);
40035
- return versionMatch ? versionMatch[1].trim() : null;
40036
- }
40037
- function isNewerVersion(a, b) {
40038
- const pa = a.split(".").map(Number);
40039
- const pb = b.split(".").map(Number);
40040
- for (let i = 0; i < 3; i++) {
40041
- if ((pa[i] || 0) > (pb[i] || 0))
40042
- return true;
40043
- if ((pa[i] || 0) < (pb[i] || 0))
40044
- return false;
40045
- }
40046
- return false;
40047
- }
40048
- function escapeRegExp(str) {
40049
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
40050
- }
40051
-
40052
- // src/plugin-install.ts
40053
- var SKILLS = {
40054
- "til/SKILL.md": SKILL_default,
40055
- "backlog/SKILL.md": SKILL_default2,
40056
- "research/SKILL.md": SKILL_default3,
40057
- "save/SKILL.md": SKILL_default4,
40058
- "dashboard/SKILL.md": SKILL_default5,
40059
- "omt-setup/SKILL.md": SKILL_default6,
40060
- "til-review/SKILL.md": SKILL_default7
40061
- };
40062
- var RULES = {};
40063
- var AGENTS = {
40064
- "til-fetcher.md": til_fetcher_default
40065
- };
40066
- var HOOKS = {
40067
- "notify-complete.sh": notify_complete_default
40068
- };
40069
- var HOOKS_CONFIG = {
40070
- Notification: [{
40071
- matcher: "idle_prompt",
40072
- hooks: [{ type: "command", command: "bash .claude/hooks/notify-complete.sh", async: true }]
40073
- }]
40074
- };
40075
- async function installFiles(storage, basePath, files, pluginVersion, label) {
40076
- const dirs = /* @__PURE__ */ new Set();
40077
- for (const relativePath of Object.keys(files)) {
40078
- const fullPath = `${basePath}/${relativePath}`;
40079
- dirs.add(fullPath.substring(0, fullPath.lastIndexOf("/")));
40080
- }
40081
- for (const dir of dirs) {
40082
- if (!await storage.exists(dir)) {
40083
- await storage.mkdir(dir);
40084
- }
40085
- }
40086
- await Promise.all(
40087
- Object.entries(files).map(async ([relativePath, content]) => {
40088
- const fullPath = `${basePath}/${relativePath}`;
40089
- if (await storage.exists(fullPath)) {
40090
- const existing = await storage.readFile(fullPath);
40091
- const installedVersion = extractPluginVersion(existing ?? "");
40092
- if (!installedVersion)
40093
- return;
40094
- if (!isNewerVersion(pluginVersion, installedVersion))
40095
- return;
40096
- }
40097
- await storage.writeFile(fullPath, resolveVersionPlaceholder(content, pluginVersion));
40098
- console.log(`Oh My TIL: ${label} installed \u2192 ${fullPath}`);
40099
- })
40100
- );
40101
- }
40102
- async function installPlugin(storage, pluginVersion) {
40103
- if (!await storage.exists(".claude")) {
40104
- await storage.mkdir(".claude");
40105
- }
40106
- await Promise.all([
40107
- installFiles(storage, SKILLS_BASE, SKILLS, pluginVersion, "skill"),
40108
- installFiles(storage, RULES_BASE, RULES, pluginVersion, "rule"),
40109
- installFiles(storage, AGENTS_BASE, AGENTS, pluginVersion, "agent"),
40110
- installHooks(storage)
40111
- ]);
40112
- await installClaudeMdSection(storage, pluginVersion);
40113
- await cleanupOldSkills(storage);
40114
- }
40115
- async function installHooks(storage) {
40116
- if (!await storage.exists(HOOKS_BASE)) {
40117
- await storage.mkdir(HOOKS_BASE);
40118
- }
40119
- await Promise.all(
40120
- Object.entries(HOOKS).map(
40121
- ([name, content]) => storage.writeFile(`${HOOKS_BASE}/${name}`, content)
40122
- )
40123
- );
40124
- await installHooksConfig(storage);
40125
- }
40126
- async function installHooksConfig(storage) {
40127
- const settingsPath = ".claude/settings.json";
40128
- let settings = {};
40129
- if (await storage.exists(settingsPath)) {
40130
- const content = await storage.readFile(settingsPath);
40131
- if (content) {
40132
- try {
40133
- settings = JSON.parse(content);
40134
- } catch {
40135
- return;
40136
- }
40137
- }
40138
- }
40139
- const hooks = settings.hooks ?? {};
40140
- let changed = false;
40141
- for (const [event, entries] of Object.entries(HOOKS_CONFIG)) {
40142
- const existing = hooks[event];
40143
- const alreadyInstalled = existing?.some(
40144
- (entry) => entry.hooks?.some((h) => h.command?.includes(".claude/hooks/"))
40145
- );
40146
- if (!alreadyInstalled) {
40147
- hooks[event] = [...existing ?? [], ...entries];
40148
- changed = true;
40149
- }
40150
- }
40151
- if (changed) {
40152
- settings.hooks = hooks;
40153
- await storage.writeFile(settingsPath, JSON.stringify(settings, null, " ") + "\n");
40154
- console.log("Oh My TIL: hooks config registered \u2192 .claude/settings.json");
40155
- }
40156
- }
40157
- async function installClaudeMdSection(storage, pluginVersion) {
40158
- const filePath = ".claude/CLAUDE.md";
40159
- const markerStart = `${MCP_MARKER_START}:${pluginVersion}`;
40160
- const section = `${markerStart}
40161
- ${claude_md_section_default}
40162
- ${MCP_MARKER_END}`;
40163
- if (!await storage.exists(".claude")) {
40164
- await storage.mkdir(".claude");
40165
- }
40166
- if (await storage.exists(filePath)) {
40167
- const existing = await storage.readFile(filePath);
40168
- const existingContent = existing ?? "";
40169
- if (existingContent.includes(markerStart))
40170
- return;
40171
- if (existingContent.includes(MCP_MARKER_START)) {
40172
- const replaced = existingContent.replace(
40173
- new RegExp(`${escapeRegExp(MCP_MARKER_START)}[\\s\\S]*?${escapeRegExp(MCP_MARKER_END)}`),
40174
- section
40175
- );
40176
- await storage.writeFile(filePath, replaced);
40177
- } else {
40178
- await storage.writeFile(filePath, existingContent.trimEnd() + "\n\n" + section + "\n");
40179
- }
40180
- } else {
40181
- await storage.writeFile(filePath, section + "\n");
40182
- }
40183
- console.log("Oh My TIL: MCP tools guide added to CLAUDE.md");
40184
- }
40185
- async function cleanupOldSkills(storage) {
40186
- const oldPaths = ["til/SKILL.md", "backlog/SKILL.md", "research/SKILL.md"];
40187
- for (const relativePath of oldPaths) {
40188
- const oldPath = `${OLD_SKILLS_BASE}/${relativePath}`;
40189
- if (!await storage.exists(oldPath))
40190
- continue;
40191
- const content = await storage.readFile(oldPath);
40192
- const version2 = extractPluginVersion(content ?? "");
40193
- if (version2) {
40194
- await storage.remove(oldPath);
40195
- console.log(`Oh My TIL: old skill removed \u2192 ${oldPath}`);
40196
- }
40197
- }
40198
- }
40199
-
40200
38894
  // src/cli/obsidian-install.ts
40201
- var path2 = __toESM(require("path"));
40202
- var fs2 = __toESM(require("fs"));
38895
+ var path3 = __toESM(require("path"));
38896
+ var fs3 = __toESM(require("fs"));
40203
38897
  var import_child_process = require("child_process");
40204
38898
  var PLUGIN_ARTIFACTS = ["main.js", "manifest.json", "styles.css", "migrate-links.mjs"];
40205
38899
  var VERSION_PATTERN = /^\d+\.\d+\.\d+(-\S+)?$/;
40206
38900
  function getPluginArtifacts(packageRoot) {
40207
- return PLUGIN_ARTIFACTS.map((f) => path2.join(packageRoot, f));
38901
+ return PLUGIN_ARTIFACTS.map((f) => path3.join(packageRoot, f));
40208
38902
  }
40209
38903
  function isValidVersion(v) {
40210
38904
  return VERSION_PATTERN.test(v);
@@ -40240,7 +38934,7 @@ function detectElectronVersion(override) {
40240
38934
  if (envVersion && isValidVersion(envVersion))
40241
38935
  return envVersion;
40242
38936
  const plist = "/Applications/Obsidian.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Info.plist";
40243
- if (fs2.existsSync(plist)) {
38937
+ if (fs3.existsSync(plist)) {
40244
38938
  try {
40245
38939
  const output = (0, import_child_process.execFileSync)(
40246
38940
  "/usr/libexec/PlistBuddy",
@@ -40255,12 +38949,12 @@ function detectElectronVersion(override) {
40255
38949
  return null;
40256
38950
  }
40257
38951
  function installObsidianPlugin(vaultPath, packageRoot, options) {
40258
- const pluginDir = path2.join(vaultPath, ".obsidian", "plugins", "oh-my-til");
38952
+ const pluginDir = path3.join(vaultPath, ".obsidian", "plugins", "oh-my-til");
40259
38953
  const warnings = [];
40260
38954
  let rebuilt = false;
40261
38955
  const artifacts = getPluginArtifacts(packageRoot);
40262
38956
  for (const artifact of artifacts) {
40263
- if (!fs2.existsSync(artifact)) {
38957
+ if (!fs3.existsSync(artifact)) {
40264
38958
  return {
40265
38959
  success: false,
40266
38960
  pluginDir,
@@ -40269,14 +38963,14 @@ function installObsidianPlugin(vaultPath, packageRoot, options) {
40269
38963
  };
40270
38964
  }
40271
38965
  }
40272
- fs2.mkdirSync(pluginDir, { recursive: true });
38966
+ fs3.mkdirSync(pluginDir, { recursive: true });
40273
38967
  for (const artifact of artifacts) {
40274
- const dest = path2.join(pluginDir, path2.basename(artifact));
40275
- fs2.copyFileSync(artifact, dest);
38968
+ const dest = path3.join(pluginDir, path3.basename(artifact));
38969
+ fs3.copyFileSync(artifact, dest);
40276
38970
  }
40277
- const pkgJsonPath = path2.join(pluginDir, "package.json");
40278
- if (!fs2.existsSync(pkgJsonPath)) {
40279
- fs2.writeFileSync(pkgJsonPath, buildPluginPackageJson());
38971
+ const pkgJsonPath = path3.join(pluginDir, "package.json");
38972
+ if (!fs3.existsSync(pkgJsonPath)) {
38973
+ fs3.writeFileSync(pkgJsonPath, buildPluginPackageJson());
40280
38974
  }
40281
38975
  try {
40282
38976
  (0, import_child_process.execFileSync)("npm", ["install", "--omit=dev"], {
@@ -40299,19 +38993,19 @@ function installObsidianPlugin(vaultPath, packageRoot, options) {
40299
38993
  );
40300
38994
  return { success: true, pluginDir, warnings, rebuilt: false };
40301
38995
  }
40302
- const versionFile = path2.join(pluginDir, ".electron-version");
40303
- const cachedVersion = fs2.existsSync(versionFile) ? fs2.readFileSync(versionFile, "utf-8").trim() : null;
38996
+ const versionFile = path3.join(pluginDir, ".electron-version");
38997
+ const cachedVersion = fs3.existsSync(versionFile) ? fs3.readFileSync(versionFile, "utf-8").trim() : null;
40304
38998
  if (!needsRebuild(electronVersion, cachedVersion)) {
40305
38999
  return { success: true, pluginDir, warnings, rebuilt: false };
40306
39000
  }
40307
39001
  try {
40308
- const ptyModulePath = path2.join(pluginDir, "node_modules", "node-pty");
39002
+ const ptyModulePath = path3.join(pluginDir, "node_modules", "node-pty");
40309
39003
  (0, import_child_process.execFileSync)("npx", ["@electron/rebuild", "-m", ptyModulePath, "-v", electronVersion], {
40310
39004
  cwd: pluginDir,
40311
39005
  stdio: ["pipe", "pipe", "pipe"],
40312
39006
  encoding: "utf-8"
40313
39007
  });
40314
- fs2.writeFileSync(versionFile, electronVersion);
39008
+ fs3.writeFileSync(versionFile, electronVersion);
40315
39009
  rebuilt = true;
40316
39010
  } catch (err) {
40317
39011
  warnings.push(
@@ -40324,8 +39018,8 @@ function installObsidianPlugin(vaultPath, packageRoot, options) {
40324
39018
  }
40325
39019
 
40326
39020
  // src/core/cli.ts
40327
- var path3 = __toESM(require("path"));
40328
- var os = __toESM(require("os"));
39021
+ var path4 = __toESM(require("path"));
39022
+ var os2 = __toESM(require("os"));
40329
39023
  var VALUE_OPTIONS = /* @__PURE__ */ new Set(["port", "til-path", "out", "title", "subtitle", "github", "mode"]);
40330
39024
  var BOOLEAN_OPTIONS = /* @__PURE__ */ new Set(["no-obsidian"]);
40331
39025
  function parseArgs(args) {
@@ -40345,7 +39039,7 @@ function parseArgs(args) {
40345
39039
  }
40346
39040
  function expandTilde(p) {
40347
39041
  if (p === "~" || p.startsWith("~/")) {
40348
- return path3.join(os.homedir(), p.slice(1));
39042
+ return path4.join(os2.homedir(), p.slice(1));
40349
39043
  }
40350
39044
  return p;
40351
39045
  }
@@ -41342,26 +40036,25 @@ function generateProfileHtml(config2, summaryCardsHtml, heatmapHtml, recentTilsH
41342
40036
  }
41343
40037
 
41344
40038
  // src/cli/index.ts
41345
- var path5 = __toESM(require("path"));
41346
- var fs4 = __toESM(require("fs"));
41347
- var VERSION = true ? "1.1.2" : "0.0.0";
40039
+ var path6 = __toESM(require("path"));
40040
+ var fs5 = __toESM(require("fs"));
40041
+ var VERSION = true ? "1.3.1-dev.0" : "0.0.0";
41348
40042
  function printUsage() {
41349
40043
  console.log(`oh-my-til v${VERSION}
41350
40044
 
41351
40045
  Usage:
41352
- oh-my-til init [<path>] [options] Install skills, rules, and CLAUDE.md
41353
- oh-my-til serve [<path>] [options] Start MCP server (HTTP)
41354
40046
  oh-my-til mcp [<path>] [options] Start MCP server (stdio)
41355
40047
  oh-my-til install-obsidian [<path>] Install Obsidian desktop plugin only
41356
40048
  oh-my-til deploy [<path>] [options] Generate static site from TIL files
40049
+ oh-my-til config get Show current global config
40050
+ oh-my-til config set <key> <value> Set a config value
41357
40051
  oh-my-til version Print version
41358
40052
 
41359
- Options (init):
41360
- --no-obsidian Skip Obsidian plugin installation
41361
-
41362
- Options (serve):
41363
- --til-path <path> TIL folder path (default: til)
41364
- --port <port> MCP server port (default: 22360)
40053
+ Config keys:
40054
+ vault TIL vault path (e.g. ~/my-til)
40055
+ ai.provider AI provider: anthropic | openai | ollama
40056
+ ai.model AI model name
40057
+ ai.apiKey AI API key (stored with chmod 600)
41365
40058
 
41366
40059
  Options (mcp):
41367
40060
  --til-path <path> TIL folder path (default: til)
@@ -41396,58 +40089,11 @@ async function main() {
41396
40089
  const parsed = parseArgs(args.slice(1));
41397
40090
  const rawPath = parsed.positional[0];
41398
40091
  const envPath = process.env["TIL_VAULT_PATH"];
41399
- const basePath = path5.resolve(
40092
+ const basePath = path6.resolve(
41400
40093
  rawPath ? expandTilde(rawPath) : envPath ? expandTilde(envPath) : process.cwd()
41401
40094
  );
41402
40095
  const tilPath = parsed.options["til-path"] ?? "til";
41403
- const port = parseInt(parsed.options["port"] ?? "22360", 10);
41404
- if (isNaN(port) || port < 1 || port > 65535) {
41405
- console.error(`Invalid port: ${parsed.options["port"]}`);
41406
- process.exit(1);
41407
- }
41408
- if (command === "init") {
41409
- if (!fs4.existsSync(basePath)) {
41410
- fs4.mkdirSync(basePath, { recursive: true });
41411
- console.log(`Created directory: ${basePath}`);
41412
- }
41413
- const storage = new FsStorage(basePath);
41414
- console.log(`Initializing oh-my-til in ${basePath}...`);
41415
- await installPlugin(storage, VERSION);
41416
- console.log("\nInstalled:");
41417
- console.log(" - .claude/skills/ (8 skills)");
41418
- console.log(" - .claude/rules/ (1 rule)");
41419
- console.log(" - .claude/CLAUDE.md (MCP section)");
41420
- console.log(`
41421
- To start MCP server: oh-my-til serve ${basePath}`);
41422
- console.log(`To register with Claude Code: claude mcp add --transport http oh-my-til http://localhost:${port}/mcp`);
41423
- const obsidianDir = path5.join(basePath, ".obsidian");
41424
- if (parsed.options["no-obsidian"]) {
41425
- console.log("\nObsidian plugin installation skipped (--no-obsidian).");
41426
- } else if (fs4.existsSync(obsidianDir)) {
41427
- console.log("\nObsidian vault detected. Installing plugin...");
41428
- const packageRoot = path5.resolve(__dirname, "..");
41429
- const result = installObsidianPlugin(basePath, packageRoot);
41430
- if (result.success) {
41431
- console.log(` Plugin installed: ${result.pluginDir}`);
41432
- if (result.rebuilt) {
41433
- console.log(" node-pty rebuilt for Electron.");
41434
- }
41435
- for (const w of result.warnings) {
41436
- console.warn(` Warning: ${w}`);
41437
- }
41438
- console.log(" Restart Obsidian or reload the plugin to activate.");
41439
- } else {
41440
- console.error(" Plugin installation failed:");
41441
- for (const w of result.warnings) {
41442
- console.error(` ${w}`);
41443
- }
41444
- console.log(" You can install manually:");
41445
- console.log(" https://github.com/SongYunSeop/oh-my-til#option-b-obsidian-plugin");
41446
- }
41447
- } else {
41448
- console.log("\nUsing Obsidian? Run init inside your vault to auto-install the plugin.");
41449
- }
41450
- } else if (command === "mcp") {
40096
+ if (command === "mcp") {
41451
40097
  const storage = new FsStorage(basePath);
41452
40098
  const metadata = new FsMetadata(basePath);
41453
40099
  const mcpServer = new McpServer({
@@ -41465,33 +40111,14 @@ To start MCP server: oh-my-til serve ${basePath}`);
41465
40111
  };
41466
40112
  process.on("SIGINT", shutdown);
41467
40113
  process.on("SIGTERM", shutdown);
41468
- } else if (command === "serve") {
41469
- const storage = new FsStorage(basePath);
41470
- const metadata = new FsMetadata(basePath);
41471
- const server = new TILMcpServer(storage, metadata, port, tilPath, VERSION, {
41472
- onError: (msg) => console.error(`Error: ${msg}`)
41473
- });
41474
- process.on("SIGINT", async () => {
41475
- console.log("\nShutting down...");
41476
- await server.stop();
41477
- process.exit(0);
41478
- });
41479
- process.on("SIGTERM", async () => {
41480
- await server.stop();
41481
- process.exit(0);
41482
- });
41483
- await server.start();
41484
- console.log(`MCP server running on http://localhost:${port}/mcp`);
41485
- console.log(`TIL path: ${tilPath}`);
41486
- console.log("Press Ctrl+C to stop");
41487
40114
  } else if (command === "install-obsidian") {
41488
- const obsidianDir = path5.join(basePath, ".obsidian");
41489
- if (!fs4.existsSync(obsidianDir)) {
40115
+ const obsidianDir = path6.join(basePath, ".obsidian");
40116
+ if (!fs5.existsSync(obsidianDir)) {
41490
40117
  console.error("No .obsidian/ folder found. Run this command inside an Obsidian vault.");
41491
40118
  process.exit(1);
41492
40119
  }
41493
40120
  console.log("Installing Obsidian plugin...");
41494
- const packageRoot = path5.resolve(__dirname, "..");
40121
+ const packageRoot = path6.resolve(__dirname, "..");
41495
40122
  const result = installObsidianPlugin(basePath, packageRoot);
41496
40123
  if (result.success) {
41497
40124
  console.log(`Plugin installed: ${result.pluginDir}`);
@@ -41585,13 +40212,13 @@ To start MCP server: oh-my-til serve ${basePath}`);
41585
40212
  { title: entry.title, category: entry.category, createdDate: entry.createdDate, contentHtml: entry.contentHtml, relatedTils },
41586
40213
  config2
41587
40214
  );
41588
- await storage.writeFile(path5.join(outDir, entry.category, `${entry.slug}.html`), tilPageHtml);
40215
+ await storage.writeFile(path6.join(outDir, entry.category, `${entry.slug}.html`), tilPageHtml);
41589
40216
  generated++;
41590
40217
  }
41591
40218
  for (const [category, tils] of categoryMap) {
41592
40219
  tils.sort((a, b) => b.createdDate.localeCompare(a.createdDate));
41593
40220
  const catHtml = generateCategoryIndexHtml({ category, tils }, config2);
41594
- await storage.writeFile(path5.join(outDir, category, "index.html"), catHtml);
40221
+ await storage.writeFile(path6.join(outDir, category, "index.html"), catHtml);
41595
40222
  }
41596
40223
  const heatmapData = computeHeatmapData(statsEntries, deployTilPath, void 0, statsEntries);
41597
40224
  const streak = computeStreak(statsEntries, deployTilPath, void 0, statsEntries);
@@ -41617,9 +40244,11 @@ To start MCP server: oh-my-til serve ${basePath}`);
41617
40244
  const recentTilsHtml = renderRecentTilsHtml(recentTils);
41618
40245
  const allTilsHtml = renderAllTilsHtml(allCategories);
41619
40246
  const profileHtml = generateProfileHtml(config2, summaryCardsHtml, heatmapHtml, recentTilsHtml, allTilsHtml);
41620
- await storage.writeFile(path5.join(outDir, "index.html"), profileHtml);
40247
+ await storage.writeFile(path6.join(outDir, "index.html"), profileHtml);
41621
40248
  console.log(`Generated ${generated} TIL pages + ${categoryMap.size} category indexes + profile`);
41622
- console.log(`Output: ${path5.resolve(basePath, outDir)}/`);
40249
+ console.log(`Output: ${path6.resolve(basePath, outDir)}/`);
40250
+ } else if (command === "config") {
40251
+ runConfigCommand(args.slice(1));
41623
40252
  } else {
41624
40253
  console.error(`Unknown command: ${command}`);
41625
40254
  printUsage();